{ "cells": [ { "cell_type": "markdown", "id": "5857fe8d-5beb-43d8-9418-3d1e6b0a93c4", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "\"Open" ] }, { "cell_type": "markdown", "id": "5d08a29e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "# Fortran magic's documentation\n", "\n", "Fortran magic is an [IPython](http://ipython.org) extension that help to use fortran code in an interactive session. \n", "\n", "It adds a `%%fortran` cell magic that compile and import the Fortran code in the cell, using [F2py](http://wiki.scipy.org/F2py).\n", "\n", "The contents of the cell are written to a `.f90`/`.f` file in the\n", "directory `IPYTHONDIR/fortran` using a filename with the hash of the\n", "code. This file is then compiled. The resulting module\n", "is imported and all of its symbols are injected into the user's\n", "namespace.\n", "\n", "**Warning**: Starting with `python 3.12`, numpy switched to using `meson` instead of `distutils`. Unfortunately, at the moment, the backward compatibility of `f2py` based on `meson` is incomplete.\n", "\n", "* Author: Martín Gaitán \n", "* Homepage: https://github.com/mgaitan/fortran_magic \n", "* Twitter: [@tin`_`nqn`_`](https://twitter.com/tin_nqn_)\n", "* License: BSD\n", "\n", "This software was originally sponsored by [Phasety](http://phasety.com)\n", "\n", "Feedback, report of issues and pull requests are welcome!" ] }, { "cell_type": "markdown", "id": "5fe5001d-38e6-4a7c-be7a-f75e0f6c5397", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Install or upgrade\n", "\n", "You can install or upgrade via `pip`\n", "\n", " pip install -U fortran-magic\n", "\n", "or install via `conda-forge`\n", "\n", " conda install -c conda-forge fortran-magic" ] }, { "cell_type": "markdown", "id": "b93cf0e7-1f9f-4b59-8877-34854ce7c61d", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Try without local install (online)\n", "\n", "You can try `fortran-magic` in Google Colab by clicking the \"Open in\n", "Colab\" badge at the top (quick and easy, but need Google account).\n", "\n", "Or in GitHub Codespaces (a bit more complicated, but possible with\n", "a GitHub account):\n", "- Open this page with \"github.dev\" (\"More edit options\" at top right);\n", "- Create Codespace;\n", "- Install Python and Jupyter extension;" ] }, { "cell_type": "code", "execution_count": 1, "id": "d50d4527-974f-44f3-8d12-55806378e40e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "data": { "application/javascript": [ "\n", " if(typeof IPython === 'undefined') {\n", " console.log('fortranmagic.py: TDOO: JupyterLab ' +\n", " 'syntax highlight - unimplemented.');\n", " } else {\n", " IPython.CodeCell.options_default\n", " .highlight_modes['magic_fortran'] = {'reg':[/^%%fortran/]};\n", " }\n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "try:\n", " %load_ext fortranmagic\n", "except ModuleNotFoundError as err:\n", " # Automatic install required packages for know environments\n", " if \"codespace\" in str(get_ipython().config):\n", " # For GitHub Codespace install GNU Fortran, LAPACK, BLAS and pkg-config\n", " !conda install -y -q -c conda-forge fortran-compiler lapack blas pkgconfig\n", " %pip install -q -U fortran-magic --pre\n", " # TODO: remove pre-release version by release\n", " print(\"Warning: you may need to restart and execute all again\")\n", " %load_ext fortranmagic\n", " elif \"google.colab\" in str(get_ipython().config):\n", " # Google Colab have preinstalled GNU Fortran, LAPACK, BLAS and pkg-config\n", " %pip install -q -U fortran-magic --pre\n", " # TODO: remove pre-release version by release\n", " %load_ext fortranmagic\n", " else:\n", " raise AssertionError(\"Autoinstall\") from err" ] }, { "cell_type": "markdown", "id": "849bb941", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "# Usage \n", "\n", "Then you are ready to load the magic " ] }, { "cell_type": "code", "execution_count": 2, "id": "cb7ec369", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [ "fast" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The fortranmagic extension is already loaded. To reload it, use:\n", " %reload_ext fortranmagic\n" ] } ], "source": [ "%load_ext fortranmagic" ] }, { "cell_type": "markdown", "id": "c2bcfe5d", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "To load it each time IPython starts, list it in your configuration file:\n", "\n", " c.InteractiveShellApp.extensions = [\n", " 'fortranmagic'\n", " ]" ] }, { "cell_type": "code", "execution_count": 3, "id": "b204c9a5-229e-4f54-a86b-3540869ef44c", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "fast", "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "New default arguments for %fortran:\n", "\t--extra '-DNPY_NO_DEPRECATED_API=0'\n" ] } ], "source": [ "import numpy as np\n", "\n", "f_config = \"--extra '-DNPY_NO_DEPRECATED_API=0'\"\n", "\n", "%fortran_config {f_config}" ] }, { "cell_type": "markdown", "id": "db4d6f87", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Basic example\n", "\n", "Just mark the cell with `%%fortran` in the first line. The code will be highlighted accordingly and compiled when the cell is run " ] }, { "cell_type": "code", "execution_count": 4, "id": "edddd3c0", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "fast" ] }, "outputs": [], "source": [ "%%fortran\n", "\n", "subroutine f1(x, y, z)\n", " real, intent(in) :: x,y\n", " real, intent(out) :: z\n", "\n", " z = sin(x+y)\n", "\n", "end subroutine f1" ] }, { "cell_type": "code", "execution_count": 5, "id": "05f82b33", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [ "fast" ] }, "outputs": [ { "data": { "text/plain": [ "9.26574e-05" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%precision %g\n", "f1(1.0, 2.1415)" ] }, { "cell_type": "code", "execution_count": 6, "id": "fea5599d", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "fast" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "z = f1(x,y)\n", "\n", "Wrapper for ``f1``.\n", "\n", "Parameters\n", "----------\n", "x : input float\n", "y : input float\n", "\n", "Returns\n", "-------\n", "z : float\n", "\n" ] } ], "source": [ "print(f1.__doc__)" ] }, { "cell_type": "code", "execution_count": 7, "id": "0b155099-12b3-451d-b8cc-e6f4e6971226", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "fast" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "subroutine f1(x, y, z)\n", " real, intent(in) :: x,y\n", " real, intent(out) :: z\n", "\n", " z = sin(x+y)\n", "\n", "end subroutine f1\n", "\n" ] } ], "source": [ "print(f1.__source__)" ] }, { "cell_type": "markdown", "id": "fb0aa568", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Verbosity\n", "\n", "By default the magic only returns output when the compilation process fails. But you can increase the verbosity with the flag `-v`" ] }, { "cell_type": "code", "execution_count": 8, "id": "0c0d794b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Ok. The following fortran objects are ready to use: hi\n" ] } ], "source": [ "%%fortran -v\n", "\n", "module hi\n", " integer :: five = 5\n", "end module" ] }, { "cell_type": "code", "execution_count": 9, "id": "95150cfc-492b-4bd7-9f00-27995e58e3ed", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "assert hi.five == 5" ] }, { "cell_type": "code", "execution_count": 10, "id": "1c75b752", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [ "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running...\n", " /Users/leo/opt/anaconda3/envs/sage312/bin/python -m numpy.f2py -DNPY_NO_DEPRECATED_API=0 --backend meson -m _fortran_magic_47bbfc7f119bc93e4ed46ac1cbeff2b3 -c /Users/leo/.cache/ipython/fortranmagic/26beaced/_fortran_magic_47bbfc7f119bc93e4ed46ac1cbeff2b3.f90\n", "\n", "Ok. The following fortran objects are ready to use: hi\n" ] } ], "source": [ "%%fortran -vv\n", "\n", "module hi\n", " integer :: five = 5\n", "end module" ] }, { "cell_type": "code", "execution_count": 11, "id": "dcbf20c1-f550-431b-991b-7e715d8a5f5f", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "assert hi.five == 5" ] }, { "cell_type": "code", "execution_count": null, "id": "228e92af", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random", "slow", "random_long" ] }, "outputs": [], "source": [ "%%fortran -vvv\n", "\n", "module hi\n", " integer :: five = 5\n", "end module" ] }, { "cell_type": "code", "execution_count": 13, "id": "6210c503-f27f-4eec-a33e-4f8bdadb14a8", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "assert hi.five == 5" ] }, { "cell_type": "markdown", "id": "b39c4fe4", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Using f2py options\n", "\n", "Almost all f2py's command line options are exposed to the `%%fortran` cell magic. See the docstring for detail. For example:" ] }, { "cell_type": "code", "execution_count": 14, "id": "2d4750df", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Ok. The following fortran objects are ready to use: zadd\n" ] } ], "source": [ "%%fortran -v --f77flags=\"-ffixed-form\"\n", "C\n", " SUBROUTINE ZADD(A,B,C,N)\n", "C\n", " DOUBLE COMPLEX A(*)\n", " DOUBLE COMPLEX B(*)\n", " DOUBLE COMPLEX C(*)\n", " INTEGER N\n", " DO 20 J = 1, N\n", " C(J) = A(J)+B(J)\n", " 20 CONTINUE\n", " END" ] }, { "cell_type": "code", "execution_count": 15, "id": "88eb2644", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zadd(a,b,c,n)\n", "\n", "Wrapper for ``zadd``.\n", "\n", "Parameters\n", "----------\n", "a : input rank-1 array('D') with bounds (*)\n", "b : input rank-1 array('D') with bounds (*)\n", "c : input rank-1 array('D') with bounds (*)\n", "n : input int\n", "\n" ] } ], "source": [ "print(zadd.__doc__)" ] }, { "cell_type": "code", "execution_count": 16, "id": "3e40e3d4-e2c5-4398-97ac-f6eaaa7531b3", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.+0.j 1.+1.j 2.+2.j 3.+3.j 4.+4.j 5.+5.j 6.+6.j 7.+7.j 8.+8.j 9.+9.j]\n" ] } ], "source": [ "a = np.arange(10, dtype=np.cdouble)\n", "b = a * complex(0, 1)\n", "c = np.empty_like(a)\n", "zadd(a, b, c, len(c))\n", "print(c)" ] }, { "cell_type": "markdown", "id": "f834854f", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Linking resources\n", "\n", "Use `--link` option. This is `--link-` in f2py command line" ] }, { "cell_type": "code", "execution_count": 17, "id": "bd257b84", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running...\n", " /Users/leo/opt/anaconda3/envs/sage312/bin/python -m numpy.f2py --dep lapack -DNPY_NO_DEPRECATED_API=0 --backend meson -m _fortran_magic_4abccef68ae429c7d4210594302cc7da -c /Users/leo/.cache/ipython/fortranmagic/26beaced/_fortran_magic_4abccef68ae429c7d4210594302cc7da.f90\n", "\n", "Ok. The following fortran objects are ready to use: solve\n" ] } ], "source": [ "%%fortran --link lapack -vv\n", "\n", "subroutine solve(A, b, x, n)\n", " ! solve the matrix equation A*x=b using LAPACK\n", " implicit none\n", "\n", " real*8, dimension(n,n), intent(in) :: A\n", " real*8, dimension(n), intent(in) :: b\n", " real*8, dimension(n), intent(out) :: x\n", "\n", " integer :: i, j, pivot(n), ok\n", "\n", " integer, intent(in) :: n\n", " x = b\n", "\n", " ! find the solution using the LAPACK routine SGESV\n", " call DGESV(n, 1, A, n, pivot, x, n, ok)\n", "\n", "end subroutine" ] }, { "cell_type": "code", "execution_count": 18, "id": "385be515", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "A = np.array([[1, 2.5], [-3, 4]])\n", "b = np.array([1, 2.5])" ] }, { "cell_type": "code", "execution_count": 19, "id": "94ff10f7", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x = solve(a,b,[n])\n", "\n", "Wrapper for ``solve``.\n", "\n", "Parameters\n", "----------\n", "a : input rank-2 array('d') with bounds (n,n)\n", "b : input rank-1 array('d') with bounds (n)\n", "\n", "Other Parameters\n", "----------------\n", "n : input int, optional\n", " Default: shape(a, 0)\n", "\n", "Returns\n", "-------\n", "x : rank-1 array('d') with bounds (n)\n", "\n" ] } ], "source": [ "print(solve.__doc__)" ] }, { "cell_type": "markdown", "id": "be6d669e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Which is, by the way, the same than" ] }, { "cell_type": "code", "execution_count": 20, "id": "67c73007", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "array([-0.19565217, 0.47826087])" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.linalg.solve(A, b)\n", "x" ] }, { "cell_type": "code", "execution_count": 21, "id": "1fcd6beb-ffad-4787-90fc-683850018b66", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "np.testing.assert_allclose(x, solve(A, b))" ] }, { "cell_type": "markdown", "id": "368d33d9", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Extra arguments\n", "\n", "F2py could have many other arguments. You could append extra arguments with `--extra`. For example:\n", "\n", "\n", " %%fortran --extra '-L/path/to/open/ -lopenblas'\n", " \n", " %%fortran --extra '-D -U'\n", " \n", " %%fortran --extra '-DPREPEND_FORTRAN -DUPPERCASE_FORTRAN'\n", " \n", " %%fortran --extra '-DNPY_NO_DEPRECATED_API=0'\n", " \n", "The option `--extra` could be given multiple times." ] }, { "cell_type": "markdown", "id": "bd784372-1533-4713-ab7e-7fc1e1116fe4", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Compilers runtime compatibility\n", "\n", "Incompatibility of compilers or runtime libraries that python was built with, and which are used to build the python extension, can lead to errors during build and/or errors in loading the resulting python extension module.\n", "\n", "For example, at the moment, Visual Studio compiler and GNU Fortran (`gfortran`, formerly `g95`) are not compatible when used with `numpy.f2py`. GNU Fortran is compatible with the mingw32 compiler (32-bit or 64-bit), which is available in `conda-forge` or `MSYS2`.\n", "\n", "Detailed description see:\n", "- Numpy issue [Can't import module created by f2py \"ImportError: DLL load failed\" #16416](https://github.com/numpy/numpy/issues/16416#issue-626668211) ;\n", "- Numpy documentation PR [DOC: Windows and F2PY #20311](https://github.com/numpy/numpy/pull/20311/files) ." ] }, { "cell_type": "markdown", "id": "82842bda", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Save options\n", "\n", "By default, `%%fortran` call to `f2py` without parameters (except, of course, the `-m` and `-c` needed to compile a new module). You can change this behaviour with `%fortran_config`. This line magic can be used in three different ways:\n", "\n", "\n", " %fortran_config\n", "\n", " Show the current custom configuration\n", "\n", " %fortran_config --defaults\n", "\n", " Delete the current configuration and back to defaults\n", "\n", " %fortran_config \n", "\n", " Save (persitently) to use with %%fortran. The same arguments allowed for `%%fortran` are available\n", " \n", "For example, to set the highest verbose level (`-vvv`) as default:" ] }, { "cell_type": "code", "execution_count": 22, "id": "3786a402", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "New default arguments for %fortran:\n", "\t-vvv --extra '-DNPY_NO_DEPRECATED_API=0'\n" ] } ], "source": [ "%fortran_config -vvv {f_config}" ] }, { "cell_type": "markdown", "id": "9897a7e4", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Now the use of `%%fortran` will include `-vvv` implicitly" ] }, { "cell_type": "code", "execution_count": null, "id": "fe47d30c", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random", "slow", "random_long" ] }, "outputs": [], "source": [ "%%fortran\n", "\n", "module hi\n", " integer :: five = 5\n", "end module" ] }, { "cell_type": "markdown", "id": "5293bf6c", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "We can see whatever the default config has" ] }, { "cell_type": "code", "execution_count": 24, "id": "54480e4b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Current defaults arguments for %fortran:\n", "\t-vvv --extra '-DNPY_NO_DEPRECATED_API=0'\n" ] } ], "source": [ "%fortran_config" ] }, { "cell_type": "markdown", "id": "50e9df0e", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "You can override that global configuration for one specific cell. For example, `%%fortran -v` will change the verbose level but keep the saved defaults." ] }, { "cell_type": "code", "execution_count": 25, "id": "1475ba52", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "slow" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Ok. The following fortran objects are ready to use: hi\n" ] } ], "source": [ "%%fortran -v\n", "\n", "module hi\n", " integer :: five = 5\n", "end module" ] }, { "cell_type": "markdown", "id": "26df09eb", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "To clear the custom defaults and back to the defaults (no arguments) use:" ] }, { "cell_type": "code", "execution_count": 26, "id": "3321871f", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Deleted custom config. Back to default arguments for %%fortran\n" ] } ], "source": [ "%fortran_config --defaults" ] }, { "cell_type": "code", "execution_count": 27, "id": "0be16a46-9ebe-40d5-a130-6dbdd81a13e7", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "New default arguments for %fortran:\n", "\t--extra '-DNPY_NO_DEPRECATED_API=0'\n" ] } ], "source": [ "%fortran_config {f_config}" ] }, { "cell_type": "markdown", "id": "723266a0", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Help on f2py \n", "\n", "F2py has some flag that output help. See the docstring of `%f2py_help`" ] }, { "cell_type": "code", "execution_count": null, "id": "09f050a3", "metadata": { "collapsed": false, "editable": true, "jupyter": { "outputs_hidden": false }, "slideshow": { "slide_type": "" }, "tags": [ "random", "random_long" ] }, "outputs": [], "source": [ "%f2py_help --link blas" ] }, { "cell_type": "code", "execution_count": null, "id": "f8fd3a4a", "metadata": { "editable": true, "scrolled": true, "slideshow": { "slide_type": "" }, "tags": [ "random", "slow", "random_long" ] }, "outputs": [], "source": [ "%f2py_help --resources" ] }, { "cell_type": "code", "execution_count": 30, "id": "d02f8355", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random", "slow" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Use --dep for meson builds\n" ] } ], "source": [ "%f2py_help --link lapack" ] }, { "cell_type": "markdown", "id": "f8141784-036d-4dd0-a014-0aba0a863e25", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## Cache advanced\n", "\n", "As described above, build is performed in a separate directory. Since name of temporary module is obtained as a hash of the source code, compilation keys and configuration, usually when working with a single notebook, this does not cause problems. However, in difficult cases: parallel work with several notebooks, significant dependence of the assembly on environment variables, etc., conflicts may arise over the names of temporary modules. For example, Windows locks writing to files of already loaded modules, Linux and macOS ignore changes when reloading the extension module into the same process, etc.\n", "\n", "Identical modules are not rebuild, previously loaded instances are used." ] }, { "cell_type": "code", "execution_count": 31, "id": "acf599f8-245b-4b8e-b582-1e9f6f1f52db", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "original_f1 = f1" ] }, { "cell_type": "code", "execution_count": 32, "id": "beae6740-c9db-40d0-aeae-802d4883403b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "fast", "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The extension _fortran_magic_9d72701d516b1704fe4ad110d877459f is already loaded. To reload it, use:\n", " %fortran_config --clean-cache\n" ] } ], "source": [ "%%fortran\n", "\n", "subroutine f1(x, y, z)\n", " real, intent(in) :: x,y\n", " real, intent(out) :: z\n", "\n", " z = sin(x+y)\n", "\n", "end subroutine f1" ] }, { "cell_type": "code", "execution_count": 33, "id": "0d7a144d-c857-40c3-99e8-5ecd95ac8f82", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "import sys\n", "\n", "secondary_f1 = f1\n", "assert original_f1.__source__ == secondary_f1.__source__\n", "assert sys.version_info.major < 3 or original_f1.__hash__() == secondary_f1.__hash__() # or .__code__ compare" ] }, { "cell_type": "markdown", "id": "83cca953-cf6c-4407-85b1-140982749eee", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "
\n", "`--add-hash=` flags changes hash and, accordingly, name of temporary module." ] }, { "cell_type": "code", "execution_count": 34, "id": "fa8575a6-01ef-48b1-a243-9ad353965123", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "fast" ] }, "outputs": [], "source": [ "%%fortran --add-hash=1\n", "\n", "subroutine f1(x, y, z)\n", " real, intent(in) :: x,y\n", " real, intent(out) :: z\n", "\n", " z = sin(x+y)\n", "\n", "end subroutine f1" ] }, { "cell_type": "code", "execution_count": 35, "id": "2a6e2289-8875-48b6-a8cf-e831e1b777a5", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "third_f1 = f1\n", "assert original_f1.__source__ == third_f1.__source__\n", "assert sys.version_info.major < 3 or original_f1.__hash__() != third_f1.__hash__()" ] }, { "cell_type": "markdown", "id": "483fb2c8-1c8e-40e0-9654-80f843dab460", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "
\n", "Clearing cache directory." ] }, { "cell_type": "code", "execution_count": 36, "id": "96b0a47c-dadc-48d3-beda-49c0511622f5", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "random" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Clean cache: /Users/leo/.cache/ipython/fortranmagic/26beaced\n", "New cache: /Users/leo/.cache/ipython/fortranmagic/64dea1f0\n" ] } ], "source": [ "%fortran_config -v --clean-cache" ] }, { "cell_type": "markdown", "id": "14a4b9b1-bc73-4995-8108-f5a5d6ced3b0", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "
\n", "At the moment, when using additional files or libraries, absolute paths should be used." ] }, { "cell_type": "code", "execution_count": 37, "id": "8f61fddc-676d-499d-b9f5-2ac9d1b6b744", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting tfone.f90\n" ] } ], "source": [ "%%file tfone.f90\n", "\n", "integer function tfone()\n", " tfone = 1\n", "end" ] }, { "cell_type": "code", "execution_count": 38, "id": "7fb27b941602401d91542211134fc71a", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "import os\n", "\n", "tfone = os.path.abspath(\"tfone.f90\")" ] }, { "cell_type": "code", "execution_count": 39, "id": "7e0eafe3-c8c7-4fd7-ae23-617ad791a9cb", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "%%fortran --extra {tfone}\n", "\n", "integer function tfdigits()\n", " real x\n", " tfdigits = digits(x)\n", "end" ] }, { "cell_type": "code", "execution_count": 40, "id": "f3cb72e1-55a3-4242-baa0-02b2053aea94", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "assert tfone() == 1 and tfdigits() == 24" ] }, { "cell_type": "markdown", "id": "871526a3", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "---------------\n", "# Final\n", "* Bugs? Ideas? [Open an issue](https://github.com/mgaitan/fortran_magic)\n", "* Do you want to collaborate? [Fork it](https://github.com/mgaitan/fortran_magic/fork)! and send a pull-request\n", "\n", "## Cell tags\n", "Tags | Descriptions\n", ":-------------|:-------------\n", "`random` | Tests don't check outpus tagged cells.\n", "`random_long` | `Clear Outputs` before commit. \n", "`fast` | Will be tested on `pytest -m 'fast'`\n", "`slow` | Don't tested on `pytest -m 'not slow'` (pytest-astropy plugin: `pytest --run-slow`)\n", "`skip`, `skip_darwin`, `skip_linux`, `skip_win32`| Skip cell (tests don't compute)\n", "`xfail`, `xfail_darwin`, `xfail_linux`, `xfail_win32`| Cell compute, but failed.\n", "\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.0" }, "toc-autonumbering": false, "toc-showtags": true }, "nbformat": 4, "nbformat_minor": 5 }