Skip to content

Commit e6b5869

Browse files
committed
Update docs
1 parent 29543ca commit e6b5869

6 files changed

Lines changed: 29 additions & 79 deletions

File tree

docs/NAVIGATION.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ See https://oprypin.github.io/mkdocs-literate-nav/
66
- [Home](index.md)
77
- [Installation](installation.md)
88
- [How-to guides](how-to-guides/index.md)
9-
- [Do a basic calculation](how-to-guides/basic-calculation.md)
10-
- [Run code in a notebook](how-to-guides/run-code-in-a-notebook.py)
119
- [Tutorials](tutorials/index.md)
1210
- [Further background](further-background/index.md)
1311
- [Dependency pinning and testing](further-background/dependency-pinning-and-testing.md)
12+
- [Wrapping Fortran derived types](further-background/wrapping-fortran-derived-types.md)
1413
- [Development](development.md)
1514
- [API reference](api/example_fgen_basic/)
1615
- [Fortran API](fortran-api/home.html)

IMPLEMENTATION-NOTES.md renamed to docs/further-background/wrapping-fortran-derived-types.md

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
@Marco please move these into `docs/further-background/wrapping-derived-types.md` (and do any other clean up and formatting fixes you'd like)
1+
# Wrapping derived types
2+
3+
Here we describe our approach to wrapping Fortran derived types.
24

35
## What is the goal?
46

@@ -30,7 +32,7 @@ the original Python object will remain unchanged
3032

3133
This assumption makes ownership and memory management clear.
3234
We do not need to keep instances around as views
33-
and worry about consistency across the Python-Fortran interface.
35+
and therefore do not need to worry about consistency across the Python-Fortran interface.
3436
Instead, we simply pass data back and forth,
3537
and the normal rules of data consistency within each programming language apply.
3638

@@ -45,57 +47,54 @@ The manager module has two key components:
4547
In practice, they are essentially temporary variables.
4648
1. an allocatable array of logical (boolean) values,
4749
call this `available_array`.
48-
The convention is that, if `available_array(i)`, where `i` is an integer,
49-
is `.true.` then the instance at `instance_array(i)` is available for the manager to use,
50-
otherwise the manager assumes that the instance is already being used for some purpose
50+
The convention is that, if `available_array(i)` is `.true.`,
51+
where `i` is an integer,
52+
then the instance at `instance_array(i)` is available for the manager to use.
53+
Otherwise, the manager assumes that the instance is already being used for some purpose
5154
and therefore cannot be used for whatever operation is currently being performed.
5255

5356
This setup allows us to effectively pass derived types back and forth between Python and Fortran.
5457

55-
Whenever we need to return a derived type to Python, we:
56-
57-
[TODO think about retrieving multiple derived types at once]
58+
Whenever we need to return a derived type (or derived types) to Python, we:
5859

59-
1. get the derived type from whatever Fortran function or subroutine created it,
60+
1. get the derived type(s) from whatever Fortran function or subroutine created it,
6061
call this `derived_type_original`
6162
1. find an index, `idx`, in `available_array` such that `available_array(idx)` is `.true.`
6263
1. set `instance_array(idx)` equal to `derived_type_original`
6364
1. we return `idx` to Python
64-
- `idx` is an integer, so we can return this easily to Python using `f2py`
65-
1. we then create a Python object with an API that mirrors `derived_type_original`
65+
- `idx` is an integer (or integers), so we can return this easily to Python using `f2py`
66+
1. we then create a Python object (or objects) with an API that mirrors `derived_type_original`
6667
using the class method `from_instance_index`.
67-
This class method is [TODO or will be] auto-generated via `pyfgen`
68+
This class method is auto-generated via `pyfgen`
69+
(TODO: implement auto-generation)
6870
and handles retrieval of all the attribute values of `derived_type_original`
6971
from Fortran and sets them on the Python object that is being instantiated
7072
- we can do this as, if you dig down deep enough, all attributes eventually
7173
become primitive types which can be passed back and forth using `f2py`,
7274
it can just be that multiple levels of recursion are needed
7375
if you have derived types that themselves have derived type attributes
74-
1. we then call the manager [TODO I think this will end up being wrapper, we can tighten the language later]
75-
module's `finalise_instance` function to free the (temporary) instance
76+
1. we then call the wrapper module's `finalise_instance` function to free the (temporary) instance(s)
7677
that was used by the manager
78+
(we cannot access the manager module directly as it cannot be wrapped by `f2py`)
7779
- this instance is no longer needed because all the data has been transferred to Python
78-
1. we end up with a Python instance that has the result
80+
1. we end up with a Python instance(s) that has the result
7981
and no extra/leftover memory footprint in Fortran
8082
(and leave Fortran to decide whether to clean up `derived_type_original` or not)
8183

82-
Whenever we need to pass a derived type to Fortran, we:
83-
84-
[TODO think about passing multiple derived types at once]
84+
Whenever we need to pass a derived type (or derived types) to Fortran, we:
8585

86-
1. call the manager [TODO I think this will end up being wrapper, we can tighten the language later]
87-
module's `get_free_instance_index` function to get an available index to use for the passing
88-
1. call the manager [TODO I think this will end up being wrapper, we can tighten the language later]
89-
module's `build_instance` function with the index we just received
90-
plus all of the Python object's attribute values
91-
- on the Fortran side, there is now an instantiated derived type, ready for use
86+
1. get an instance index we can use to communicate with Fortran
87+
1. call the Python object's `build_fortran_instance` method,
88+
which returns the instance index where the object was created on the Fortran side.
89+
Under the hood, this calls the wrapper module's
90+
`get_free_instance_index` and `build_instance` functions
91+
1. on the Fortran side, there is now an instantiated derived type, ready for use
9292
1. call the wrapped Fortran function of interest,
93-
except we pass the instance index instead of the derived type
93+
except we pass the instance index instead of the actual Python object itself
9494
1. on the Fortran side, retrieve the instantiated index from the manager module
9595
and use this to call the Fortran function/subroutine of interest
9696
1. return the result from Fortran back to Python
97-
1. call the manager [TODO I think this will end up being wrapper, we can tighten the language later]
98-
module's `finalise_instance` function to free the (temporary) instance
97+
1. call the wrapper module's `finalise_instance` function to free the (temporary) instance
9998
that was used to pass the instance in the first place
10099
- this instance is no longer needed because all the data has been transferred and used by Fortran
101100
1. we end up with the result of the Fortran callable back in Python
@@ -175,9 +174,7 @@ and normal Python rules apply in Python
175174
Note: this section was never properly finished.
176175
Once we started trying to write it,
177176
we realised how hard it would be to avoid weird edge cases
178-
so we stopped and changed to [our current solution][Our solution]
179-
(@Marco please check that this internal cross-reference works
180-
once the docs are built).
177+
so we stopped and changed to [our current solution][our-solution].
181178

182179
To pass derived types back and forth across the Python-Fortran interface,
183180
we introduce a 'manager' module for all derived types.

docs/how-to-guides/basic-calculation.md

Lines changed: 0 additions & 10 deletions
This file was deleted.

docs/how-to-guides/index.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,3 @@
33
This part of the project documentation
44
focuses on a **problem-oriented** approach.
55
We'll go over how to solve common tasks.
6-
7-
## How can I do a basic calculation?
8-
9-
<!---
10-
You will probably want to remove this bit.
11-
12-
It is included to demonstrate how to include sub-sections
13-
and cross-reference them.
14-
-->
15-
16-
If you want to do a basic calculation,
17-
see ["How to do a basic calculation"][how-to-do-a-basic-calculation].

docs/how-to-guides/run-code-in-a-notebook.py

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/example_fgen_basic/error_v/creation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def create_error(inv: int) -> ErrorV:
4141
Input value
4242
4343
If odd, the error code is
44-
[NO_ERROR_CODE][example_fgen_basic.error_v.NO_ERROR_CODE].
44+
[NO_ERROR_CODE][example_fgen_basic.error_v.error_v.NO_ERROR_CODE].
4545
If even, the error code is 1.
4646
If a negative number is supplied, the error code is 2.
4747

0 commit comments

Comments
 (0)