Exemplo n.º 1
0
def generate_adjoint_str(tl_fortran_str):
    '''Takes an LFRic tangent-linear kernel encoded as a string as input
    and returns its adjoint encoded as a string.

    :param str tl_fortran_str: Fortran implementation of an LFRic \
        tangent-linear kernel.

    :returns: a string containing the Fortran implementation of the \
        supplied tangent-linear kernel.
    :rtype: str

    '''
    logger = logging.getLogger(__name__)
    logger.debug(tl_fortran_str)

    # TL Language-level PSyIR
    reader = FortranReader()
    tl_psyir = reader.psyir_from_source(tl_fortran_str)

    # Addressing issue #1238 will allow the view() method to be output
    # to the logger.
    # logger.debug(tl_psyir.view())

    # TL to AD translation
    ad_psyir = generate_adjoint(tl_psyir)

    # AD Fortran code
    writer = FortranWriter()
    adjoint_fortran_str = writer(ad_psyir)
    logger.debug(adjoint_fortran_str)

    return adjoint_fortran_str
Exemplo n.º 2
0
def test_fortran_psyir_from_source():
    ''' Test that the psyir_from_source method parses to PSyIR
    the specified source code. '''
    fortran_reader = FortranReader()
    file_container = fortran_reader.psyir_from_source(CODE)
    assert isinstance(file_container, FileContainer)
    subroutine = file_container.children[0]
    assert isinstance(subroutine, Routine)
Exemplo n.º 3
0
def test_fortran_reader_constructor():
    ''' Test that the constructor initialises the _parser and _processor
    attributes. '''
    freader = FortranReader()
    assert freader._parser is Fortran2003.Program
    assert isinstance(freader._processor, Fparser2Reader)

    # Check that the initialised parser can parse Fortran 2008 standard,
    # the return value of this function is tested in the following tests
    freader.psyir_from_source(ONLY_2008_CODE)
Exemplo n.º 4
0
def test_fortran_psyir_from_file(tmpdir_factory):
    ''' Test that the psyir_from_file method reads and parses to PSyIR
    the specified file. '''
    filename = str(tmpdir_factory.mktemp('frontend_test').join("testfile.f90"))
    with open(filename, "w") as wfile:
        wfile.write(CODE)

    # Check with a proper file
    fortran_reader = FortranReader()
    subroutine = fortran_reader.psyir_from_file(filename)
    assert isinstance(subroutine, Routine)

    # Check with a file that doesn't exist
    filename = str(tmpdir_factory.mktemp('frontend_test').join("Idontexist"))
    with pytest.raises(IOError) as err:
        fortran_reader.psyir_from_file(filename)
    assert "No such file or directory: '" + str(filename) in str(err.value)
Exemplo n.º 5
0
def create_alg_psyir(code):
    '''Utility to create an LFRic Algorithm PSyIR tree from Fortran
    code.

    :param str code: Fortran algorithm code encoded as a string.

    :returns: LFRic Algorithm PSyIR tree representing the Fortran \
        code.
    :rtype: :py:class:`psyclone.psyir.nodes.Node`

    '''
    fortran_reader = FortranReader()
    psyir = fortran_reader.psyir_from_source(code)
    alg_trans = LFRicAlgTrans()
    alg_trans.apply(psyir)

    return psyir
Exemplo n.º 6
0
def test_generate_adjoint():
    '''Test that the generate_adjoint() function works as expected.'''

    tl_fortran_str = ("program test\n"
                      "integer :: a\n"
                      "a = 0.0\n"
                      "end program test\n")
    expected_ad_fortran_str = ("program test\n"
                               "  integer :: a\n\n"
                               "  a = 0.0\n\n"
                               "end program test\n")
    reader = FortranReader()
    tl_psyir = reader.psyir_from_source(tl_fortran_str)

    ad_psyir = generate_adjoint(tl_psyir)

    writer = FortranWriter()
    ad_fortran_str = writer(ad_psyir)
    assert expected_ad_fortran_str in ad_fortran_str
Exemplo n.º 7
0
def test_generate_adjoint_logging(caplog):
    '''Test that logging works as expected in the generate_adjoint()
    function.

    '''
    tl_fortran_str = ("program test\n"
                      "integer :: a\n"
                      "a = 0.0\n"
                      "end program test\n")
    expected_ad_fortran_str = ("program test\n"
                               "  integer :: a\n\n"
                               "  a = 0.0\n\n"
                               "end program test\n")
    reader = FortranReader()
    tl_psyir = reader.psyir_from_source(tl_fortran_str)

    with caplog.at_level(logging.INFO):
        ad_psyir = generate_adjoint(tl_psyir)
    assert caplog.text == ""

    writer = FortranWriter()
    ad_fortran_str = writer(ad_psyir)
    assert expected_ad_fortran_str in ad_fortran_str

    with caplog.at_level(logging.DEBUG):
        ad_psyir = generate_adjoint(tl_psyir)
    # Python2 and 3 report different line numbers
    if six.PY2:
        line_number = 96
    else:
        line_number = 95
    assert (
        "DEBUG    psyclone.psyad.tl2ad:tl2ad.py:{0} Translation from generic "
        "PSyIR to LFRic-specific PSyIR should be done now.".format(line_number)
        in caplog.text)
    assert (
        "DEBUG    psyclone.psyad.tl2ad:tl2ad.py:100 Transformation from TL to "
        "AD should be done now." in caplog.text)

    ad_fortran_str = writer(ad_psyir)
    assert expected_ad_fortran_str in ad_fortran_str
Exemplo n.º 8
0
    def import_container(name):
        ''' Imports a Fortran module as a PSyIR container. The module is
        expected to be found in a Fortran source file with the same name
        as the module plus the '.[f|F]90' extension. The search
        locations are provided in-order by the Config include_paths
        attribute ('-I' in the psyclone script).

        :param str name: name of the module to be imported.

        :returns: container associated with the given name.
        :rtype: :py:class:`psyclone.psyir.nodes.Container`

        :raises SymbolError: the given Fortran module is not found on the \
            import path.

        '''
        # pylint: disable=import-outside-toplevel
        from psyclone.psyir.frontend.fortran import FortranReader
        for directory in Config.get().include_paths:
            for filename in [name+'.f90', name+'.F90']:
                if filename in listdir(directory):
                    # Parse the module source code
                    abspath = path.join(directory, filename)
                    fortran_reader = FortranReader()
                    file_container = fortran_reader.psyir_from_file(abspath)
                    # Check the expected container is in this file
                    for candidate in file_container.children:
                        if candidate.name.lower() == name.lower():
                            return candidate
                    raise ValueError(
                        "Error importing the Fortran module '{0}' into a "
                        "PSyIR container. The file with filename '{1}' "
                        "does not contain the expected module."
                        "".format(name, filename))

        raise SymbolError(
            "Module '{0}' (expected to be found in '{0}.[f|F]90') not found in"
            " any of the include_paths directories {1}."
            "".format(name, Config.get().include_paths))
Exemplo n.º 9
0
def test_fortran_psyir_from_source():
    ''' Test that the psyir_from_source method parses to PSyIR
    the specified source code. '''
    fortran_reader = FortranReader()
    subroutine = fortran_reader.psyir_from_source(CODE)
    assert isinstance(subroutine, Routine)
Exemplo n.º 10
0
def fixture_fortran_reader():
    '''Create and return a FortranReader object with default settings.'''
    return FortranReader()