Example #1
0
    def __init__(self, test_platforms, gas, specs, reacs):
        self.test_platforms = test_platforms
        self.gas = gas
        self.specs = specs
        self.reacs = reacs
        self.test_size = test_size
        self.script_dir = script_dir
        self.build_dir = build_dir
        self.obj_dir = obj_dir
        self.lib_dir = lib_dir

        # clean out build dir
        utils.create_dir(build_dir)
        for f in os.listdir(build_dir):
            if os.path.isfile(os.path.join(build_dir, f)):
                os.remove(os.path.join(build_dir, f))

        # info
        self.nspec = self.gas.n_species
        self.nrxn = self.gas.n_reactions
        # Ns - 1 + Temperature + Extra Variable
        self.jac_dim = self.gas.n_species - 1 + 2

        # create states
        np.random.seed(0)
        self.T = np.random.uniform(600, 2200, size=test_size)
        self.P = np.random.uniform(0.5, 50, size=test_size) * ct.one_atm
        self.V = np.random.uniform(1e-3, 1, size=test_size)
        self.Y = np.random.uniform(0, 1, size=(test_size, self.gas.n_species))
        # randomly set some zeros for each species
        self.Y[np.random.choice(self.Y.shape[0], size=gas.n_species),
               np.arange(gas.n_species)] = 0
        self.concs = np.empty_like(self.Y)
        self.n = np.empty((test_size, self.gas.n_species - 1))
        self.fwd_rate_constants = np.zeros((test_size, self.gas.n_reactions))
        self.fwd_rxn_rate = np.zeros((test_size, self.gas.n_reactions))

        self.spec_u = np.zeros((test_size, gas.n_species))
        self.spec_h = np.zeros((test_size, gas.n_species))
        self.spec_cv = np.zeros((test_size, gas.n_species))
        self.spec_cp = np.zeros((test_size, gas.n_species))
        self.spec_b = np.zeros((test_size, gas.n_species))
        self.conp_temperature_rates = np.zeros(test_size)
        self.conv_temperature_rates = np.zeros(test_size)

        # third body indicies
        self.thd_inds = np.array([
            i for i, x in enumerate(gas.reactions())
            if isinstance(x, ct.FalloffReaction)
            or isinstance(x, ct.ChemicallyActivatedReaction)
            or isinstance(x, ct.ThreeBodyReaction)
        ])
        self.ref_thd = np.zeros((test_size, self.thd_inds.size))
        self.ref_pres_mod = np.zeros((test_size, self.thd_inds.size))
        self.species_rates = np.zeros((test_size, gas.n_species))
        self.rxn_rates = np.zeros((test_size, gas.n_reactions))
        thd_eff_maps = []
        for i in self.thd_inds:
            default = gas.reaction(i).default_efficiency
            # fill all missing with default
            thd_eff_map = [
                default if j not in gas.reaction(i).efficiencies else
                gas.reaction(i).efficiencies[j] for j in gas.species_names
            ]
            thd_eff_maps.append(np.array(thd_eff_map))
        thd_eff_maps = np.array(thd_eff_maps)

        # various indicies and mappings
        self.rev_inds = np.array(
            [i for i in range(gas.n_reactions) if gas.is_reversible(i)],
            dtype=np.int32)
        self.rev_rate_constants = np.zeros((test_size, self.rev_inds.size))
        self.rev_rxn_rate = np.zeros((test_size, self.rev_inds.size))
        self.equilibrium_constants = np.zeros((test_size, self.rev_inds.size))

        self.fall_inds = np.array([
            i for i, x in enumerate(gas.reactions())
            if isinstance(x, ct.FalloffReaction)
        ])
        self.sri_inds = np.array([
            i for i, x in enumerate(gas.reactions())
            if i in self.fall_inds and isinstance(x.falloff, ct.SriFalloff)
        ])
        self.troe_inds = np.array([
            i for i, x in enumerate(gas.reactions())
            if i in self.fall_inds and isinstance(x.falloff, ct.TroeFalloff)
        ])
        self.lind_inds = np.array([
            i for i, x in enumerate(gas.reactions()) if i in self.fall_inds
            and not (i in self.troe_inds or i in self.sri_inds)
        ])
        self.troe_to_pr_map = np.array(
            [np.where(self.fall_inds == j)[0][0] for j in self.troe_inds])
        self.sri_to_pr_map = np.array(
            [np.where(self.fall_inds == j)[0][0] for j in self.sri_inds])
        self.lind_to_pr_map = np.array(
            [np.where(self.fall_inds == j)[0][0] for j in self.lind_inds])
        self.ref_Pr = np.zeros((test_size, self.fall_inds.size))
        self.ref_Sri = np.zeros((test_size, self.sri_inds.size))
        self.ref_Troe = np.zeros((test_size, self.troe_inds.size))
        self.ref_Lind = np.ones((test_size, self.lind_inds.size))
        self.ref_Fall = np.ones((test_size, self.fall_inds.size))
        self.ref_B_rev = np.zeros((test_size, gas.n_species))
        # and the corresponding reactions
        fall_reacs = [gas.reaction(j) for j in self.fall_inds]
        sri_reacs = [gas.reaction(j) for j in self.sri_inds]
        troe_reacs = [gas.reaction(j) for j in self.troe_inds]

        # convenience method for reduced pressure evaluation
        arrhen_temp = np.zeros(self.fall_inds.size)

        def pr_eval(i, j):
            reac = fall_reacs[j]
            return reac.low_rate(self.T[i]) / reac.high_rate(self.T[i])

        thd_to_fall_map = np.where(np.in1d(self.thd_inds, self.fall_inds))[0]

        for i in range(test_size):
            self.gas.TPY = self.T[i], self.P[i], self.Y[i, :]
            self.concs[i, :] = self.gas.concentrations[:]

            # set moles
            self.n[i, :] = self.concs[i, :-1] * self.V[i]

            # ensure that n_ns is non-negative
            n_ns = self.P[i] * self.V[i] / (ct.gas_constant * self.T[i]) \
                - np.sum(self.n[i, :])
            assert n_ns >= 0 or np.isclose(n_ns, 0)

            # store various information
            self.fwd_rate_constants[i, :] = gas.forward_rate_constants[:]
            self.rev_rate_constants[i, :] = gas.reverse_rate_constants[
                self.rev_inds]
            self.equilibrium_constants[i, :] = gas.equilibrium_constants[
                self.rev_inds]
            self.fwd_rxn_rate[i, :] = gas.forward_rates_of_progress[:]
            self.rev_rxn_rate[i, :] = gas.reverse_rates_of_progress[
                self.rev_inds]
            self.rxn_rates[i, :] = gas.net_rates_of_progress[:]
            self.species_rates[i, :] = gas.net_production_rates[:]
            self.ref_thd[i, :] = np.dot(thd_eff_maps, self.concs[i, :])
            # species thermo props
            for j in range(gas.n_species):
                cp = gas.species(j).thermo.cp(self.T[i])
                s = gas.species(j).thermo.s(self.T[i])
                h = gas.species(j).thermo.h(self.T[i])
                self.spec_cv[i, j] = cp - ct.gas_constant
                self.spec_cp[i, j] = cp
                self.spec_b[i, j] = s / ct.gas_constant - h / \
                    (ct.gas_constant * self.T[i]) - np.log(self.T[i])
                self.spec_u[i, j] = h - self.T[i] * ct.gas_constant
                self.spec_h[i, j] = h

            self.conp_temperature_rates[i] = (
                -np.dot(self.spec_h[i, :], self.species_rates[i, :]) /
                np.dot(self.spec_cp[i, :], self.concs[i, :]))
            self.conv_temperature_rates[i] = (
                -np.dot(self.spec_u[i, :], self.species_rates[i, :]) /
                np.dot(self.spec_cv[i, :], self.concs[i, :]))
            for j in range(self.fall_inds.size):
                arrhen_temp[j] = pr_eval(i, j)
            self.ref_Pr[i, :] = self.ref_thd[i, thd_to_fall_map] * arrhen_temp
            for j in range(self.sri_inds.size):
                self.ref_Sri[i, j] = sri_reacs[j].falloff(
                    self.T[i], self.ref_Pr[i, self.sri_to_pr_map[j]])
            for j in range(self.troe_inds.size):
                self.ref_Troe[i, j] = troe_reacs[j].falloff(
                    self.T[i], self.ref_Pr[i, self.troe_to_pr_map[j]])
            if self.sri_inds.size:
                self.ref_Fall[i, self.sri_to_pr_map] = self.ref_Sri[i, :]
            if self.troe_inds.size:
                self.ref_Fall[i, self.troe_to_pr_map] = self.ref_Troe[i, :]
            for j in range(gas.n_species):
                self.ref_B_rev[i, j] = gas.species(j).thermo.s(
                    self.T[i]) / ct.gas_constant - gas.species(j).thermo.h(
                        self.T[i]) / (ct.gas_constant * self.T[i]) - np.log(
                            self.T[i])

        # set phi
        self.phi_cp = np.concatenate(
            (self.T.reshape(-1, 1), self.V.reshape(-1, 1), self.n), axis=1)
        self.phi_cv = np.concatenate(
            (self.T.reshape(-1, 1), self.P.reshape(-1, 1), self.n), axis=1)

        # get extra variable rates
        mws = self.gas.molecular_weights
        mws = (1 - mws[:-1] / mws[-1])
        self.V_dot = self.V * (self.T * ct.gas_constant / self.P *
                               np.dot(self.species_rates[:, :-1], mws) +
                               self.conp_temperature_rates / self.T)

        self.P_dot = (self.T * ct.gas_constant *
                      np.dot(self.species_rates[:, :-1], mws) +
                      self.conv_temperature_rates * self.P / self.T)

        self.dphi_cp = np.concatenate((self.conp_temperature_rates.reshape(
            -1, 1), self.V_dot.reshape(
                -1, 1), self.species_rates[:, :-1] * self.V[:, np.newaxis]),
                                      axis=1)
        self.dphi_cv = np.concatenate((self.conv_temperature_rates.reshape(
            -1, 1), self.P_dot.reshape(
                -1, 1), self.species_rates[:, :-1] * self.V[:, np.newaxis]),
                                      axis=1)

        # the pressure mod terms depend on the reaction type
        # for pure third bodies, it's just the third body conc:
        self.ref_pres_mod[:, :] = self.ref_thd[:, :]
        # now find the Pr poly
        Pr_poly = 1. / (1. + self.ref_Pr)
        # and multiply the falloff (i.e. non-chem activated terms)
        pure_fall_inds = np.array([
            i for i, x in enumerate(gas.reactions())
            if isinstance(x, ct.FalloffReaction)
            and not isinstance(x, ct.ChemicallyActivatedReaction)
        ])
        pure_fall_inds = np.where(np.in1d(self.fall_inds, pure_fall_inds))[0]
        Pr_poly[:, pure_fall_inds] *= self.ref_Pr[:, pure_fall_inds]
        # finally find the product of the Pr poly and the falloff blending term
        Fall_pres_mod = Pr_poly * self.ref_Fall
        # and replace in the pressure mod
        replace_inds = np.where(np.in1d(self.thd_inds, self.fall_inds))[0]
        self.ref_pres_mod[:, replace_inds] = Fall_pres_mod[:, :]
Example #2
0
def run(gas, interval, num_states, work_dir, repeats=10):
    def arrhenius(T, A, b, Ea, print_stats=False):
        vals = A * np.power(T, b) * np.exp(-Ea / (ct.gas_constant * T))
        if print_stats:
            print(A, b, Ea, np.max(np.abs(vals - kf) / kf))
        return vals

    # first, convert all reactions to a single rate form
    reacs = gas.reactions()[:]
    for i, reac in enumerate(reacs):
        if isinstance(reac, ct.ChemicallyActivatedReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.high_rate
        elif isinstance(reac, ct.FalloffReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.high_rate
        elif isinstance(reac, ct.ThreeBodyReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.rate
        elif isinstance(reac, ct.PlogReaction):
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = reac.rates[-1][1]
        elif isinstance(reac, ct.ChebyshevReaction):
            # fit _something_ to it at a 10 bar, for 600-2200K
            T = np.linspace(600, 2200, num=1000)
            kf = np.zeros_like(T)
            for j in range(T.size):
                kf[j] = reac(T[j], 10 * 10*1e5)
            A = 1e10
            b = 1
            Ea = 1200 * ct.gas_constant
            (A, b, Ea), _ = curve_fit(
                arrhenius, T, kf,
                p0=[A, b, Ea],
                bounds=[(0, -2, 0), (np.inf, 5, np.inf)],
                maxfev=1e6,
                xtol=1e-15)
            if False:
                plt.plot(T, kf, color='b', linestyle='-', label='cheb')
                plt.plot(T, arrhenius(T, A, b, Ea), color='r', linestyle='--',
                         label='fit')
                plt.legend(loc=0)
                plt.show()
            reacs[i] = ct.ElementaryReaction(reac.reactants, reac.products)
            reacs[i].rate = ct.Arrhenius(A, b, Ea)
        # set all to reversible
        reacs[i].reversible = True

    # and convert gas
    gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                      reactions=reacs,
                      species=gas.species())

    # next, order the reactions by the number of distinct species
    def get_reac_and_spec_maps(mygas):
        # first, create rxn->species maps
        reac_nu = mygas.reactant_stoich_coeffs()
        prod_nu = mygas.product_stoich_coeffs()
        # species -> rxn mappings
        spec_masks = np.zeros((mygas.n_species, mygas.n_reactions),
                              dtype=np.bool)
        # the reaction -> species mappings
        reac_masks = []
        for i, reac in enumerate(mygas.reactions()):
            for spec in set(list(reac.reactants.keys()) + list(
                                 reac.products.keys())):
                j = mygas.species_index(spec)
                if prod_nu[j, i] - reac_nu[j, i]:
                    # non-zero species
                    spec_masks[j, i] = True
            reac_masks.append(np.where(spec_masks[:, i])[0])

        # convert to flat, fixed size array
        copy = np.array(reac_masks, copy=True)
        max_size = np.max([x.size for x in reac_masks])
        reac_masks = np.full((len(reac_masks), max_size), -1)
        for i, mask in enumerate(copy):
            reac_masks[i, :mask.size] = mask[:]

        return spec_masks, reac_masks

    # ensure we didn't remove any species
    spec_masks, reac_masks = get_reac_and_spec_maps(gas)
    converted_spec_count = np.where(~np.sum(spec_masks, axis=1))[0].size
    assert converted_spec_count == gas.n_species

    def species_to_rxn_count(reac_list=slice(None)):
        """
        The number of reactions each species is in
        """
        return np.sum(spec_masks[:, reac_list], axis=1)

    def simple(specs, spec_counts):
        """
        Returns 0 if any species in the reaction is unique to that reaction
        otherwise mean of the number of reactions per species in the reaction
        """
        specs = specs[np.where(specs >= 0)]
        if np.any(spec_counts[specs] == 1):
            return 0
        return np.mean(spec_counts[specs])

    def minh(specs, spec_counts):
        """
        The minimum number of reactions any species in the reaction is in
        """

        specs = specs[np.where(specs >= 0)]
        minh = np.min(spec_counts[specs])
        return 0 if minh == 1 else minh

    def rxn_scores(heuristic, reac_list=slice(None)):
        """
        Returns a score from 0--1, where 1 indicates that the reactions is a
        good removal candidate and 0 a bad candidate

        Heuristics correspond to local methods
        """

        reac_list = np.arange(gas.n_reactions)[reac_list]
        s2r = species_to_rxn_count(reac_list)
        scores = np.apply_along_axis(heuristic, 1, reac_masks[reac_list], s2r)
        return scores

    def get_next_removed(heuristic, reac_list=slice(None)):
        """
        Get the index of the next reaction to remove from the current reac_list
        using the given heuristic
        """
        scores = rxn_scores(heuristic, reac_list)
        amax = np.argmax(scores)
        if scores[amax] == 0:
            return -1
        return reac_list[amax]

    def active_reactions(reac_list, return_active=False):
        """
        Returns the number of active reactions in the reac_list
        If return_active is True, return the list of active reactions
        """
        alist = np.where(reac_list >= 0)[0]
        if return_active:
            return alist
        return alist.size

    saved_reaction_lists = []
    reac_list = np.arange(gas.n_reactions)
    saved_reaction_lists.append(active_reactions(reac_list, True))
    while True:
        remove_at = get_next_removed(minh, reac_list=np.where(
            reac_list >= 0)[0])
        if remove_at == -1:
            break
        reac_list[remove_at] = -1
        if (active_reactions(reac_list) <= active_reactions(
                saved_reaction_lists[-1]) - interval):
            # save list
            saved_reaction_lists.append(active_reactions(reac_list, True))

    # get final reaction list and save
    reac_list = active_reactions(reac_list, True)
    saved_reaction_lists.append(reac_list)

    def gas_from_reac_list(reac_list):
        reacs = gas.reactions()[:]
        reacs = [reacs[i] for i in reac_list]
        return ct.Solution(thermo='IdealGas', kinetics='GasKinetics',
                           reactions=reacs,
                           species=gas.species())

    # remap, and ensure the number of removed species is not less than
    # previously
    newgas = gas_from_reac_list(reac_list)
    smap_final, _ = get_reac_and_spec_maps(newgas)
    scount_final = np.where(~np.sum(smap_final, axis=1))[0].size
    assert scount_final == converted_spec_count

    print('Final mechanism size: {} reactions, {} species'.format(
        newgas.n_reactions, scount_final))

    vecsize = 8
    platform = 'intel'
    split_rate_kernels = False
    lang = 'opencl'
    rate_spec = 'hybrid'
    num_cores = 1
    order = 'C'

    def get_filename(wide=False):
        """
        emulate pyjac's naming scheme
        """
        desc = 'spec'
        vsize = vecsize if wide else '1'
        vectype = 'w' if wide else 'par'
        platform = 'intel'
        split = 'split' if split_rate_kernels else 'single'
        conp = 'conp'

        return '{}_{}_{}_{}_{}_{}_{}_{}_{}_{}'.format(
                desc, lang, vsize, order,
                vectype, platform, rate_spec,
                split, num_cores, conp) + '.txt'

    def check_file(file):
        if not os.path.exists(file):
            return repeats
        with open(file, 'r') as f:
            lines = f.readlines()
        import re
        todo = repeats
        for line in lines:
            line = line.split(',')
            if len(line) > 1 and sum(
                    1 if re.search(r'(?:\d+(?:\.\d+e[+-]\d+))', l) else 0
                    for l in line) == 4:
                # four doubles -> good line
                todo -= 1
        return todo

    build = os.path.join(path, 'out')
    obj = os.path.join(path, 'obj')
    lib = os.path.join(path, 'lib')

    for wide in [True, False]:
        vsize = vecsize if wide else None
        # now, go through the various generated reactions lists and run
        # the test on each
        for reac_list in saved_reaction_lists:
            outname = get_filename(wide)
            todo = check_file(outname)
            # clean
            clean_dir(build, remove_dir=False)
            clean_dir(obj, remove_dir=False)
            clean_dir(lib, remove_dir=False)

            subdir = os.path.join(work_dir, str(active_reactions(reac_list)))
            create_dir(subdir)
            # generate the source rate evaluation
            rgas = gas_from_reac_list(reac_list)
            create_jacobian('opencl', gas=rgas, vector_size=vsize,
                            wide=wide, build_path=build,
                            rate_specialization=rate_spec,
                            split_rate_kernels=split_rate_kernels,
                            data_filename=os.path.abspath(
                                os.path.join(work_dir, 'data.bin')),
                            data_order=order,
                            platform=platform,
                            skip_jac=True)

            # first create the executable (via libgen)
            tester = generate_library(lang, build, obj_dir=obj, out_dir=lib,
                                      shared=True,
                                      btype=build_type.species_rates,
                                      as_executable=True)

            # and do runs
            with open(os.path.join(subdir, outname), 'a+') as file:
                for i in range(todo):
                    print(i, "/", todo)
                    subprocess.check_call([os.path.join(lib, tester),
                                           str(num_states), str(1)],
                                          stdout=file)
Example #3
0
def test_strided_copy(state):
    lang = state['lang']
    order = state['order']
    depth = state['depth']
    width = state['width']

    # cleanup
    clean_dir(build_dir)
    clean_dir(obj_dir)
    clean_dir(lib_dir)

    # create
    utils.create_dir(build_dir)
    utils.create_dir(obj_dir)
    utils.create_dir(lib_dir)

    vec_size = depth if depth else (width if width else 0)
    # set max per run such that we will have a non-full run (1024 - 1008)
    # this should also be evenly divisible by depth and width
    # (as should the non full run)
    max_per_run = 16
    # number of ics should be divisibly by depth and width
    ics = max_per_run * 8 + vec_size
    if vec_size:
        assert ics % vec_size == 0
        assert max_per_run % vec_size == 0
        assert int(np.floor(ics / max_per_run) * max_per_run) % vec_size == 0
    dtype = np.dtype('float64')

    # create test arrays
    def __create(shape):
        if not isinstance(shape, tuple):
            shape = (shape, )
        shape = (ics, ) + shape
        arr = np.zeros(shape, dtype=dtype, order=order)
        arr.flat[:] = np.arange(np.prod(shape))
        return arr

    arrays = [
        __create(16),
        __create(10),
        __create(20),
        __create((20, 20)),
        __create(())
    ]
    const = [np.arange(10, dtype=dtype)]
    lp_arrays = [lp.GlobalArg('a{}'.format(i), shape=('problem_size',) + a.shape[1:],
                              order=order, dtype=(arrays + const)[i].dtype)
                 for i, a in enumerate(arrays)] + \
                [lp.TemporaryVariable('a{}'.format(i + len(arrays)), dtype=dtype,
                 order=order, initializer=const[i], read_only=True,
                 shape=const[i].shape) for i in range(len(const))]
    const = lp_arrays[len(arrays):]

    dtype = 'double'

    # create array splitter
    opts = type('', (object, ), {
        'width': width,
        'depth': depth,
        'order': order,
        'lang': lang
    })
    asplit = array_splitter(opts)

    # split numpy
    arrays = asplit.split_numpy_arrays(arrays)
    # make dummy knl
    knl = lp.make_kernel(
        '{[i]: 0 <= i <= 1}', """
                            if i > 1
                                a0[i, i] = 0
                                a1[i, i] = 0
                                a2[i, i] = 0
                                a3[i, i, i] = 0
                                a4[i] = 0
                                <> k = a5[i]
                            end
                         """, lp_arrays)
    # split loopy
    lp_arrays = asplit.split_loopy_arrays(knl).args

    # now create a simple library
    mem = memory_manager(opts.lang,
                         opts.order,
                         asplit._have_split(),
                         dev_type=state['device_type'],
                         strided_c_copy=lang == 'c')
    mem.add_arrays([x for x in lp_arrays],
                   in_arrays=[x.name for x in lp_arrays if x not in const],
                   out_arrays=[x.name for x in lp_arrays if x not in const],
                   host_constants=const)

    # create "kernel"
    size_type = 'int'
    lang_headers = []
    if lang == 'opencl':
        lang_headers.extend([
            '#include "memcpy_2d.oclh"', '#include "vectorization.oclh"',
            '#include <CL/cl.h>', '#include "ocl_errorcheck.oclh"'
        ])
        size_type = 'cl_uint'
    elif lang == 'c':
        lang_headers.extend(
            ['#include "memcpy_2d.h"', '#include "error_check.h"'])

    # kernel must copy in and out, using the mem_manager's format
    knl = Template("""
    for (size_t offset = 0; offset < problem_size; offset += per_run)
    {
        ${type} this_run = problem_size - offset < per_run ? \
            problem_size - offset : per_run;
        /* Memory Transfers into the kernel, if any */
        ${mem_transfers_in}

        /* Memory Transfers out */
        ${mem_transfers_out}
    }
    """).safe_substitute(type=size_type,
                         mem_transfers_in=mem._mem_transfers(
                             to_device=True, host_postfix='_save'),
                         mem_transfers_out=mem.get_mem_transfers_out(),
                         problem_size=ics)

    # create the host memory allocations
    host_names = ['h_' + arr.name for arr in lp_arrays]
    host_allocs = mem.get_mem_allocs(True, host_postfix='')

    # device memory allocations
    device_allocs = mem.get_mem_allocs(False)

    # copy to save for test
    host_name_saves = ['h_' + a.name + '_save' for a in lp_arrays]
    host_const_allocs = mem.get_host_constants()
    host_copies = [
        Template("""
        ${type} ${save} [${size}] = {${vals}};
        memset(${host}, 0, ${size} * sizeof(${type}));
        """).safe_substitute(save='h_' + lp_arrays[i].name + '_save',
                             host='h_' + lp_arrays[i].name,
                             size=arrays[i].size,
                             vals=', '.join(
                                 [str(x) for x in arrays[i].flatten()]),
                             type=dtype) for i in range(len(arrays))
    ]

    # and finally checks
    check_template = Template("""
        for(int i = 0; i < ${size}; ++i)
        {
            assert(${host}[i] == ${save}[i]);
        }
    """)
    checks = [
        check_template.safe_substitute(host=host_names[i],
                                       save=host_name_saves[i],
                                       size=arrays[i].size)
        for i in range(len(arrays))
    ]

    # and preambles
    ocl_preamble = """
    double* temp_d;
    int* temp_i;
    // create a context / queue
    int lim = 10;
    cl_uint num_platforms;
    cl_uint num_devices;
    cl_platform_id platform [lim];
    cl_device_id device [lim];
    cl_int return_code;
    cl_context context;
    cl_command_queue queue;
    check_err(clGetPlatformIDs(lim, platform, &num_platforms));
    for (int i = 0; i < num_platforms; ++i)
    {
        check_err(clGetDeviceIDs(platform[i], CL_DEVICE_TYPE_ALL, lim, device,
            &num_devices));
        if(num_devices > 0)
            break;
    }
    context = clCreateContext(NULL, 1, &device[0], NULL, NULL, &return_code);
    check_err(return_code);

    //create queue
    queue = clCreateCommandQueue(context, device[0], 0, &return_code);
    check_err(return_code);
    """
    preamble = ''
    if lang == 'opencl':
        preamble = ocl_preamble

    end = ''
    if lang == 'opencl':
        end = """
        check_err(clFlush(queue));
        check_err(clReleaseCommandQueue(queue));
        check_err(clReleaseContext(context));
    """

    file_src = Template("""
${lang_headers}
#include <stdlib.h>
#include <string.h>
#include <assert.h>


void main()
{
    ${preamble}

    double zero [${max_dim}] = {0};

    ${size_type} problem_size = ${problem_size};
    ${size_type} per_run = ${max_per_run};

    ${host_allocs}
    ${host_const_allocs}
    ${mem_declares}
    ${device_allocs}

    ${mem_saves}

    ${host_constant_copy}

    ${knl}

    ${checks}

    ${end}

    exit(0);
}
    """).safe_substitute(lang_headers='\n'.join(lang_headers),
                         mem_declares=mem.get_defns(),
                         host_allocs=host_allocs,
                         host_const_allocs=host_const_allocs,
                         device_allocs=device_allocs,
                         mem_saves='\n'.join(host_copies),
                         host_constant_copy=mem.get_host_constants_in(),
                         checks='\n'.join(checks),
                         knl=knl,
                         preamble=preamble,
                         end=end,
                         size_type=size_type,
                         max_per_run=max_per_run,
                         problem_size=ics,
                         max_dim=max([x.size for x in arrays]))

    # write file
    fname = os.path.join(build_dir, 'test' + utils.file_ext[lang])
    with open(fname, 'w') as file:
        file.write(file_src)
    files = [fname]

    # write aux
    write_aux(build_dir, opts, [], [])

    # copy any deps
    def __copy_deps(lang,
                    scan_path,
                    out_path,
                    change_extension=True,
                    ffilt=None):
        deps = [
            x for x in os.listdir(scan_path)
            if os.path.isfile(os.path.join(scan_path, x))
            and not x.endswith('.in')
        ]
        if ffilt is not None:
            deps = [x for x in deps if ffilt in x]
        files = []
        for dep in deps:
            dep_dest = dep
            dep_is_header = dep.endswith(utils.header_ext[lang])
            ext = (utils.file_ext[lang]
                   if not dep_is_header else utils.header_ext[lang])
            if change_extension and not dep.endswith(ext):
                dep_dest = dep[:dep.rfind('.')] + ext
            shutil.copyfile(os.path.join(scan_path, dep),
                            os.path.join(out_path, dep_dest))
            if not dep_is_header:
                files.append(os.path.join(out_path, dep_dest))
        return files

    scan = os.path.join(script_dir, os.pardir, 'kernel_utils', lang)
    files += __copy_deps(lang, scan, build_dir)
    scan = os.path.join(script_dir, os.pardir, 'kernel_utils', 'common')
    files += __copy_deps(host_langs[lang],
                         scan,
                         build_dir,
                         change_extension=False,
                         ffilt='memcpy_2d')

    # build
    files = [
        file_struct(lang, lang, f[:f.rindex('.')], [build_dir], [], build_dir,
                    obj_dir, True, True) for f in files
    ]
    assert not any(compiler(x) for x in files)
    lib = libgen(lang, obj_dir, lib_dir, [x.filename for x in files], True,
                 False, True)
    lib = os.path.join(lib_dir, lib)
    # and run
    subprocess.check_call(lib)
Example #4
0
    def test_read_initial_conditions(self):
        build_dir = self.store.build_dir
        obj_dir = self.store.obj_dir
        lib_dir = self.store.lib_dir
        setup = test_utils.get_read_ics_source()
        utils.create_dir(build_dir)
        utils.create_dir(obj_dir)
        utils.create_dir(lib_dir)
        oploop = OptionLoop(
            OrderedDict([
                # no need to test conv
                ('conp', [True]),
                ('order', ['C', 'F']),
                ('depth', [4, None]),
                ('width', [4, None]),
                ('lang', ['c'])
            ]))
        for state in oploop:
            if state['depth'] and state['width']:
                continue
            self.__cleanup(False)
            # create dummy loopy opts
            opts = type('', (object, ), state)()
            asplit = array_splitter(opts)

            # get source
            path = os.path.realpath(
                os.path.join(self.store.script_dir, os.pardir, 'kernel_utils',
                             'common', 'read_initial_conditions.c.in'))

            with open(path, 'r') as file:
                ric = Template(file.read())
            # subs
            ric = ric.safe_substitute(mechanism='mechanism.h',
                                      vectorization='vectorization.h')
            # write
            with open(os.path.join(build_dir, 'read_initial_conditions.c'),
                      'w') as file:
                file.write(ric)
            # write header
            write_aux(build_dir, opts, self.store.specs, self.store.reacs)
            # write setup
            with open(os.path.join(build_dir, 'setup.py'), 'w') as file:
                file.write(setup.safe_substitute(buildpath=build_dir))
            # copy read ics header to final dest
            shutil.copyfile(
                os.path.join(self.store.script_dir, os.pardir, 'kernel_utils',
                             'common', 'read_initial_conditions.h'),
                os.path.join(build_dir, 'read_initial_conditions.h'))
            # copy wrapper
            shutil.copyfile(
                os.path.join(self.store.script_dir, 'test_utils',
                             'read_ic_wrapper.pyx'),
                os.path.join(build_dir, 'read_ic_wrapper.pyx'))
            # setup
            python_str = 'python{}.{}'.format(sys.version_info[0],
                                              sys.version_info[1])
            call = [
                python_str,
                os.path.join(build_dir, 'setup.py'), 'build_ext',
                '--build-lib', lib_dir
            ]
            subprocess.check_call(call)
            # copy in tester
            shutil.copyfile(
                os.path.join(self.store.script_dir, 'test_utils',
                             'ric_tester.py'),
                os.path.join(lib_dir, 'ric_tester.py'))

            # For simplicity (and really, lack of need) we test CONP only
            # hence, the extra variable is the volume, while the fixed parameter
            # is the pressure

            # save phi, param in correct order
            phi = (self.store.phi_cp if opts.conp else self.store.phi_cv)
            save_phi, = asplit.split_numpy_arrays(phi)
            save_phi = save_phi.flatten(opts.order)
            param = self.store.P if opts.conp else self.store.V
            save_phi.tofile(os.path.join(lib_dir, 'phi_test.npy'))
            param.tofile(os.path.join(lib_dir, 'param_test.npy'))

            # save bin file
            out_file = np.concatenate(
                (
                    np.reshape(phi[:, 0], (-1, 1)),  # temperature
                    np.reshape(param, (-1, 1)),  # param
                    phi[:, 1:]),
                axis=1  # species
            )
            out_file = out_file.flatten('K')
            with open(os.path.join(lib_dir, 'data.bin'), 'wb') as file:
                out_file.tofile(file)

            # and run
            subprocess.check_call([
                python_str,
                os.path.join(lib_dir, 'ric_tester.py'), opts.order,
                str(self.store.test_size)
            ])