summaryrefslogtreecommitdiff
path: root/doc/source/f2py/python-usage.rst
blob: ef8ccd7dd657a562b1e2c4f1d32972c097fe3465 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
==================================
Using F2PY bindings in Python
==================================

All wrappers for Fortran/C routines, common blocks, or for Fortran
90 module data generated by F2PY are exposed to Python as ``fortran``
type objects. Routine wrappers are callable ``fortran`` type objects
while wrappers to Fortran data have attributes referring to data
objects.

All ``fortran`` type objects have an attribute ``_cpointer`` that contains a
``CObject`` referring to the C pointer of the corresponding Fortran/C function
or variable at the C level. Such ``CObjects`` can be used as a callback argument
for F2PY generated functions to bypass the Python C/API layer for calling Python
functions from Fortran or C when the computational aspects of such functions are
implemented in C or Fortran and wrapped with F2PY (or any other tool capable of
providing the ``CObject`` of a function).

Consider a Fortran 77 file ```ftype.f``:

  .. literalinclude:: ./code/ftype.f
     :language: fortran

and a wrapper built using ``f2py -c ftype.f -m ftype``.

In Python:

  .. literalinclude:: ./code/results/ftype_session.dat
     :language: python


Scalar arguments
=================

In general, a scalar argument for a F2PY generated wrapper function can
be an ordinary Python scalar (integer, float, complex number) as well as
an arbitrary sequence object (list, tuple, array, string) of
scalars. In the latter case, the first element of the sequence object
is passed to Fortran routine as a scalar argument.

.. note::

   * When type-casting is required and there is possible loss of information via
     narrowing e.g. when type-casting float to integer or complex to float, F2PY
     *does not* raise an exception.

     * For complex to real type-casting only the real part of a complex number is used.

   * ``intent(inout)`` scalar arguments are assumed to be array objects in
     order to have *in situ* changes be effective. It is recommended to use
     arrays with proper type but also other types work.

Consider the following Fortran 77 code:

  .. literalinclude:: ./code/scalar.f
     :language: fortran

and wrap it using ``f2py -c -m scalar scalar.f``.

In Python:

  .. literalinclude:: ./code/results/scalar_session.dat
     :language: python


String arguments
=================

F2PY generated wrapper functions accept almost any Python object as
a string argument, since ``str`` is applied for non-string objects.
Exceptions are NumPy arrays that must have type code ``'c'`` or
``'1'`` when used as string arguments.

A string can have an arbitrary length when used as a string argument
for an F2PY generated wrapper function. If the length is greater than
expected, the string is truncated silently. If the length is smaller than
expected, additional memory is allocated and filled with ``\0``.

Because Python strings are immutable, an ``intent(inout)`` argument
expects an array version of a string in order to have *in situ* changes be effective.

Consider the following Fortran 77 code:

  .. literalinclude:: ./code/string.f
     :language: fortran

and wrap it using ``f2py -c -m mystring string.f``.

Python session:

  .. literalinclude:: ./code/results/string_session.dat
     :language: python


Array arguments
================

In general, array arguments for F2PY generated wrapper functions accept
arbitrary sequences that can be transformed to NumPy array objects. There are
two notable exceptions:

* ``intent(inout)`` array arguments must always be proper-contiguous (defined below) and have a
  compatible ``dtype``, otherwise an exception is raised.
* ``intent(inplace)`` array arguments  will be changed *in situ* if the argument
  has a different type than expected (see the ``intent(inplace)`` attribute for
  more information).

In general, if a NumPy array is proper-contiguous and has a proper type then it
is directly passed to the wrapped Fortran/C function. Otherwise, an element-wise
copy of the input array is made and the copy, being proper-contiguous and with
proper type, is used as the array argument.

There are two types of proper-contiguous NumPy arrays:

* Fortran-contiguous arrays refer to data that is stored columnwise,
  i.e. the indexing of data as stored in memory starts from the lowest
  dimension;
* C-contiguous, or simply contiguous arrays, refer to data that is stored
  rowwise, i.e. the indexing of data as stored in memory starts from the highest
  dimension.

For one-dimensional arrays these notions coincide.

For example, a 2x2 array ``A`` is Fortran-contiguous if its elements
are stored in memory in the following order::

  A[0,0] A[1,0] A[0,1] A[1,1]

and C-contiguous if the order is as follows::

  A[0,0] A[0,1] A[1,0] A[1,1]

To test whether an array is C-contiguous, use the ``.flags.c_contiguous``
attribute of NumPy arrays.  To test for Fortran contiguity, use the
``.flags.f_contiguous`` attribute.

Usually there is no need to worry about how the arrays are stored in memory and
whether the wrapped functions, being either Fortran or C functions, assume one
or another storage order. F2PY automatically ensures that wrapped functions get
arguments with the proper storage order; the underlying algorithm is designed to
make copies of arrays only when absolutely necessary. However, when dealing with
very large multidimensional input arrays with sizes close to the size of the
physical memory in your computer, then care must be taken to ensure the usage of
proper-contiguous and proper type arguments.

To transform input arrays to column major storage order before passing
them to Fortran routines, use the function ``numpy.asfortranarray(<array>)``.

Consider the following Fortran 77 code:

  .. literalinclude:: ./code/array.f
     :language: fortran

and wrap it using ``f2py -c -m arr array.f -DF2PY_REPORT_ON_ARRAY_COPY=1``.

In Python:

  .. literalinclude:: ./code/results/array_session.dat
     :language: python

.. _Call-back arguments:

Call-back arguments
====================

F2PY supports calling Python functions from Fortran or C codes.

Consider the following Fortran 77 code:

  .. literalinclude:: ./code/callback.f
     :language: fortran

and wrap it using ``f2py -c -m callback callback.f``.

In Python:

  .. literalinclude:: ./code/results/callback_session.dat
     :language: python

In the above example F2PY was able to guess accurately the signature
of the call-back function. However, sometimes F2PY cannot establish the
appropriate signature; in these cases the signature of the call-back
function must be explicitly defined in the signature file.

To facilitate this, signature files may contain special modules (the names of
these modules contain the special ``__user__`` sub-string) that defines the
various signatures for call-back functions.  Callback arguments in routine
signatures have the ``external`` attribute (see also the ``intent(callback)``
attribute). To relate a callback argument with its signature in a ``__user__``
module block, a ``use`` statement can be utilized as illustrated below. The same
signature for a callback argument can be referred to in different routine
signatures.

We use the same Fortran 77 code as in the previous example but now
we will pretend that F2PY was not able to guess the signatures of
call-back arguments correctly. First, we create an initial signature
file ``callback2.pyf`` using F2PY::

    f2py -m callback2 -h callback2.pyf callback.f

Then modify it as follows

  .. include:: ./code/callback2.pyf
     :literal:

Finally, we build the extension module using ``f2py -c callback2.pyf callback.f``.

An example Python session for this snippet would be identical to the previous
example except that the argument names would differ.

Sometimes a Fortran package may require that users provide routines
that the package will use. F2PY can construct an interface to such
routines so that Python functions can be called from Fortran.

Consider the following Fortran 77 subroutine that takes an array as its input
and applies a function ``func`` to its elements.

  .. literalinclude:: ./code/calculate.f
     :language: fortran

The Fortran code expects that the function ``func`` has been defined externally.
In order to use a Python function for ``func``, it must have an attribute
``intent(callback)`` and, it must be specified before the ``external`` statement.

Finally, build an extension module using ``f2py -c -m foo calculate.f``

In Python:

  .. literalinclude:: ./code/results/calculate_session.dat
     :language: python

The function is included as an argument to the python function call to the
Fortran subroutine even though it was *not* in the Fortran subroutine argument
list. The "external" keyword refers to the C function generated by f2py, not the
python function itself. The python function is essentially being supplied to the
C function.

The callback function may also be explicitly set in the module.
Then it is not necessary to pass the function in the argument list to
the Fortran function. This may be desired if the Fortran function calling
the python callback function is itself called by another Fortran function.

Consider the following Fortran 77 subroutine:

  .. literalinclude:: ./code/extcallback.f
     :language: fortran

and wrap it using ``f2py -c -m pfromf extcallback.f``.

In Python:

  .. literalinclude:: ./code/results/extcallback_session.dat
     :language: python

Resolving arguments to call-back functions
===========================================

F2PY generated interfaces are very flexible with respect to call-back
arguments.  For each call-back argument an additional optional
argument ``<name>_extra_args`` is introduced by F2PY. This argument
can be used to pass extra arguments to user provided call-back
functions.

If a F2PY generated wrapper function expects the following call-back
argument::

  def fun(a_1,...,a_n):
     ...
     return x_1,...,x_k

but the following Python function

::

  def gun(b_1,...,b_m):
     ...
     return y_1,...,y_l

is provided by a user, and in addition,

::

  fun_extra_args = (e_1,...,e_p)

is used, then the following rules are applied when a Fortran or C
function evaluates the call-back argument ``gun``:

* If ``p == 0`` then ``gun(a_1, ..., a_q)`` is called, here
  ``q = min(m, n)``.
* If ``n + p <= m`` then ``gun(a_1, ..., a_n, e_1, ..., e_p)`` is called.
* If ``p <= m < n + p`` then ``gun(a_1, ..., a_q, e_1, ..., e_p)`` is called, here
  ``q=m-p``.
* If ``p > m`` then ``gun(e_1, ..., e_m)`` is called.
* If ``n + p`` is less than the number of required arguments to ``gun``
  then an exception is raised.

If the function ``gun`` may return any number of objects as a tuple; then
the following rules are applied:

* If ``k < l``, then ``y_{k + 1}, ..., y_l`` are ignored.
* If ``k > l``, then only ``x_1, ..., x_l`` are set.


Common blocks
==============

F2PY generates wrappers to ``common`` blocks defined in a routine
signature block. Common blocks are visible to all Fortran codes linked
to the current extension module, but not to other extension modules
(this restriction is due to the way Python imports shared libraries).  In
Python, the F2PY wrappers to ``common`` blocks are ``fortran`` type
objects that have (dynamic) attributes related to the data members of
the common blocks. When accessed, these attributes return as NumPy array
objects (multidimensional arrays are Fortran-contiguous) which
directly link to data members in common blocks. Data members can be
changed by direct assignment or by in-place changes to the
corresponding array objects.

Consider the following Fortran 77 code:

  .. literalinclude:: ./code/common.f
     :language: fortran

and wrap it using ``f2py -c -m common common.f``.

In Python:

  .. literalinclude:: ./code/results/common_session.dat
     :language: python


Fortran 90 module data
=======================

The F2PY interface to Fortran 90 module data is similar to the handling of Fortran 77
common blocks.

Consider the following Fortran 90 code:

  .. literalinclude:: ./code/moddata.f90
     :language: fortran

and wrap it using ``f2py -c -m moddata moddata.f90``.

In Python:

  .. literalinclude:: ./code/results/moddata_session.dat
     :language: python


Allocatable arrays
===================

F2PY has basic support for Fortran 90 module allocatable arrays.

Consider the following Fortran 90 code:

  .. literalinclude:: ./code/allocarr.f90
     :language: fortran

and wrap it using ``f2py -c -m allocarr allocarr.f90``.

In Python:

  .. literalinclude:: ./code/results/allocarr_session.dat
     :language: python