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
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)
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)
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)
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
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
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
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))
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)
def fixture_fortran_reader(): '''Create and return a FortranReader object with default settings.''' return FortranReader()