Ejemplo n.º 1
0
    def sdc_spinup(self, water, ll, cwd, rl, lnc):
        """SOIL POOLS SPINUP"""

        for x in range(100000):

            s_out = soil_dec.carbon3(self.soil_temp, water / self.wmax_mm, ll,
                                     cwd, rl, lnc, self.sp_csoil, self.sp_snc)

            soil_out = catch_out_carbon3(s_out)
            self.sp_csoil = soil_out['cs']
            self.sp_snc = soil_out['snc']
Ejemplo n.º 2
0
    def run_caete(self, start_date, end_date, spinup=0, fix_co2=None):
        """ start_date [str]   "yyyymmdd" Start model execution

            end_date   [str]   "yyyymmdd" End model execution

            spinup     [int]   Number of repetitions in spinup. 0 for no spinup

            fix_co2    [Float] Fixed value for ATM [CO2]
                       [int]   Fixed value for ATM [CO2]
                       [str]   "yyyy" Corresponding year of an ATM [CO2]

            This function run the fortran subroutines and manage data flux. It
            is the proper CAETÊ-DVM execution in the start_date - end_date period
        """

        assert self.filled, "The gridcell has no input data"
        assert not fix_co2 or type(
            fix_co2
        ) == str or fix_co2 > 0, "A fixed value for ATM[CO2] must be a positive number greater than zero or a proper string "

        def find_co2(year):
            for i in self.co2_data:
                if int(i.split('\t')[0]) == year:
                    return float(i.split('\t')[1].strip())

        def find_index(start, end):
            result = []
            num = np.arange(self.ssize)
            ind = np.arange(self.sind, self.eind + 1)
            for r, i in zip(num, ind):
                if i == start:
                    result.append(r)
            for r, i in zip(num, ind):
                if i == end:
                    result.append(r)
            return result

        # Define start and end dates (read actual arguments)
        start = cftime.real_datetime(int(start_date[:4]), int(start_date[4:6]),
                                     int(start_date[6:]))
        end = cftime.real_datetime(int(end_date[:4]), int(end_date[4:6]),
                                   int(end_date[6:]))
        # Check dates sanity
        assert start < end, "start > end"
        assert start >= self.start_date
        assert end <= self.end_date

        # Define time index
        start_index = int(cftime.date2num(start, self.time_unit,
                                          self.calendar))
        end_index = int(cftime.date2num(end, self.time_unit, self.calendar))

        lb, hb = find_index(start_index, end_index)
        steps = np.arange(lb, hb + 1)
        day_indexes = np.arange(start_index, end_index + 1)
        spin = 1 if spinup == 0 else spinup

        # Catch climatic input and make conversions
        temp = self.tas[lb:hb + 1] - 273.15  # ! K to °C
        prec = self.pr[lb:hb + 1] * 86400  # kg m-2 s-1 to  mm/day
        # transforamando de Pascal pra mbar (hPa)
        p_atm = self.ps[lb:hb + 1] * 0.01
        # W m-2 to mol m-2 s-1 ! 0.5 converts RSDS to PAR
        ipar = self.rsds[lb:hb + 1] * 0.5 / 2.18e5
        ru = self.rhs[lb:hb + 1] / 100.0

        year0 = start.year
        co2 = find_co2(year0)
        count_days = start.dayofyr - 2
        loop = 0
        next_year = 0.0

        fix_co2_p = False
        if fix_co2 is None:
            fix_co2_p = False
        elif type(fix_co2) == int or type(fix_co2) == float:
            co2 = fix_co2
            fix_co2_p = True
        elif type(fix_co2) == str:
            assert type(
                int(fix_co2)
            ) == int, "The string(\"yyyy\") for the fix_co2 argument must be an year between 1901-2016"
            co2 = find_co2(int(fix_co2))
            fix_co2_p = True

        for s in range(spin):
            self._allocate_output(steps.size)
            for step in range(steps.size):
                if fix_co2_p:
                    pass
                else:
                    loop += 1
                    count_days += 1
                    # CAST CO2 ATM CONCENTRATION
                    days = 366 if m.leap(year0) == 1 else 365
                    if count_days == days:
                        count_days = 0
                        year0 = cftime.num2date(day_indexes[step],
                                                self.time_unit,
                                                self.calendar).year
                        co2 = find_co2(year0)
                        next_year = (find_co2(year0 + 1) - co2) / days

                    elif loop == 1 and count_days < days:
                        year0 = start.year
                        next_year = (find_co2(year0 + 1) - co2) / \
                            (days - count_days)

                    co2 += next_year
                # if step == 0:
                #     #print('1st day')
                # Update soil temperature
                self.soil_temp = st.soil_temp(self.soil_temp, temp[step])

                # INFLATe VARS
                sto = np.zeros(shape=(3, npls), order='F')
                cleaf = np.zeros(npls, order='F')
                cwood = np.zeros(npls, order='F')
                croot = np.zeros(npls, order='F')
                dcl = np.zeros(npls, order='F')
                dca = np.zeros(npls, order='F')
                dcf = np.zeros(npls, order='F')
                uptk_costs = np.zeros(npls, order='F')

                sto[0, self.vp_lsid] = self.vp_sto[0, :]
                sto[1, self.vp_lsid] = self.vp_sto[1, :]
                sto[2, self.vp_lsid] = self.vp_sto[2, :]
                # Just Check the integrity of the data
                assert self.vp_lsid.size == self.vp_cleaf.size, 'different shapes'
                c = 0
                for n in self.vp_lsid:
                    cleaf[n] = self.vp_cleaf[c]
                    cwood[n] = self.vp_cwood[c]
                    croot[n] = self.vp_croot[c]
                    dcl[n] = self.vp_dcl[c]
                    dca[n] = self.vp_dca[c]
                    dcf[n] = self.vp_dcf[c]
                    uptk_costs[n] = self.sp_uptk_costs[c]
                    c += 1
                ton = self.sp_organic_n + self.sp_sorganic_n
                top = self.sp_organic_p + self.sp_sorganic_p
                out = model.daily_budget(
                    self.pls_table, self.wp_water_upper_mm,
                    self.wp_water_lower_mm, self.soil_temp, temp[step],
                    p_atm[step], ipar[step], ru[step], self.sp_available_n,
                    self.sp_available_p, ton, top, self.sp_organic_p, co2, sto,
                    cleaf, cwood, croot, dcl, dca, dcf, uptk_costs,
                    self.wmax_mm, step)

                del sto, cleaf, cwood, croot, dcl, dca, dcf, uptk_costs
                # Create a dict with the function output
                daily_output = catch_out_budget(out)

                self.vp_lsid = np.where(daily_output['ocpavg'] > 0.0)[0]
                self.vp_ocp = daily_output['ocpavg'][self.vp_lsid]
                self.ls[step] = self.vp_lsid.size

                # UPDATE STATE VARIABLES
                # WATER CWM
                self.runom[step] = self._update_pool(prec[step],
                                                     daily_output['evavg'])

                # UPDATE vegetation pools ! ABLE TO USE SPARSE MATRICES
                self.vp_cleaf = daily_output['cleafavg_pft'][self.vp_lsid]
                self.vp_cwood = daily_output['cawoodavg_pft'][self.vp_lsid]
                self.vp_croot = daily_output['cfrootavg_pft'][self.vp_lsid]
                self.vp_dcl = daily_output['delta_cveg'][0][self.vp_lsid]
                self.vp_dca = daily_output['delta_cveg'][1][self.vp_lsid]
                self.vp_dcf = daily_output['delta_cveg'][2][self.vp_lsid]
                self.vp_sto = daily_output['stodbg'][:, self.vp_lsid]
                self.sp_uptk_costs = daily_output['npp2pay'][self.vp_lsid]

                # Plant uptake and Carbon costs of nutrient uptake
                self.nupt[:, step] = daily_output['nupt']
                self.pupt[:, step] = daily_output['pupt']
                for i in range(3):
                    self.storage_pool[i, step] = np.sum(self.vp_ocp *
                                                        self.vp_sto[i])

                # OUTPUTS for SOIL CWM
                self.litter_l[step] = daily_output['litter_l']
                self.cwd[step] = daily_output['cwd']
                self.litter_fr[step] = daily_output['litter_fr']
                self.lnc[:, step] = daily_output['lnc']
                wtot = self.wp_water_upper_mm + self.wp_water_lower_mm
                s_out = soil_dec.carbon3(self.soil_temp, wtot / self.wmax_mm,
                                         self.litter_l[step], self.cwd[step],
                                         self.litter_fr[step], self.lnc[:,
                                                                        step],
                                         self.sp_csoil, self.sp_snc)

                soil_out = catch_out_carbon3(s_out)

                # Organic C N & P
                self.sp_csoil = soil_out['cs']
                self.sp_snc = soil_out['snc']

                # INCLUDE MINERALIZED NUTRIENTS
                self.sp_available_p += soil_out['pmin']
                self.sp_available_n += soil_out['nmin']

                # NUTRIENT DINAMICS
                # Inorganic N
                self.sp_in_n += self.sp_available_n + self.sp_so_n
                self.sp_so_n = soil_dec.sorbed_n_equil(self.sp_in_n)
                self.sp_available_n = soil_dec.solution_n_equil(self.sp_in_n)
                self.sp_in_n -= self.sp_so_n + self.sp_available_n

                # Inorganic P
                self.sp_in_p += self.sp_available_p + self.sp_so_p
                self.sp_so_p = soil_dec.sorbed_p_equil(self.sp_in_p)
                self.sp_available_p = soil_dec.solution_p_equil(self.sp_in_p)
                self.sp_in_p -= self.sp_so_p + self.sp_available_p

                # Sorbed P
                if self.pupt[1, step] > 0.05:
                    rwarn(
                        f"Puptk_SO > soP_max - 729 | in spin{s}, step{step} - {self.pupt[1, step]}"
                    )
                    self.pupt[1, step] = 0.0

                if self.pupt[1, step] > self.sp_so_p:
                    rwarn(
                        f"Puptk_SO > soP_pool - 731 | in spin{s}, step{step} - {self.pupt[1, step]}"
                    )

                self.sp_so_p -= self.pupt[1, step]

                t1 = np.all(self.sp_snc > 0.0)
                if not t1:
                    self.snc[np.where(self.snc < 0)] = 0.0
                # ORGANIC nutrients uptake
                # N
                if self.nupt[1, step] < 0.0:
                    rwarn(
                        f"NuptkO < 0 - 745 | in spin{s}, step{step} - {self.nupt[1, step]}"
                    )
                    self.nupt[1, step] = 0.0
                if self.nupt[1, step] > 0.8:
                    rwarn(
                        f"NuptkO  > max - 749 | in spin{s}, step{step} - {self.nupt[1, step]}"
                    )
                    self.nupt[1, step] = 0.0

                total_on = self.sp_snc[:4].sum()
                frsn = [i / total_on for i in self.sp_snc[:4]]
                for i, fr in enumerate(frsn):
                    self.sp_snc[i] -= self.nupt[1, step] * fr
                self.sp_organic_n = self.sp_snc[:2].sum()
                self.sp_sorganic_n = self.sp_snc[2:4].sum()

                # P
                if self.pupt[2, step] < 0.0:
                    rwarn(
                        f"PuptkO < 0 - 759 | in spin{s}, step{step} - {self.pupt[2, step]}"
                    )
                    self.pupt[2, step] = 0.0
                if self.pupt[2, step] > 0.1:
                    rwarn(
                        f"PuptkO  < max - 763 | in spin{s}, step{step} - {self.pupt[2, step]}"
                    )
                    self.pupt[2, step] = 0.0
                total_op = self.sp_snc[4:].sum()
                frsp = [i / total_op for i in self.sp_snc[4:]]
                for i, fr in enumerate(frsp):
                    self.sp_snc[i + 4] -= self.pupt[2, step] * fr
                self.sp_organic_p = self.sp_snc[4:6].sum()
                self.sp_sorganic_p = self.sp_snc[6:].sum()

                # Raise some warnings
                if self.sp_organic_n < 0.0:
                    rwarn(f"ON negative in spin{s}, step{step}")
                if self.sp_sorganic_n < 0.0:
                    rwarn(f"SON negative in spin{s}, step{step}")
                if self.sp_organic_p < 0.0:
                    rwarn(f"OP negative in spin{s}, step{step}")
                if self.sp_sorganic_p < 0.0:
                    rwarn(f"SOP negative in spin{s}, step{step}")

                # CALCULATE THE EQUILIBTIUM IN SOIL POOLS
                # Soluble and inorganic pools
                if self.pupt[0, step] > 2.5:
                    rwarn(
                        f"Puptk > max - 786 | in spin{s}, step{step} - {self.pupt[0, step]}"
                    )
                    self.pupt[0, step] = 0.0
                self.sp_available_p -= self.pupt[0, step]

                if self.nupt[0, step] > 2.5:
                    rwarn(
                        f"Nuptk > max - 792 | in spin{s}, step{step} - {self.nupt[0, step]}"
                    )
                    self.nupt[0, step] = 0.0
                self.sp_available_n -= self.nupt[0, step]

                # END SOIL NUTRIENT DYNAMICS

                # # # Process (cwm) & store (np.array) outputs
                self.carbon_costs[self.vp_lsid, step] = self.sp_uptk_costs
                self.emaxm.append(daily_output['epavg'])
                self.tsoil.append(self.soil_temp)
                self.photo[step] = daily_output['phavg']
                self.aresp[step] = daily_output['aravg']
                self.npp[step] = daily_output['nppavg']
                self.lai[step] = daily_output['laiavg']
                self.rcm[step] = daily_output['rcavg']
                self.f5[step] = daily_output['f5avg']
                self.evapm[step] = daily_output['evavg']
                self.wsoil[step] = self.wp_water_upper_mm
                self.swsoil[step] = self.wp_water_lower_mm
                self.rm[step] = daily_output['rmavg']
                self.rg[step] = daily_output['rgavg']
                self.wue[step] = daily_output['wueavg']
                self.cue[step] = daily_output['cueavg']
                self.cdef[step] = daily_output['c_defavg']
                self.vcmax[step] = daily_output['vcmax']
                self.specific_la[step] = daily_output['specific_la']
                self.cleaf[step] = daily_output['cp'][0]
                self.cawood[step] = daily_output['cp'][1]
                self.cfroot[step] = daily_output['cp'][2]
                self.hresp[step] = soil_out['hr']
                self.csoil[:, step] = soil_out['cs']
                self.inorg_n[step] = self.sp_in_n
                self.inorg_p[step] = self.sp_in_p
                self.sorbed_n[step] = self.sp_so_n
                self.sorbed_p[step] = self.sp_so_p
                self.snc[:, step] = soil_out['snc']
                self.nmin[step] = self.sp_available_n
                self.pmin[step] = self.sp_available_p
                self.area[self.vp_lsid, step] = self.vp_ocp
                self.lim_status[:, self.vp_lsid, step] = daily_output[
                    'limitation_status'][:, self.vp_lsid]
                self.uptake_strategy[:, self.vp_lsid, step] = daily_output[
                    'uptk_strat'][:, self.vp_lsid]

            if s > 0:
                while True:
                    if sv.is_alive():
                        sleep(0.5)
                    else:
                        break

            self.flush_data = self._flush_output('spin',
                                                 (start_index, end_index))
            sv = Thread(target=self._save_output, args=(self.flush_data, ))
            sv.start()

        while True:
            if sv.is_alive():
                sleep(0.5)
            else:
                break
        return None
Ejemplo n.º 3
0
from caete_module import soil_dec as funcs
from caete_module import global_par as gp


def zeroes(*args):
    return np.zeros(shape=args, dtype=np.float32)


cl = zeroes(2) + 0.01
cs = zeroes(3) + 0.01
nmin = zeroes(1) + 0.02
plab = zeroes(1) + 0.003
lnr = zeroes(6) + np.random.random(6, ) * 0.001
header = ['hr', 'cl1', 'cl2', 'cs1', 'cs2', 'cs3']

#   subroutine carbon3(tsoil,leaf_l,cwd,root_l,lnr,cl,cs,cl_out,cs_out,hr)
# tsoil, leaf_l, cwd, root_l, lnr, cl, cs, cl_out, cs_out, hr
with open('carbon3_test.csv', 'w') as fh:
    CSV_WRITER = csv.writer(fh, delimiter=',')
    CSV_WRITER.writerow(header)
    for x in range(100000):
        df = funcs.carbon3(20, 0.1, 0.1, 0.1, lnr, cl, cs)
        line = [df[-1], df[0][0], df[0][1], df[1][0], df[1][1], df[1][2]]
        CSV_WRITER.writerow(line)
        cl = df[0][:]
        cs = df[1][:]

data = pd.read_csv('carbon3_test.csv')
os.system('rm -rf carbon3_test.csv')