Beispiel #1
0
 def terminal_velocity(self, values, radius, k1, k2, k3, r1, r2):
     k1 = PrecisionResolver.get_floating_point(k1)
     k2 = PrecisionResolver.get_floating_point(k2)
     k3 = PrecisionResolver.get_floating_point(k3)
     r1 = PrecisionResolver.get_floating_point(r1)
     r2 = PrecisionResolver.get_floating_point(r2)
     self.__terminal_velocity_body.launch_n(values.size(), [values, radius, k1, k2, k3, r1, r2])
Beispiel #2
0
def c_inline(fun, **args):
    prae = r"([,+\-*/( ]|^)"
    post = r"([ )/*\-+,]|$)"
    real_t = PrecisionResolver.get_C_type()
    real_fmt = ".32g"
    source = ''
    for lineno, line in enumerate(inspect.getsourcelines(fun)[0]):
        stripped = line.strip()
        if stripped.startswith('@'):
            continue
        if stripped.startswith('//'):
            continue
        if stripped.startswith('def '):
            continue
        source += stripped
    source = source.replace("power(", "pow(")
    source = re.sub("^return ", "", source)
    for arg in inspect.signature(fun).parameters:
        source = re.sub(f"{prae}({arg}){post}", f"\\1{real_t}({args[arg]})\\3",
                        source)
    source = re.sub(f"{prae}const\\.([^\\d\\W]\\w*]*){post}",
                    "\\1" + real_t + "({const.\\2:" + real_fmt + "})\\3",
                    source)
    source = eval(f'f"""{source}"""')
    return f'{real_t}({source})'
Beispiel #3
0
def thrust(obj):
    if isinstance(obj, list):
        result = [thrust(o) for o in obj]
    elif hasattr(obj, 'data'):
        result = obj.data
    elif isinstance(obj, float):
        result = PrecisionResolver.get_floating_point(obj)
    elif isinstance(obj, int):
        result = trtc.DVInt64(obj)
    else:
        raise ValueError(f"Cannot upload {obj} to device.")
    return result
Beispiel #4
0
    def __init__(self):
        phys = self.formulae

        self._temperature_pressure_RH_body = trtc.For(["rhod", "thd", "qv", "T", "p", "RH"], "i", f'''
            T[i] = {phys.state_variable_triplet.T.c_inline(rhod="rhod[i]", thd="thd[i]")};
            p[i] = {phys.state_variable_triplet.p.c_inline(rhod="rhod[i]", T="T[i]", qv="qv[i]")};
            RH[i] = {phys.state_variable_triplet.pv.c_inline(p="p[i]", qv="qv[i]")} / {phys.saturation_vapour_pressure.pvs_Celsius.c_inline(T="T[i] - const.T0")};
        '''.replace("real_type", PrecisionResolver.get_C_type()))

        self.__explicit_euler_body = trtc.For(("y", "dt", "dy_dt"), "i", f'''
            y[i] = {phys.trivia.explicit_euler.c_inline(y="y[i]", dt="dt", dy_dt="dy_dt")};
        '''.replace("real_type", PrecisionResolver.get_C_type()))

        self.__critical_volume_body = trtc.For(("v_cr", "kappa", "v_dry", "v_wet", "T", "cell"), "i", f'''
            auto sigma = {phys.surface_tension.sigma.c_inline(T="T[cell[i]]", v_wet="v_wet[i]", v_dry="v_dry[i]")};
            auto r_cr = {phys.hygroscopicity.r_cr.c_inline(
                kp="kappa",
                rd3="v_dry[i] / const.pi_4_3",
                T="T[cell[i]]",
                sgm="sigma"
            )};
            v_cr[i] = {phys.trivia.volume.c_inline(radius="r_cr")};
        '''.replace("real_type", PrecisionResolver.get_C_type()))

        self.__terminal_velocity_body = trtc.For(["values", "radius", "k1", "k2", "k3", "r1", "r2"], "i", '''
            if (radius[i] < r1) {
                values[i] = k1 * radius[i] * radius[i];
            }
            else {
                if (radius[i] < r2) {
                    values[i] = k2 * radius[i];
                }
                else {
                    values[i] = k3 * pow(radius[i], (real_type)(.5));
                }
            }
            '''.replace("real_type", PrecisionResolver.get_C_type()))
Beispiel #5
0
    def _get_empty_data(shape, dtype):
        if dtype in (float, Storage.FLOAT):
            elem_cls = PrecisionResolver.get_C_type()
            dtype = Storage.FLOAT
        elif dtype in (int, Storage.INT):
            elem_cls = 'int64_t'
            dtype = Storage.INT
        elif dtype in (bool, Storage.BOOL):
            elem_cls = 'bool'
            dtype = Storage.BOOL
        else:
            raise NotImplementedError

        data = trtc.device_vector(elem_cls, int(np.prod(shape)))
        return data, shape, dtype
Beispiel #6
0
 def __setitem__(self, key, value):
     if hasattr(value, 'data') and hasattr(value, 'shape') and len(value.shape) != 0:
         if isinstance(value, np.ndarray):
             vector = trtc.device_vector_from_numpy(value)
             trtc.Copy(vector, self.data)
         else:
             trtc.Copy(value.data, self.data)
     else:
         if isinstance(value, int):
             dvalue = trtc.DVInt64(value)
         elif isinstance(value, float):
             dvalue = PrecisionResolver.get_floating_point(value)
         else:
             raise TypeError("Only Storage, int and float are supported.")
         trtc.Fill(self.data, dvalue)
     return self
Beispiel #7
0
    def _to_host(self):
        if isinstance(self.data, trtc.DVVector.DVRange):
            if self.dtype is Storage.FLOAT:
                elem_cls = PrecisionResolver.get_C_type()
            elif self.dtype is Storage.INT:
                elem_cls = 'int64_t'
            elif self.dtype is Storage.BOOL:
                elem_cls = 'bool'
            else:
                raise NotImplementedError()

            data = trtc.device_vector(elem_cls, self.data.size())

            trtc.Copy(self.data, data)
        else:
            data = self.data
        return data.to_host()
Beispiel #8
0
class Storage:

    FLOAT = PrecisionResolver.get_np_dtype()
    INT = np.int64
    BOOL = np.bool_

    def __init__(self, data, shape, dtype):
        self.data = data
        self.shape = (shape,) if isinstance(shape, int) else shape
        self.dtype = dtype

    def __getitem__(self, item):
        dim = len(self.shape)
        if isinstance(item, slice):
            start = item.start or 0
            stop = item.stop or self.shape[0]
            if dim == 1:
                result_data = self.data.range(start, stop)
                result_shape = (stop - start,)
            elif dim == 2:
                result_data = self.data.range(self.shape[1] * start, self.shape[1] * stop)
                result_shape = (stop - start, self.shape[1])
            else:
                raise NotImplementedError("Only 2 or less dimensions array is supported.")
            result = Storage(result_data, result_shape, self.dtype)
        elif isinstance(item, tuple) and dim == 2 and isinstance(item[0], int) and isinstance(item[1], slice):
            assert item[1].start is None or item[1].start == 0
            assert item[1].stop is None or item[1].stop == self.shape[1]
            assert item[1].step is None or item[1].step == 1
            result_data = self.data.range(self.shape[1] * item[0], self.shape[1] * (item[0] + 1))
            result = Storage(result_data, (*self.shape[1:],), self.dtype)
        else:
            result = self.to_ndarray()[item]
        return result

    def __setitem__(self, key, value):
        if hasattr(value, 'data') and hasattr(value, 'shape') and len(value.shape) != 0:
            if isinstance(value, np.ndarray):
                vector = trtc.device_vector_from_numpy(value)
                trtc.Copy(vector, self.data)
            else:
                trtc.Copy(value.data, self.data)
        else:
            if isinstance(value, int):
                dvalue = trtc.DVInt64(value)
            elif isinstance(value, float):
                dvalue = PrecisionResolver.get_floating_point(value)
            else:
                raise TypeError("Only Storage, int and float are supported.")
            trtc.Fill(self.data, dvalue)
        return self

    def __add__(self, other):
        raise TypeError("Use +=")

    def __iadd__(self, other):
        impl.add(self, other)
        return self

    def __sub__(self, other):
        raise TypeError("Use -=")

    def __isub__(self, other):
        impl.subtract(self, other)
        return self

    def __mul__(self, other):
        raise TypeError("Use *=")

    def __imul__(self, other):
        impl.multiply(self, other)
        return self

    def __truediv__(self, other):
        raise TypeError("Use /=")

    def __itruediv__(self, other):
        impl.truediv(self, other)
        return self

    def __mod__(self, other):
        raise TypeError("Use %=")

    def __imod__(self, other):
        impl.row_modulo(self, other)
        return self

    def __pow__(self, other):
        raise TypeError("Use **=")

    def __ipow__(self, other):
        impl.power(self, other)
        return self

    def __len__(self):
        return self.shape[0]

    def __bool__(self):
        if len(self) == 1:
            result = bool(self.data.to_host()[0] != 0)
        else:
            raise NotImplementedError("Logic value of array is ambiguous.")
        return result

    def _to_host(self):
        if isinstance(self.data, trtc.DVVector.DVRange):
            if self.dtype is Storage.FLOAT:
                elem_cls = PrecisionResolver.get_C_type()
            elif self.dtype is Storage.INT:
                elem_cls = 'int64_t'
            elif self.dtype is Storage.BOOL:
                elem_cls = 'bool'
            else:
                raise NotImplementedError()

            data = trtc.device_vector(elem_cls, self.data.size())

            trtc.Copy(self.data, data)
        else:
            data = self.data
        return data.to_host()

    def amin(self):
        return impl.amin(self.data)

    def all(self):
        assert self.dtype is Storage.BOOL
        return self.amin()

    def download(self, target, reshape=False):
        shape = target.shape if reshape else self.shape
        target[:] = np.reshape(self._to_host(), shape)

    @staticmethod
    def _get_empty_data(shape, dtype):
        if dtype in (float, Storage.FLOAT):
            elem_cls = PrecisionResolver.get_C_type()
            dtype = Storage.FLOAT
        elif dtype in (int, Storage.INT):
            elem_cls = 'int64_t'
            dtype = Storage.INT
        elif dtype in (bool, Storage.BOOL):
            elem_cls = 'bool'
            dtype = Storage.BOOL
        else:
            raise NotImplementedError

        data = trtc.device_vector(elem_cls, int(np.prod(shape)))
        return data, shape, dtype

    @staticmethod
    def empty(shape, dtype):
        result = Storage(*Storage._get_empty_data(shape, dtype))
        return result

    @staticmethod
    def _get_data_from_ndarray(array):
        if str(array.dtype).startswith('int'):
            dtype = Storage.INT
        elif str(array.dtype).startswith('float'):
            dtype = Storage.FLOAT
        elif str(array.dtype).startswith('bool'):
            dtype = Storage.BOOL
        else:
            raise NotImplementedError()

        data = trtc.device_vector_from_numpy(array.astype(dtype).ravel())
        return data, array.shape, dtype

    @staticmethod
    def from_ndarray(array):
        result = Storage(*Storage._get_data_from_ndarray(array))
        return result

    def floor(self, other=None):
        if other is None:
            impl.floor(self.data)
        else:
            impl.floor_out_of_place(self, other)
        return self

    def product(self, multiplicand, multiplier):
        impl.multiply_out_of_place(self, multiplicand, multiplier)
        return self

    def ratio(self, dividend, divisor):
        impl.divide_out_of_place(self, dividend, divisor)
        return self

    def ravel(self, other):
        if isinstance(other, Storage):
            trtc.Copy(other.data, self.data)
        else:
            self.data = trtc.device_vector_from_numpy(other.ravel())

    def to_ndarray(self):
        result = self._to_host()
        result = np.reshape(result, self.shape)
        return result

    def urand(self, generator=None):
        generator(self)

    def upload(self, data):
        trtc.Copy(
            trtc.device_vector_from_numpy(data.astype(self.dtype).ravel()),
            self.data
        )
Beispiel #9
0
 def explicit_euler(self, y, dt, dy_dt):
     dt = PrecisionResolver.get_floating_point(dt)
     dy_dt = PrecisionResolver.get_floating_point(dy_dt)
     self.__explicit_euler_body.launch_n(y.shape[0], (y.data, dt, dy_dt))
Beispiel #10
0
 def critical_volume(self, v_cr, kappa, v_dry, v_wet, T, cell):
     kappa = PrecisionResolver.get_floating_point(kappa)
     self.__critical_volume_body.launch_n(
         v_cr.shape[0],
         (v_cr.data, kappa, v_dry.data, v_wet.data, T.data, cell.data))
Beispiel #11
0
class PhysicsMethods:
    def __init__(self):
        phys = self.formulae

        self._temperature_pressure_RH_body = trtc.For(
            ["rhod", "thd", "qv", "T", "p", "RH"], "i", f'''
            T[i] = {c_inline(phys.state_variable_triplet.T, rhod="rhod[i]", thd="thd[i]")};
            p[i] = {c_inline(phys.state_variable_triplet.p, rhod="rhod[i]", T="T[i]", qv="qv[i]")};
            RH[i] = {c_inline(phys.state_variable_triplet.pv, p="p[i]", qv="qv[i]")} / {c_inline(phys.saturation_vapour_pressure.pvs_Celsius, T="T[i] - const.T0")};
        ''')

        self.__explicit_euler_body = trtc.For(("y", "dt", "dy_dt"), "i", f'''
            y[i] = {c_inline(phys.trivia.explicit_euler, y="y[i]", dt="dt", dy_dt="dy_dt")};
        ''')

        self.__critical_volume_body = trtc.For(
            ("v_cr", "kappa", "v_dry", "v_wet", "T", "cell"), "i", f'''
            auto sigma = {c_inline(phys.surface_tension.sigma, T="T[cell[i]]", v_wet="v_wet[i]", v_dry="v_dry[i]")};
            auto r_cr = {c_inline(phys.hygroscopicity.r_cr,
                kp="kappa",
                rd3="v_dry[i] / const.pi_4_3",
                T="T[cell[i]]",
                sgm="sigma"
            )};
            v_cr[i] = {c_inline(phys.trivia.volume, radius="r_cr")};
        ''')

    @nice_thrust(**NICE_THRUST_FLAGS)
    def critical_volume(self, v_cr, kappa, v_dry, v_wet, T, cell):
        kappa = PrecisionResolver.get_floating_point(kappa)
        self.__critical_volume_body.launch_n(
            v_cr.shape[0],
            (v_cr.data, kappa, v_dry.data, v_wet.data, T.data, cell.data))

    @nice_thrust(**NICE_THRUST_FLAGS)
    def temperature_pressure_RH(self, rhod, thd, qv, T, p, RH):
        self._temperature_pressure_RH_body.launch_n(
            T.shape[0],
            (rhod.data, thd.data, qv.data, T.data, p.data, RH.data))

    __terminal_velocity_body = trtc.For(
        ["values", "radius", "k1", "k2", "k3", "r1", "r2"], "i", '''
        if (radius[i] < r1) {
            values[i] = k1 * radius[i] * radius[i];
        }
        else {
            if (radius[i] < r2) {
                values[i] = k2 * radius[i];
            }
            else {
                values[i] = k3 * pow(radius[i], (real_type)(.5));
            }
        }
        '''.replace("real_type", PrecisionResolver.get_C_type()))

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def terminal_velocity(values, radius, k1, k2, k3, r1, r2):
        k1 = PrecisionResolver.get_floating_point(k1)
        k2 = PrecisionResolver.get_floating_point(k2)
        k3 = PrecisionResolver.get_floating_point(k3)
        r1 = PrecisionResolver.get_floating_point(r1)
        r2 = PrecisionResolver.get_floating_point(r2)
        PhysicsMethods.__terminal_velocity_body.launch_n(
            values.size(), [values, radius, k1, k2, k3, r1, r2])

    @nice_thrust(**NICE_THRUST_FLAGS)
    def explicit_euler(self, y, dt, dy_dt):
        dt = PrecisionResolver.get_floating_point(dt)
        dy_dt = PrecisionResolver.get_floating_point(dy_dt)
        self.__explicit_euler_body.launch_n(y.shape[0], (y.data, dt, dy_dt))
Beispiel #12
0
class PhysicsMethods:
    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def explicit_in_space(omega, c_l, c_r):
        return "c_l * (1 - omega) + c_r * omega;"

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def implicit_in_space(omega, c_l, c_r):
        """
        see eqs 14-16 in Arabas et al. 2015 (libcloudph++)
        """
        result = "(omega * (c_r - c_l) + c_l) / (1 - (c_r - c_l));"
        return result

    __temperature_pressure_RH_body = trtc.For(
        ["rhod", "thd", "qv", "T", "p", "RH"], "i", f'''
        // equivalent to eqs A11 & A12 in libcloudph++ 1.0 paper
        real_type exponent = {const.Rd} / {const.c_pd};
        real_type pd = pow((rhod[i] * {const.Rd} * thd[i]) / pow({const.p1000}, exponent), 1 / (1 - exponent));
        T[i] = thd[i] * pow((pd / {const.p1000}), exponent);
    
        real_type R = {const.Rv} / (1 / qv[i] + 1) + {const.Rd} / (1 + qv[i]);
        p[i] = rhod[i] * (1 + qv[i]) * R * T[i];
    
        // August-Roche-Magnus formula
        real_type pvs = {const.ARM_C1} * exp(({const.ARM_C2} * (T[i] - {const.T0})) / (T[i] - {const.T0} + {const.ARM_C3}));
    
        RH[i] = (p[i] - pd) / pvs;
    '''.replace("real_type", PrecisionResolver.get_C_type()))

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def temperature_pressure_RH(rhod, thd, qv, T, p, RH):
        PhysicsMethods.__temperature_pressure_RH_body.launch_n(
            T.shape[0],
            (rhod.data, thd.data, qv.data, T.data, p.data, RH.data))

    __terminal_velocity_body = trtc.For(
        ["values", "radius", "k1", "k2", "k3", "r1", "r2"], "i", '''
        if (radius[i] < r1) {
            values[i] = k1 * radius[i] * radius[i];
        }
        else {
            if (radius[i] < r2) {
                values[i] = k2 * radius[i];
            }
            else {
                values[i] = k3 * pow(radius[i], (real_type).5);
            }
        }
        '''.replace("real_type", PrecisionResolver.get_C_type()))

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def terminal_velocity(values, radius, k1, k2, k3, r1, r2):
        k1 = PrecisionResolver.get_floating_point(k1)
        k2 = PrecisionResolver.get_floating_point(k2)
        k3 = PrecisionResolver.get_floating_point(k3)
        r1 = PrecisionResolver.get_floating_point(r1)
        r2 = PrecisionResolver.get_floating_point(r2)
        PhysicsMethods.__terminal_velocity_body.launch_n(
            values.size(), [values, radius, k1, k2, k3, r1, r2])

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def radius(volume):
        return ""

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def dr_dt_MM(r, T, p, RH, kp, rd):
        return ""

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def dr_dt_FF(r, T, p, qv, kp, rd, T_i):
        return ""

    @staticmethod
    @nice_thrust(**NICE_THRUST_FLAGS)
    def dthd_dt(rhod, thd, T, dqv_dt):
        return ""