Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update C and Fortran docs examples #97

Merged
merged 26 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fd4756b
Rename conda env file for C example
mdpiper Apr 2, 2024
2d132d2
Match C example babel.toml with 'babelize sample-config' output
mdpiper Apr 2, 2024
3b433d6
Update C example through babelizing
mdpiper Apr 2, 2024
edf60ca
Rename C example
mdpiper Apr 2, 2024
db955a9
Update reference to C example from Fortran example
mdpiper Apr 2, 2024
98cf829
Update C example through installation
mdpiper Apr 3, 2024
fa14f96
Replace Finder image with 'tree' output to show final directory struc…
mdpiper Apr 3, 2024
b82b1b4
Include bmi-tester in example environment
mdpiper Apr 3, 2024
e4727ad
Move parameters for C example to their own directory
mdpiper Apr 3, 2024
0632fa5
Move Python examples to c directory
mdpiper Apr 3, 2024
c4d15ea
Include pymt in example environment
mdpiper Apr 3, 2024
ae533ff
Update Python examples for C heat model
mdpiper Apr 3, 2024
ac642d3
Update location of C Python example
mdpiper Apr 3, 2024
8d5a121
Finish updating C example
mdpiper Apr 3, 2024
f571e71
Show a smaller tree for final result
mdpiper Apr 3, 2024
f202a97
Update Fortran environment file; relax bmi-tester version requirement
mdpiper Apr 3, 2024
7460ecb
Update HeatF babelizer config file
mdpiper Apr 3, 2024
1270529
Minor edits; fix typos
mdpiper Apr 3, 2024
5c8b334
Add Fortran-Python examples
mdpiper Apr 3, 2024
2be54ed
Fix typo
mdpiper Apr 3, 2024
5703222
Update the Fortran example to match the C example
mdpiper Apr 3, 2024
049917b
Add news fragment
mdpiper Apr 3, 2024
f636241
Add code of conduct document to repo and docs
mdpiper Apr 4, 2024
daf0991
Remove obsolete docs makefiles
mdpiper Apr 4, 2024
f811c96
Add news fragments
mdpiper Apr 4, 2024
4f42303
Merge branch 'develop' into mdpiper/revise-docs-examples
mcflugen Apr 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions docs/source/babel_heatc.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
[library]
[library.HeatModel]
# See https://babelizer.readthedocs.io/ for more information

# Describe the library being wrapped.
[library.HeatC]
language = "c"
library = "bmiheatc"
header = "bmi_heat.h"
entry_point = "register_bmi_heat"

# Describe compiler options need to build the library being wrapped.
[build]
undef_macros = []
define_macros = []
Expand All @@ -13,17 +16,26 @@ library_dirs = []
include_dirs = []
extra_compile_args = []

# Describe the newly wrapped package.
[package]
name = "pymt_heatc"
requirements = [""]
requirements = []

[info]
github_username = "pymt-lab"
package_author = "csdms"
package_author_email = "[email protected]"
package_license = "MIT"
summary = "PyMT plugin for the C heat model"
package_license = "MIT License"
summary = "PyMT component for the C heat model"

[ci]
python_version = ["3.9"]
os = ["linux", "mac", "windows"]
python_version = [
"3.10",
"3.11",
"3.12",
]
os = [
"linux",
"mac",
"windows",
]
4 changes: 2 additions & 2 deletions docs/source/environment.yml → docs/source/environment-c.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A conda environment file for the babelizer example
name: wrap
# A conda environment file for the babelizer C example
name: wrap-c
channels:
- conda-forge
dependencies:
Expand Down
163 changes: 66 additions & 97 deletions docs/source/example.rst → docs/source/example-c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,79 +9,79 @@ To simplify package management in the example,
we'll use :term:`conda`.
We'll also use :term:`git` to obtain the model source code.

This is a somewhat long example.
To break it up,
here are the steps we'll take:
Here are the steps we'll take to complete this example:

#. Create a :term:`conda environment` that includes software to compile the
model and wrap it with the *babelizer*
#. Clone the `bmi-example-c`_ repository from GitHub and build the
*heat* model from source
#. Create a *babelizer* input file describing the *heat* model
#. Run the *babelizer* to generate Python bindings, then build the bindings
#. Run the *babelizer* to generate a Python package, then build and install the package
#. Show the *heat* model running in Python through *pymt*

Before we begin,
create a directory to hold our work:

.. code:: bash

$ mkdir build && cd build
mkdir example-c && cd example-c

This directory is a starting point;
we'll make new directories under it as we proceed through the example.
In the end,
the directory structure under ``build`` should look like that in Figure 1.
the directory structure under ``example-c`` should look like that in Figure 1.

.. figure:: _static/babelizer-bmi-example-c.png
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using a png for this, how about using the output of a tree command? Apart from looking better (in my opinion), it would be easier to keep up-to-date and would be one less binary file in version control.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about removing it entirely because it's hard to maintain. It was a request from a reviewer on the JOSS paper.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in fa14f96.

:align: center
:alt: Directory structure after completing example

Figure 1: Directory structure after completing example.
Figure 1: Directory structure after completing the C example.

Set up a conda environment
--------------------------

Start by setting up a :term:`conda environment` that includes the *babelizer*,
as well as a toolchain to build and install the model.
The necessary packages are listed in the conda environment file
:download:`environment.yml`:
:download:`environment-c.yml`:

.. include:: environment.yml
.. include:: environment-c.yml
:literal:

:download:`Download <environment.yml>` this file
and create the new environment with:
:download:`Download <environment-c.yml>` this file
and place it in the ``example-c`` directory you created above.
Create the new environment with:

.. code:: bash

$ conda env create --file=environment.yml
conda env create --file environment-c.yml

When this command completes,
activate the environment
(on Linux and macOS, you may have to use ``source`` instead of ``conda``):

.. code:: bash

$ conda activate wrap
conda activate wrap-c

The *wrap* environment now contains all the dependencies needed
The *wrap-c* environment now contains all the dependencies needed
to build, install, and wrap the *heat* model.


Build the *heat* model from source
----------------------------------

Clone the `bmi-example-c`_ repository from GitHub:
From the ``example-c`` directory,
clone the `bmi-example-c`_ repository from GitHub:

.. code:: bash

$ git clone https://github.com/csdms/bmi-example-c
git clone https://github.com/csdms/bmi-example-c

There are general `instructions`_ in the repository for building and installing
this package on Linux, macOS, and Windows.
We'll augment those instructions
with the note that we're installing into the *wrap* conda environment,
with the note that we're installing into the *wrap-c* conda environment,
so the ``CONDA_PREFIX`` environment variable
should be used to specify the install path.

Expand All @@ -93,128 +93,89 @@ use these commands to build and install the *heat* model:

.. code:: bash

$ cd bmi-example-c
$ mkdir _build && cd _build
$ cmake .. -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
$ make install
cd bmi-example-c
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
make install

Verify the install by testing for the existence of the header
of the library containing the compiled *heat* model:

.. code:: bash

$ test -f $CONDA_PREFIX/include/bmi_heat.h ; echo $?
test -f $CONDA_PREFIX/include/bmi_heat.h ; echo $?

A return of zero indicates success.

Windows
.......

Building on Windows requires
Microsoft Visual Studio 2017 or Microsoft Build Tools for Visual Studio 2017.
Microsoft Visual Studio 2019 or Microsoft Build Tools for Visual Studio 2019.
To build and install the *heat* model,
the following commands must be run in a `Developer Command Prompt`_:

.. code::
.. code:: bat

> cd bmi-example-c
> mkdir _build && cd _build
> cmake .. ^
-G "NMake Makefiles" ^
-DCMAKE_INSTALL_PREFIX=%CONDA_PREFIX% ^
-DCMAKE_BUILD_TYPE=Release
> cmake --build . --target install --config Release
cd bmi-example-c
mkdir build && cd build
cmake .. ^
-G "NMake Makefiles" ^
-DCMAKE_INSTALL_PREFIX=%CONDA_PREFIX% ^
-DCMAKE_BUILD_TYPE=Release
cmake --build . --target install --config Release

Verify the install by testing for the existence of the header
of the library containing the compiled *heat* model:

.. code::
.. code:: bat

> if not exist %LIBRARY_INC%\\bmi_heat.h exit 1
if not exist %LIBRARY_INC%\\bmi_heat.h exit 1

Create the *babelizer* input file
---------------------------------
Create a *babelizer* configuration file
---------------------------------------

The *babelizer* input file provides information to the *babelizer*
A *babelizer* configuration file provides information to the *babelizer*
about the model to be wrapped.
The input file is created with the ``babelize generate`` subcommand.

Return to our initial ``build`` directory and call ``babelize generate`` with:

.. code:: bash

$ cd ../..
$ babelize generate \
--package=pymt_heatc \
--summary="PyMT plugin for the C heat model" \
--language=c \
--library=bmiheatc \
--header=bmi_heat.h \
--entry-point=register_bmi_heat \
--name=HeatModel \
--requirement="" > babel_heatc.toml
Typically, we would use the ``babelize sample-config`` command
to create a sample configuration file, which could then be edited.
However, to simplify this example, we have provided a completed
configuration file for the *heat* model.
:download:`Download <babel_heatc.toml>` the file
:download:`babel_heatc.toml` and copy it to the ``build`` directory.

In this call,
the *babelizer* will also fill in default values;
e.g., author name, author email, GitHub username, and license.

The resulting file, :download:`babel_heatc.toml`,
will look something like this:
The configuration file looks like this:

.. include:: babel_heatc.toml
:literal:

For more information on the entries and sections of the *babelizer* input file,
For more information on the entries and sections of the *babelizer* configuration file,
see `Input file <./readme.html#input-file>`_.


Wrap the model with the *babelizer*
-----------------------------------

Generate Python bindings for the model with the ``babelize init`` subcommand:
From the ``example-c`` directory,
generate a Python package for the model with the ``babelize init`` command:

.. code:: bash

$ babelize init babel_heatc.toml
babelize init babel_heatc.toml

The results are placed in a new directory, ``pymt_heatc``,
under the current directory.

.. code:: bash

$ ls -aF pymt_heatc
./ MANIFEST.in recipe/
../ Makefile requirements-build.txt
.git/ README.rst requirements-library.txt
.github/ babel.toml requirements-testing.txt
.gitignore docs/ requirements.txt
CHANGES.rst meta/ setup.cfg
CREDITS.rst pymt_heatc/ setup.py
LICENSE pyproject.toml

Before we can build the Python bindings,
we must ensure that the dependencies required by the toolchain,
as well as any required by the model,
as specified in the *babelizer* input file (none in this case),
are satisfied.

Change to the ``pymt_heatc`` directory and install dependencies
into the conda environment:

.. code:: bash

$ cd pymt_heatc
$ conda install -c conda-forge \
--file=requirements-build.txt \
--file=requirements-testing.txt \
--file=requirements-library.txt \
--file=requirements.txt
Build and install the wrapped model
...................................

Now build the Python bindings with:
Change to the ``pymt_heatc`` directory,
then build and install the Python package with:

.. code:: bash

$ make install
pip install ."[dev]"

This command sets off a long list of messages,
at the end of which you'll hopefully see:
Expand All @@ -224,29 +185,37 @@ at the end of which you'll hopefully see:
Successfully installed pymt-heatc

Pause a moment to see what we've done.
Change back to the initial ``build`` directory,
Change back to the initial ``example-c`` directory,
make a new ``test`` directory,
and change to it:

.. code:: bash

$ cd ..
$ mkdir test && cd test
cd ..
mkdir test && cd test

Start a Python session and try the following commands:

.. code:: python

>>> from pymt_heatc import HeatModel
>>> m = HeatModel()
>>> print(m.get_component_name())
from pymt_heatc import HeatC
m = HeatC()
m.get_component_name()

You should see:

.. code:: bash

The 2D Heat Equation

We've imported the *heat* model,
written in C,
into Python!
Exit the Python session.

Test the BMI
............

At this point,
it's a good idea to run the *bmi-tester* (`GitHub repo <bmi-tester>`_)
over the model.
Expand Down
4 changes: 2 additions & 2 deletions docs/source/example-fortran.rst
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ then run it with:
$ python pymt_heatc_ex.py

Note that here we are actually running the Python script that
was developed for the :doc:`C example <example>`, not Fortran.
was developed for the :doc:`C example <example-c>`, not Fortran.
That is one of the powerful things about wrapping your
BMI-enabled model and accessing it via PyMT - it provides a
standardised interface, regardless of the underlying model
Expand All @@ -410,7 +410,7 @@ Using the *babelizer*, we wrapped the *heat* model, which is written in Fortran.
It can now be called as a *pymt* component in Python.

The steps for wrapping a model with the *babelizer* outlined in this example
can also be applied to models written in C (:doc:`see the example <example>`)
can also be applied to models written in C (:doc:`see the example <example-c>`)
and C++.


Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ User Guide

readme
cli
example
example-c
example-fortran
glossary

Expand Down