예제 #1
0
class GrossGrowthEfficiency:
    """
    to N: beta*(1-epsilon)
    to D: 1-beta
    to Z: beta*epsilon
    """
    assimilated_consumer = phydra.variable(foreign=True, flux='assimilation')
    egested_detritus = phydra.variable(foreign=True, flux='egestion')
    excreted_nutrient = phydra.variable(foreign=True, flux='excretion')

    beta = phydra.parameter(description='absorption efficiency')
    epsilon = phydra.parameter(description='net production efficiency')

    @phydra.flux(group_to_arg='graze_out')
    def assimilation(self, assimilated_consumer, egested_detritus,
                     excreted_nutrient, graze_out, beta, epsilon):
        return self.m.sum(graze_out) * beta * epsilon

    @phydra.flux(group_to_arg='graze_out')
    def egestion(self, assimilated_consumer, egested_detritus,
                 excreted_nutrient, graze_out, beta, epsilon):
        return self.m.sum(graze_out) * (1 - beta)

    @phydra.flux(group_to_arg='graze_out')
    def excretion(self, assimilated_consumer, egested_detritus,
                  excreted_nutrient, graze_out, beta, epsilon):
        return self.m.sum(graze_out) * beta * (1 - epsilon)
예제 #2
0
class HollingTypeIII:
    resource = phydra.variable(foreign=True, flux='grazing', negative=True)
    consumer = phydra.variable(foreign=True, flux='grazing', negative=False)
    feed_pref = phydra.parameter(description='feeding preferences')
    Imax = phydra.parameter(description='maximum ingestion rate')
    kZ = phydra.parameter(description='feeding preferences')

    @phydra.flux
    def grazing(self, resource, consumer, feed_pref, Imax, kZ):
        return Imax * resource ** 2 \
               * feed_pref / (kZ ** 2 + self.m.sum([resource ** 2 * feed_pref])) * consumer
예제 #3
0
파일: growth.py 프로젝트: ben1post/phydra
class MonodGrowth_mu_ConsumerDim:
    resource = phydra.variable(foreign=True, flux='uptake', negative=True)
    consumer = phydra.variable(foreign=True,
                               dims='var',
                               flux='uptake',
                               negative=False)  # dims='var',

    halfsat = phydra.parameter(
        dims='var', description='half-saturation constant')  # dims='var'
    mu_max = phydra.parameter(dims='var', description='maximum growth rate')

    @phydra.flux(dims='var')
    def uptake(self, resource, consumer, halfsat, mu_max):
        return mu_max * resource / (resource + halfsat) * consumer
예제 #4
0
class EMPOWER_Monod_ML:
    """ """
    resource = phydra.variable(foreign=True)
    halfsat = phydra.parameter(description='monod half-saturation constant')

    @phydra.flux(group='growth_lims')
    def monod_lim(self, resource, halfsat):
        return resource / (resource + halfsat)
예제 #5
0
class SizebasedGrazingKernel_Dims:
    """ ASTroCAT Grazing Kernel """
    resource = phydra.variable(foreign=True, dims='resource')
    consumer = phydra.variable(foreign=True, dims='consumer')
    phiP = phydra.parameter(dims=('resource', 'consumer'),
                            description='feeding preferences')
    Imax = phydra.parameter(dims='consumer',
                            description='maximum ingestion rate')
    KsZ = phydra.parameter(description='half sat of grazing')

    @phydra.flux(group='graze_matrix', dims=('resource', 'consumer'))
    def grazing(self, resource, consumer, phiP, Imax, KsZ):
        """ """
        PscaledAsFood = phiP / KsZ * resource[:, None]
        FgrazP = Imax * consumer * PscaledAsFood / (
            1 + self.m.sum(PscaledAsFood, axis=0))
        return FgrazP
예제 #6
0
파일: forcings.py 프로젝트: ben1post/phydra
class GlobalSlabClimatologyForcing:
    forcing = phydra.forcing(foreign=False, setup_func='forcing_setup')
    dataset = phydra.parameter(description="Options: 'n0x', 'mld', 'tmld', 'par'")
    lat = phydra.parameter(description='constant value of forcing')
    lon = phydra.parameter(description='constant value of forcing')
    rbb = phydra.parameter(description='constant value of forcing')
    smooth = phydra.parameter(description='smoothing conditions, larger values = stronger smoothing')
    k = phydra.parameter(description='The degree of the spline fit')
    deriv = phydra.parameter(description='order of derivative to store, for basic forcing pass 0')

    def forcing_setup(self, dataset, lat, lon, rbb, smooth, k, deriv):
        data = ClimatologyForcing(lat, lon, rbb, dataset).outForcing

        dayspermonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        dpm = dayspermonth
        dpm_cumsum = np.cumsum(dpm) - np.array(dpm) / 2

        time = np.concatenate([[0], dpm_cumsum, [365]], axis=None)

        boundary_int = [(data[0] + data[-1]) / 2]
        dat = np.concatenate([boundary_int, data, boundary_int], axis=None)

        spl = intrp.splrep(time, dat, per=True, k=k, s=smooth)

        def forcing(time):
            return intrp.splev(np.mod(time, 365), spl, der=deriv)

        return forcing
예제 #7
0
class SlabSinking:
    """ """
    var = phydra.variable(foreign=True, flux='sinking', negative=True)
    mld = phydra.forcing(foreign=True)
    rate = phydra.parameter(description='sinking rate, units: m d^-1')

    @phydra.flux
    def sinking(self, var, rate, mld):
        return var * rate / mld
예제 #8
0
class Eppley_ML:
    """ """
    temp = phydra.forcing(foreign=True, description='Temperature forcing')

    eppley_exp = phydra.parameter(description='eppley exponent')

    @phydra.flux(group='growth_lims')
    def eppley_growth(self, temp, eppley_exp):
        return self.m.exp(eppley_exp * temp)
예제 #9
0
class EMPOWER_Eppley_ML:
    """ """
    temp = phydra.forcing(foreign=True, description='Temperature forcing')

    VpMax = phydra.parameter(
        description='Maximum photosynthetic rate at 0 degrees celcius')

    @phydra.flux(group='VpT')
    def temp_dependence(self, temp, VpMax):
        return VpMax * 1.066**temp
예제 #10
0
class HollingTypeIII_ResourcesListInput_Consumption2Group:
    """
    """
    resources = phydra.variable(foreign=True,
                                negative=True,
                                flux='grazing',
                                list_input=True,
                                dims='resources')
    consumer = phydra.variable(foreign=True)
    feed_prefs = phydra.parameter(
        dims='resources', description='feeding preference for resources')
    Imax = phydra.parameter(description='maximum ingestion rate')
    kZ = phydra.parameter(description='feeding preferences')

    @phydra.flux(group='graze_out', dims='resources')
    def grazing(self, resources, consumer, feed_prefs, Imax, kZ):
        scaled_resources = resources**2 * feed_prefs
        return scaled_resources * Imax / (
            kZ**2 + self.m.sum(scaled_resources)) * consumer
예제 #11
0
class Steele_ML:
    """ """
    pigment_biomass = phydra.variable(foreign=True)

    i_0 = phydra.forcing(foreign=True, description='Light forcing')
    mld = phydra.forcing(foreign=True, description='Mixed Layer Depth forcing')

    i_opt = phydra.parameter(description='Optimal irradiance of consumer')
    kw = phydra.parameter(description='light attenuation coef for water')
    kc = phydra.parameter(
        description='light attenuation coef for pigment biomass')

    @phydra.flux(group='growth_lims')
    def steele_light_lim(self, i_0, mld, pigment_biomass, i_opt, kw, kc):
        kPAR = kw + kc * pigment_biomass
        light_lim = 1. / (kPAR *
                          mld) * (-self.m.exp(1. - i_0 / i_opt) - (-self.m.exp(
                              (1. - (i_0 * self.m.exp(-kPAR * mld)) / i_opt))))
        return light_lim
예제 #12
0
class Mixing_K:
    """ pre-computes K to be used in all mixing processes """
    mld = phydra.forcing(foreign=True)
    mld_deriv = phydra.forcing(foreign=True)

    kappa = phydra.parameter(description='constant mixing coefficient')

    @phydra.flux(group='mixing_K')
    def mixing(self, mld, mld_deriv, kappa):
        return (self.m.max(mld_deriv, 0) + kappa) / mld
예제 #13
0
class Monod_ML_ConsumerDim:
    """ """
    resource = phydra.variable(foreign=True)
    halfsat = phydra.parameter(dims='vars',
                               description='monod half-saturation constant')

    @phydra.flux(dims='vars', group='growth_lims')
    def monod_lim(self, resource, halfsat):
        #print("in monod lim", resource, halfsat)
        #print(resource.value.ndim)
        return resource / (resource + halfsat)
예제 #14
0
파일: growth.py 프로젝트: ben1post/phydra
class MonodGrowth:
    resource = phydra.variable(foreign=True, flux='uptake', negative=True)
    consumer = phydra.variable(foreign=True, flux='uptake',
                               negative=False)  # dims='var',

    halfsat = phydra.parameter(
        description='half-saturation constant')  # dims='var'

    @phydra.flux
    def uptake(self, resource, consumer, halfsat):
        return resource / (resource + halfsat) * consumer
예제 #15
0
class LinearExchange_SourceDim:
    """ """
    source = phydra.variable(foreign=True,
                             dims='var',
                             flux='decay',
                             negative=True)
    sink = phydra.variable(foreign=True, flux='decay', negative=False)
    rate = phydra.parameter(description='decay/mortality rate')

    @phydra.flux(dims='var')
    def decay(self, source, sink, rate):
        return source * rate
예제 #16
0
class SubFlux:
    var = phydra.variable(foreign=True)
    rate = phydra.parameter()

    @phydra.flux(group='X_growth')
    def one_growth(self, var, rate):
        # print(var)
        return var * rate

    @phydra.flux(group='X_growth')
    def two_growth(self, var, rate):
        return - var * rate
예제 #17
0
class EMPOWER_Growth_ML:
    """ XXX
    """
    resource = phydra.variable(foreign=True, flux='growth', negative=True)
    consumer = phydra.variable(foreign=True, flux='growth', negative=False)

    mu_max = phydra.parameter(description='maximum growth rate')

    @phydra.flux(group_to_arg='growth_lims')
    def growth(self, resource, consumer, mu_max, growth_lims):
        # print("in growth flux func now", resource, consumer, mu_max, growth_lims)
        return mu_max * self.m.product(growth_lims) * consumer
예제 #18
0
class Growth_Monod_Eppley_Steele:
    resource = phydra.variable(foreign=True, flux='growth', negative=True)
    consumer = phydra.variable(foreign=True, flux='growth', negative=False)

    Temp = phydra.forcing(foreign=True, description='Temperature forcing')
    Light = phydra.forcing(foreign=True, description='Light forcing')
    MLD = phydra.forcing(foreign=True, description='Mixed Layer Depth forcing')

    halfsat = phydra.parameter(description='monod half-saturation constant')
    eppley = phydra.parameter(description='eppley exponent')

    i_opt = phydra.parameter(description='Optimal irradiance of consumer')
    µ_max = phydra.parameter(description='maximum growth rate')

    kw = phydra.parameter(description='light attenuation coef for water')
    kc = phydra.parameter(description='light attenuation coef for consumer')

    @phydra.flux
    def growth(self, resource, consumer, Temp, Light, MLD, i_opt, kw, kc, eppley, halfsat, µ_max):
        temp_lim = self.m.exp(eppley * Temp)
        monod_lim = resource / (resource + halfsat)
        kPAR = kw + kc * consumer
        light_lim = 1. / (kPAR * MLD) * (
                -self.m.exp(1. - Light / i_opt) - (
            -self.m.exp((1. - (Light * self.m.exp(-kPAR * MLD)) / i_opt))))

        return µ_max * temp_lim * monod_lim * light_lim * consumer
예제 #19
0
class LinearForcingInput:
    var = phydra.variable(foreign=True,
                          flux='input',
                          negative=False,
                          description='variable affected by flux')
    forcing = phydra.forcing(foreign=True,
                             description='forcing affecting flux')
    rate = phydra.parameter(description='linear rate of change')

    @phydra.flux
    def input(self, var, forcing, rate):
        """ """
        return forcing * rate
예제 #20
0
class ExponentialGrowth_Dim:
    """ """
    var = phydra.variable(foreign=True,
                          dims='var',
                          flux='growth',
                          negative=False,
                          description='variable affected by flux')
    rate = phydra.parameter(description='linear rate of change')

    @phydra.flux(dims='var')
    def growth(self, var, rate):
        """ """
        return var * rate
예제 #21
0
class QuadraticExchange_SourceDim:
    """ """
    source = phydra.variable(foreign=True,
                             dims='var',
                             flux='decay',
                             negative=True)
    sink = phydra.variable(foreign=True, flux='decay', negative=False)
    rate = phydra.parameter(description='quadratic rate of change')

    @phydra.flux(dims='var')
    def decay(self, source, sink, rate):
        """ """
        return source**2 * rate
예제 #22
0
class QuadraticDecay_Dim:
    """ """
    var = phydra.variable(foreign=True,
                          dims='var',
                          flux='decay',
                          negative=True,
                          description='variable affected by flux')
    rate = phydra.parameter(description='quadratic rate of change')

    @phydra.flux(dims='var')
    def decay(self, var, rate):
        """ """
        return var**2 * rate
예제 #23
0
class LinearDecay_VarDim:
    """ """
    var = phydra.variable(dims='var',
                          foreign=True,
                          flux='decay',
                          negative=True,
                          description='variable affected by flux')
    rate = phydra.parameter(description='linear rate of decay/mortality')

    @phydra.flux(dims='var')
    def decay(self, var, rate):
        """ """
        return var * rate
예제 #24
0
class LinearInput_Dim:
    """ """
    var = phydra.variable(foreign=True,
                          dims='var',
                          flux='input',
                          negative=False,
                          description='variable affected by flux')
    rate = phydra.parameter(dims='var', description='linear rate of change')

    @phydra.flux(dims='var')
    def input(self, var, rate):
        """ """
        return rate
예제 #25
0
파일: forcings.py 프로젝트: ben1post/phydra
class SinusoidalForcing:
    forcing = phydra.forcing(foreign=False, setup_func='forcing_setup')
    period = phydra.parameter(description='period of sinusoidal forcing')

    def forcing_setup(self, period):
        cwd = os.getcwd()
        print("forcing function is in directory:", cwd)

        @np.vectorize
        def forcing(time):
            return np.cos(time / period * 2 * np.pi) + 1

        return forcing
예제 #26
0
파일: forcings.py 프로젝트: ben1post/phydra
class NoonPARfromLat:
    """ Component that calculates Photosynthetically Active Radiation (PAR) from Latitude"""

    NoonPAR = phydra.forcing(setup_func='calcNoonPAR', description='calculated PAR from Irradiance',
                             attrs={'unit': 'W m^-2'})

    station = phydra.parameter(description="name of station, options: 'india', 'biotrans', 'kerfix', 'papa'")

    def calcNoonPAR(self, station):
        """ Function adapted from EMPOWER model (Anderson et al. 2015)"""

        def noon_PAR_calc(jday, latradians, clouds, e0):
            albedo = 0.04  # albedo
            solarconst = 1368.0  # solar constant, w m-2
            parrac = 0.43  # PAR fraction
            declin = 23.45 * np.sin(2 * np.pi * (284 + jday) * 0.00274) * np.pi / 180  # solar declination angle
            coszen = np.sin(latradians) * np.sin(declin) + np.cos(latradians) * np.cos(declin)  # cosine of zenith angle
            zen = np.arccos(coszen) * 180 / np.pi  # zenith angle, degrees
            Rvector = 1 / np.sqrt(1 + 0.033 * np.cos(2 * np.pi * jday * 0.00274))  # Earth's radius vector
            Iclear = solarconst * coszen ** 2 / (Rvector ** 2) / (
                        1.2 * coszen + e0 * (1.0 + coszen) * 0.001 + 0.0455)  # irradiance at ocean surface, clear sky
            cfac = (1 - 0.62 * clouds * 0.125 + 0.0019 * (90 - zen))  # cloud factor (atmospheric transmission)
            Inoon = Iclear * cfac * (1 - albedo)  # noon irradiance: total solar
            noonparnow = parrac * Inoon
            return noonparnow

        if station == 'india':
            latitude = 60.0  # latitude, degrees
            clouds = 6.0  # cloud fraction, oktas
            e0 = 12.0  # atmospheric vapour pressure
        elif station == 'biotrans':
            latitude = 47.0
            clouds = 6.0
            e0 = 12.0
        elif station == 'kerfix':
            latitude = -50.67
            clouds = 6.0
            e0 = 12.0
        elif station == 'papa':
            latitude = 50.0
            clouds = 6.0
            e0 = 12.0
        else:
            raise ValueError("station label not found, options: 'india', 'biotrans', 'kerfix', 'papa'")

        latradians = latitude * np.pi / 180.

        def return_noonPAR(time):
            return noon_PAR_calc(time, latradians, clouds, e0)

        return return_noonPAR
예제 #27
0
class GrossGrowthEfficiency_MatrixGrazing:
    """
    to N: beta*(1-epsilon)
    to D: 1-beta
    to Z: beta*epsilon
    """
    grazed_resource = phydra.variable(dims='resource',
                                      foreign=True,
                                      flux='grazing',
                                      negative=True)
    assimilated_consumer = phydra.variable(dims='consumer',
                                           foreign=True,
                                           flux='assimilation')
    egested_detritus = phydra.variable(foreign=True, flux='egestion')

    f_eg = phydra.parameter(description='fraction egested')
    epsilon = phydra.parameter(description='net production efficiency')

    @phydra.flux(dims='resource', group_to_arg='graze_matrix')
    def grazing(self, assimilated_consumer, egested_detritus, grazed_resource,
                graze_matrix, f_eg, epsilon):
        """ """
        out = self.m.sum(graze_matrix, axis=1)
        return out

    @phydra.flux(dims='consumer', group_to_arg='graze_matrix')
    def assimilation(self, assimilated_consumer, egested_detritus,
                     grazed_resource, graze_matrix, f_eg, epsilon):
        """ """
        out = self.m.sum(graze_matrix, axis=0) * epsilon
        return out

    @phydra.flux(group_to_arg='graze_matrix')
    def egestion(self, assimilated_consumer, egested_detritus, grazed_resource,
                 graze_matrix, f_eg, epsilon):
        """ """
        out = self.m.sum(graze_matrix, axis=None) * (1 - f_eg - epsilon)
        return out
예제 #28
0
class EMPOWER_Smith_ML:
    """ """
    pigment_biomass = phydra.variable(foreign=True)

    i_0 = phydra.forcing(foreign=True, description='Light forcing')
    mld = phydra.forcing(foreign=True, description='Mixed Layer Depth forcing')

    alpha = phydra.parameter(description='initial slop of PI curve')
    CtoChl = phydra.parameter(description='chlorophyll to carbon ratio')
    kw = phydra.parameter(description='light attenuation coef for water')
    kc = phydra.parameter(
        description='light attenuation coef for pigment biomass')

    @phydra.flux(group_to_arg='VpT', group='growth_lims')
    def smith_light_lim(self, i_0, mld, pigment_biomass, alpha, VpT, kw, kc,
                        CtoChl):
        kPAR = kw + kc * pigment_biomass
        i_0 = i_0 / 24  # from per day to per h
        x_0 = alpha * i_0  # * self.m.exp(- kPAR * 0) # (== 1)
        x_H = alpha * i_0 * self.m.exp(-kPAR * mld)
        VpH = VpT / kPAR / mld * (self.m.log(x_0 + (VpT**2 + x_0**2)**0.5) -
                                  self.m.log(x_H + (VpT**2 + x_H**2)**0.5))
        return VpH * 24 / CtoChl
예제 #29
0
파일: forcings.py 프로젝트: ben1post/phydra
class ConstantForcing:
    forcing = phydra.forcing(foreign=False, setup_func='forcing_setup')
    value = phydra.parameter(description='constant value of forcing')

    def forcing_setup(self, value):
        cwd = os.getcwd()
        print("forcing function is in directory:", cwd)
        print("forcing_val:", value)

        @np.vectorize
        def forcing(time):
            return value

        return forcing
예제 #30
0
class ListInputFlux:
    """ get variable input of multiple labels as list
        and do the routing etc.
    """
    resources = phydra.variable(foreign=True, negative=True, flux='growth', list_input=True, dims='resources')
    consumer = phydra.variable(foreign=True, flux='growth')
    halfsats = phydra.parameter(dims='resources')

    @phydra.flux(dims='resources')
    def growth(self, resources, consumer, halfsats):
        print(resources, consumer, halfsats)
        print(sum(resources + halfsats))
        out = resources / sum(resources + halfsats) * consumer
        print("out:", out, np.shape(out))
        return out