All Projects → rjfarmer → gfort2py

rjfarmer / gfort2py

Licence: GPL-2.0 license
Library to allow calling fortran code from python

Programming Languages

python
139335 projects - #7 most used programming language
fortran
972 projects

Projects that are alternatives of or similar to gfort2py

Rust Bindgen
Automatically generates Rust FFI bindings to C (and some C++) libraries.
Stars: ✭ 2,453 (+3988.33%)
Mutual labels:  bindings
Nimgl
NimGL is a Nim library that offers bindings for popular libraries used in computer graphics
Stars: ✭ 218 (+263.33%)
Mutual labels:  bindings
mapbox-ios-binding
Xamarin binding library for Mapbox iOS SDK
Stars: ✭ 15 (-75%)
Mutual labels:  bindings
Vsphere Automation Sdk Rest
REST (Postman and JavaScript) samples and API reference documentation for vSphere using the VMware REST API
Stars: ✭ 182 (+203.33%)
Mutual labels:  bindings
Intercept
A C/C++ Binding Library for SQF and RV Engine Access Abstraction Layer
Stars: ✭ 191 (+218.33%)
Mutual labels:  bindings
Fltk Rs
Rust bindings for the FLTK GUI library.
Stars: ✭ 241 (+301.67%)
Mutual labels:  bindings
Cppsharp
Tools and libraries to glue C/C++ APIs to high-level languages
Stars: ✭ 2,221 (+3601.67%)
Mutual labels:  bindings
loam
Javascript wrapper for GDAL in the browser
Stars: ✭ 174 (+190%)
Mutual labels:  bindings
Freetype Py
Python binding for the freetype library
Stars: ✭ 209 (+248.33%)
Mutual labels:  bindings
samp-rs
SA:MP SDK written in Rust
Stars: ✭ 36 (-40%)
Mutual labels:  bindings
Go Python3
Go bindings to the CPython-3 API
Stars: ✭ 185 (+208.33%)
Mutual labels:  bindings
Widgetkit
Compose native apps without a code using JSON and load them as NSBundle into another app dynamicly from local or remote locations.
Stars: ✭ 191 (+218.33%)
Mutual labels:  bindings
Python Mpv
Python interface to the awesome mpv media player
Stars: ✭ 245 (+308.33%)
Mutual labels:  bindings
Qt5.cr
Qt5 bindings for Crystal, based on Bindgen
Stars: ✭ 182 (+203.33%)
Mutual labels:  bindings
hoedown
rust bindings for hoedown
Stars: ✭ 16 (-73.33%)
Mutual labels:  bindings
Tdl
Node.js bindings to TDLib.
Stars: ✭ 177 (+195%)
Mutual labels:  bindings
Vue Firestore
☁️ Cloud Firestore binding in realtime with Vuejs
Stars: ✭ 239 (+298.33%)
Mutual labels:  bindings
DotNetJS
Consume C# in JavaScript with comfort: single-file UMD library, auto-generated 2-way bindings and type definitions
Stars: ✭ 551 (+818.33%)
Mutual labels:  bindings
swift-tree-sitter
Swift bindings for the tree-sitter parsing library
Stars: ✭ 29 (-51.67%)
Mutual labels:  bindings
RubyGateway
Embed Ruby in Swift: load Gems, run scripts, call APIs seamlessly in both directions.
Stars: ✭ 108 (+80%)
Mutual labels:  bindings

Build status Coverage Status PyPI version DOI

gfort2py

Library to allow calling fortran code from python. Requires gfortran>=8.0.0, Works with python 3.*

Current stable version is 1.1.7

Build

ipython3 setup.py install --user

or install via pip

pip install --user gfort2py

Why use this over other fortran to python translators?

gfort2py use gfortran .mod files to translate your fortran code's ABI to python compatible types using python's ctype library. The advantage here is that it can (in principle) handle anything the compiler can compile. gfort2py is almost entirely python and there are no changes needed to your fortran source code (some changes in the build process may be needed, as gfort2py needs your code compiled as a shared library). Disadvantage means we are tied to gfortran and can't support other compilers and may break when gfortran updates its .mod file format, though this happens rarely.

Using

Fortran side

Compile code with -fPIC and -shared as options, then link togethter as a shared lib at the end

gfortran -fPIC -shared -c file.f90
gfortran -fPIC -shared -o libfile file.f90

If your code comes as program that does everything, then just turn the program into a function call inside a module, then create a new file with your program that uses the module and calls the function you just made.

If the shared library needs other shared libraries you will need to set LD_LIBRARY_PATH environment variable, and its also recommended is to run chrpath on the shared libraries so you can access them from anywhere.

Python side

import gfort2py as gf

SHARED_LIB_NAME='./test_mod.so'
MOD_FILE_NAME='tester.mod'

x=gf.fFort(SHARED_LIB_NAME,MOD_FILE_NAME)

x now contains all variables, parameters and functions from the module (tab completable).

Functions

y = x.func_name(a,b,c)

Will call the fortran function with variables a,b,c and will return the result in y, subroutines will return a dict (possibly empty) with any intent out, inout or undefined intent variables.

Optional arguments are handled by not passing anything for that item (python side), but they must be at the end of the argument list (on the fortran side)

Array arguments must pass a numpy array, either pre filled (if the array is intent(in)) or made with zeros if the array is intent out or allocatable.

Variables

x.some_var = 1

Sets a module variable to 1, will attempt to coerce it to the fortran type

x.some_var
x.some_var.get()

First will print the value in some_var while get() will return the value

Arrays

Remember that fortran by default has 1-based array numbering while numpy is 0-based.

Derived types

Derived types can be set with a dict

x.my_dt={'x':1,'y':'abc'}

And return a dict when the .get() method is called, unless you pass copy=False to the get call in which case a ctype is returned (and fields access via the dot interface)

y=x.my_dt.get(copy=False)
y.x
y.y

If the derived type contains another derived type then you can set a dict in a dict

x.my_dt={'x':1,'y':{'a':1}}

This can then be accessed either via:

x.my_dt.y

To get a dict back, or:

x.my_dt.y.a
x.my_dt['a']

To get a single value.

When setting the components of a derived type you do not need to specify all of them at the same time.

Testing

ipython3 setup.py test

To run unit tests

Things that work

Module variables

  • Scalars
  • Parameters
  • Characters
  • Explicit size arrays
  • Complex numbers (Scalar and parameters)
  • Getting a pointer
  • Getting the value of a pointer
  • Allocatable arrays
  • Derived types
  • Nested derived types
  • Arrays of derived types
  • Functions inside derived types
  • Arrays with dimension (:) (pointer, allocatable) inside derived types (it doesn't break if their there, but you cant access them easily)
  • Classes
  • Abstract interfaces
  • Common blocks (parital)
  • Equivalences
  • Namelists
  • Quad precision variables

Functions/subroutines

  • Basic calling (no arguments)
  • Argument passing (scalars)
  • Argument passing (strings)
  • Argument passing (explicit arrays)
  • Argument passing (assumed size arrays)
  • Argument passing (assumed shape arrays)
  • Argument passing (allocatable arrays)
  • Argument passing (derived types)
  • Argument intents (in, out, inout and none)
  • Passing characters
  • Pointer Arguments
  • Optional arguments
  • Keyword arguments
  • Generic/Elemental functions
  • Functions as an argument

Accessing common block elements

Theres no direct way to access the common block elements, but if you declare the the common block as a module variable you may acccess the elements by their name:

module my_mod
	implicit none
	
	integer :: a,b,c
	common /comm1/ a,b,c
	

Elements in the common block can thus be accessed as:

x.a
x.b
x.c

Functions pointers:

Functions as arguments

Consider:

integer function my_func(func_arg)
	integer func_arg
	
	my_func = func_arg(5)
end function my_func
	

Assuming that func_arg is another fortran function then we can call my_func as:

x.my_func('func_arg') # With a string of the name of the argument of the function
#or
x.my_func(x.func_arg) # With the functin itself

Its left the the user to make sure that the function func_arg takes the correct inputs and returns the correct output

If instead you want func_arg to be a python function then things are a little different:

def my_py_func(x): # Python function that will be func_arg
	xv=x.contents.value # Values are passed by reference, this works for ints, floats. Characters, arrays and derived types are more complicated.
	return 10*xv

# We must "pair" the python function with an existing fortran function that has the same inputs/oupts and return type.
x.func_func_run.load() # This function call forces func_func_run to be initliazed without callling the function
y = x.func_func_arg([my_py_func,'func_func_run']) # This "pairs" the python function with a fortran function that has been loaded

Procedure pointers

Consider a prcoedure like:

procedure(my_func), pointer:: func_ptr => NULL()

We can not at this time set func_ptr from python, instead it must be set by fortran. The func_ptr can however be called from python if set, if it has not been set then we raise ValueError.

Its left to the user to enforce that the function has the correct interface

Contributing

Pull requests should target the maint branch for fixing issues, please check the test suite passes before sending a pull request. Maint will be periodically merged with master for new releases, master should never have a broken test suite.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].