Ejemplo n.º 1
0
def test_2kern_trans(kernel_outputdir):
    ''' Check that we generate correct code when we transform two kernels
    within a single invoke. '''
    psy, invoke = get_invoke("4.5.2_multikernel_invokes.f90",
                             api="dynamo0.3",
                             idx=0)
    sched = invoke.schedule
    kernels = sched.walk(Kern)
    assert len(kernels) == 5
    ktrans = Dynamo0p3KernelConstTrans()
    _, _ = ktrans.apply(kernels[1], {"number_of_layers": 100})
    _, _ = ktrans.apply(kernels[2], {"number_of_layers": 100})
    # Generate the code (this triggers the generation of new kernels)
    code = str(psy.gen).lower()
    # Find the tags added to the kernel/module names
    for match in re.finditer('use testkern_any_space_2(.+?)_mod', code):
        tag = match.group(1)
        assert ("use testkern_any_space_2{0}_mod, only: "
                "testkern_any_space_2{0}_code".format(tag) in code)
        assert "call testkern_any_space_2{0}_code(".format(tag) in code
        filepath = os.path.join(str(kernel_outputdir),
                                "testkern_any_space_2{0}_mod.f90".format(tag))
        assert os.path.isfile(filepath)
        assert "nlayers = 100" in open(filepath).read()
    assert "use testkern_any_space_2_mod, only" not in code
    assert "call testkern_any_space_2_code(" not in code
    assert LFRicBuild(kernel_outputdir).code_compiles(psy)
Ejemplo n.º 2
0
def trans(psy):
    '''PSyclone transformation script for the Dynamo0.3 API to make the
    kernel values of ndofs, nlayers and nquadrature-point sizes constant.

    '''
    const_trans = Dynamo0p3KernelConstTrans()
    fortran_writer = FortranWriter()

    for invoke in psy.invokes.invoke_list:
        print("invoke '{0}'".format(invoke.name))
        schedule = invoke.schedule
        for kernel in schedule.coded_kernels():
            print("  kernel '{0}'".format(kernel.name.lower()))
            try:
                const_trans.apply(kernel, number_of_layers=NUMBER_OF_LAYERS,
                                  element_order=ELEMENT_ORDER,
                                  quadrature=CONSTANT_QUADRATURE)
            except TransformationError:
                print("    Failed to modify kernel '{0}'".format(kernel.name))

            kernel_schedule = kernel.get_kernel_schedule()
            kern_code = fortran_writer(kernel_schedule)
            print(kern_code)

    return psy
Ejemplo n.º 3
0
def trans(psy):
    '''PSyclone transformation script for the Dynamo0.3 API to make the
    kernel values of ndofs, nlayers and nquadrature-point sizes constant.

    :param psy: a PSyclone PSy object which captures the algorithm and \
        kernel information required by PSyclone.
    :type psy: subclass of :py:class:`psyclone.psyGen.PSy`

    '''
    const_trans = Dynamo0p3KernelConstTrans()

    for invoke in psy.invokes.invoke_list:
        print("invoke '{0}'".format(invoke.name))
        schedule = invoke.schedule
        for kernel in schedule.coded_kernels():
            print("  kernel '{0}'".format(kernel.name.lower()))
            try:
                const_trans.apply(
                    kernel, {
                        "number_of_layers": NUMBER_OF_LAYERS,
                        "element_order": ELEMENT_ORDER,
                        "quadrature": CONSTANT_QUADRATURE
                    })
            except TransformationError:
                print("    Failed to modify kernel '{0}'".format(kernel.name))

    return psy
Ejemplo n.º 4
0
def test_kernel_module_name(mod_name, sub_name, kernel_outputdir, monkeypatch):
    '''Check that there is no limitation on kernel and module names. In
    particular check that the names do not have to conform to the
    <name>_mod, <name>_code convention.

    '''
    _, invoke = get_invoke("1_single_invoke.f90", api="dynamo0.3", idx=0)
    sched = invoke.schedule
    kernels = sched.coded_kernels()
    kern = kernels[0]
    ktrans = Dynamo0p3KernelConstTrans()
    _, _ = ktrans.apply(kern, {"number_of_layers": 100})
    # Modify the kernel module and subroutine names.
    monkeypatch.setattr(kern, "_module_name", mod_name)
    monkeypatch.setattr(kern, "_name", sub_name)
    # Generate the code - no exception should be raised when the names
    # do not conform to the <name>_mod, >name>_code convention.
    kern.rename_and_write()
Ejemplo n.º 5
0
def test_kern_case_insensitive(mod_name, sub_name, kernel_outputdir,
                               monkeypatch):
    '''Check that the test to see if a kernel conforms to the <name>_mod,
    <name>_code convention is case insensitive. This check also tests that the
    removal of _mod to create part of the output filename is case
    insensitive.

    '''
    _, invoke = get_invoke("1_single_invoke.f90", api="dynamo0.3", idx=0)
    sched = invoke.schedule
    kernels = sched.walk(Kern)
    kern = kernels[0]
    ktrans = Dynamo0p3KernelConstTrans()
    _, _ = ktrans.apply(kern, {"number_of_layers": 100})
    monkeypatch.setattr(kern, "_module_name", mod_name)
    monkeypatch.setattr(kern, "_name", sub_name)
    # Generate the code - this should not raise an exception.
    kern.rename_and_write()
    filename = os.path.join(str(kernel_outputdir), mod_name[:8] + "_0_mod.f90")
    assert os.path.isfile(filename)
def test_kernel_conformance_error(mod_name, sub_name, kernel_outputdir,
                                  monkeypatch):
    '''Check that an exception is raised if a kernel does not conform to
    the <name>_mod, <name>_code convention and is output via a PSyIR
    back-end. This limitation is the subject of issue #393.

    '''
    _, invoke = get_invoke("1_single_invoke.f90", api="dynamo0.3", idx=0)
    sched = invoke.schedule
    kernels = sched.coded_kernels()
    kern = kernels[0]
    ktrans = Dynamo0p3KernelConstTrans()
    _, _ = ktrans.apply(kern, number_of_layers=100)
    # Modify the kernel module and subroutine names.
    monkeypatch.setattr(kern, "_module_name", mod_name)
    monkeypatch.setattr(kern, "_name", sub_name)
    # Generate the code - this should raise an error as the kernel
    # does not conform to the <name>_mod, >name>_code convention.
    with pytest.raises(NotImplementedError) as excinfo:
        kern.rename_and_write()
    assert ("PSyclone back-end code generation relies on kernel modules "
            "conforming to the <name>_mod and <name>_code convention. "
            "However, found '{0}', '{1}'.".format(mod_name, sub_name)
            in str(excinfo))