Skip to content

Commit

Permalink
Add tutorial on using fluids from other languages
Browse files Browse the repository at this point in the history
  • Loading branch information
CalebBell committed Dec 7, 2024
1 parent bd5e1ec commit 5e9a06e
Show file tree
Hide file tree
Showing 35 changed files with 358 additions and 76 deletions.
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Module Contents:
data.rst
sample_programs.rst
developers.rst

language_examples/index

Installation
------------
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
74 changes: 0 additions & 74 deletions dev/D/source/app.d → docs/language_examples/D/source/app.d
Original file line number Diff line number Diff line change
@@ -1,77 +1,3 @@
// import std.stdio;
// import pyd.pyd;
// import pyd.embedded;
// import std.format;
//
// // Initialize Python before using it
// shared static this() {
// py_init();
// }
//
// // Helper to run Python expressions and handle errors
// auto pyEval(T)(string expr, string namespace = "") {
// try {
// return py_eval!T(expr, namespace);
// } catch (Exception e) {
// writeln("Error evaluating: ", expr);
// writeln("Error: ", e.msg);
// throw e;
// }
// }
//
// void testFluids() {
// writeln("\nTesting basic fluids functionality...");
//
// // Import fluids and create a PydObject reference
// PydObject fluidsModule = py_import("fluids");
// writeln("✓ Successfully imported fluids");
//
// // Get version using attribute access
// string fluidsVersion = fluidsModule.__version__.to_d!string();
// writeln("✓ Fluids version: ", fluidsVersion);
//
// double Re = pyEval!double("Reynolds(V=2.5, D=0.1, rho=1000, mu=0.001)", "fluids");
// writeln("✓ Reynolds number calculation: ", Re);
// assert(Re > 0);
//
// // Test friction factor
// double fd = pyEval!double("friction_factor(Re=1e5, eD=0.0001)", "fluids");
// writeln("✓ Friction factor: ", fd);
// assert(0 < fd && fd < 1);
// }
//
// void testAtmosphere() {
// writeln("\nTesting atmosphere calculations...");
//
// PydObject fluidsModule = py_import("fluids");
// PydObject atm = py_eval("ATMOSPHERE_1976(5000.0)", "fluids");
//
//
// // Get properties
// double temp = atm.T.to_d!double();
// double pressure = atm.P.to_d!double();
// double density = atm.rho.to_d!double();
//
// writeln("At 5000m elevation:");
// writeln("✓ Temperature: ", temp);
// writeln("✓ Pressure: ", pressure);
// writeln("✓ Density: ", density);
// }
//
// void main() {
// try {
// writeln("Running fluids tests from D...");
// testFluids();
// testAtmosphere();
// writeln("\nAll tests completed!");
// } catch (Exception e) {
// writeln("Test failed with error: ", e.msg);
// }
// }




import std.stdio;
import pyd.pyd;
import pyd.embedded;
Expand Down
23 changes: 23 additions & 0 deletions docs/language_examples/c.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
C Integration
=============

This example demonstrates how to use fluids from C.

Source Code
-----------

.. literalinclude:: C/fluids_test.c
:language: c
:linenos:

Requirements
------------

- Python with fluids installed
- Development python libraries

Usage Notes
-----------

- The example demonstrates basic integration with fluids
- No overhead (1.3 microsecond friction factor, 7 microsecond tank creation)
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using PyCall
using Printf
# Import fluids
const fluids = pyimport("fluids")

function test_fluids()
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
23 changes: 23 additions & 0 deletions docs/language_examples/cpp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
C++ Integration
===============

This example demonstrates how to use fluids from cpp.

Source Code
-----------

.. literalinclude:: cpp/main.cpp
:language: cpp
:linenos:

Requirements
------------

- Python with fluids installed
- pybind11

Usage Notes
-----------

- The example demonstrates basic integration with fluids
- Essentially zero overhead - 1.7 microseconds for friction factor, 8 microseconds for tank creation; only C using the has been observed to have a faster interface, able to save < 0.5 microseconds/call
File renamed without changes.
File renamed without changes.
24 changes: 24 additions & 0 deletions docs/language_examples/d.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
D Integration
=============

This example demonstrates how to use fluids from D.

Source Code
-----------

.. literalinclude:: D/source/app.d
:language: d
:linenos:

Requirements
------------

- Python with fluids installed
- PyD: https://pyd.readthedocs.io/en/latest/

Usage Notes
-----------

- The example demonstrates basic integration with fluids
- 15 microsecond friction factor, 36 microsecond tank creation observed by author
- The script was easy to develop
23 changes: 23 additions & 0 deletions docs/language_examples/fortran.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
fortran Integration
===================

This example demonstrates how to use fluids from fortran.

Source Code
-----------

.. literalinclude:: fortran/fluids_test.f90
:language: fortran
:linenos:

Requirements
------------

- Python with fluids installed

Usage Notes
-----------

- The example is incomplete. `iso_c_binding` is used to interface without actually writing C code.
- The speed is comparable to pybind11, 2 microseconds per friction factor call.
- The excess amount of code required to interface the two languages is very significant
File renamed without changes.
24 changes: 24 additions & 0 deletions docs/language_examples/go.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
go Integration
==============

This example demonstrates how to use fluids from go.

Source Code
-----------

.. literalinclude:: go/main.go
:language: go
:linenos:

Requirements
------------

- Python with fluids installed
- cgo

Usage Notes
-----------

- cgo and low-level python primitives are used to interface the two languages
- 3.5 microsecond friction factor, 25 microsecond tank creation observed by author
- There is some memory issue in the example that causes it to crash at the end
File renamed without changes.
File renamed without changes.
24 changes: 24 additions & 0 deletions docs/language_examples/haskell.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
haskell Integration
===================

This example demonstrates how to use fluids from haskell.

Source Code
-----------

.. literalinclude:: haskell/app/Main.hs
:language: haskell
:linenos:

Requirements
------------

- Python with fluids installed
- cabal
- haskell cpython package

Usage Notes
-----------

- The example is incomplete and crashes on termination
- Performance is 2 microsecond for friction factor, indicating there is very little overhead
File renamed without changes.
File renamed without changes.
File renamed without changes.
57 changes: 57 additions & 0 deletions docs/language_examples/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Language Integration Examples
=============================

Fluids can be called from many different programming languages through various Python bindings and interfaces.
These examples demonstrate some of the ways to communicate with or embed Python into a program written in another language.

The examples focus on showing how to call functions (including optional arguments), classes and their various methods, and the performance of the language binding.

The author has developed these examples with AI assistance and does not claim to be proficient in all of these languages.
The difficulty of a language integration varies from trivial in Julia to manually managing reference counts and dealing with the C API in Fortran.
The intent of these examples is to show possibilities, not to provide complete wrappers for all functionality.

Available Languages
-------------------

.. toctree::
:maxdepth: 1

julia.rst
perl.rst
ruby.rst
r.rst
octave.rst
lisp.rst
cpp.rst
c.rst
fortran.rst
go.rst
haskell.rst
nim.rst
d.rst

Common Considerations
---------------------

When using fluids from another programming language, keep in mind:

* Performance will be lower due to the overhead of cross-language communication.
Compiled languages like C++, C, D, Fortran, Go, haskell, and Nim tend to have a constant
overhead of a couple microseconds per call, and any serialization/data copying costs
which depending on the speed of the fluids function can be 2-3x the fluids call itself.
* If you use your compiler's FASTMATH setting or floating point settings (things like FLDCW/FSTCW/MXCSR) those settings will impact Python's own floating point handling
* For compiled languages error handling can be difficult - checking variable ranges in your own language may be wise

Notes for Package Maintainers
-----------------------------

If you're maintaining a package that wraps fluids for your language, feel free to let the author know (especially if it's open source!).

Contributing
------------

If you'd like to improve these examples or add support for another language:

1. Fork the fluids repository
2. Add your example including documentation
3. Submit a pull request
22 changes: 22 additions & 0 deletions docs/language_examples/julia.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
julia Integration
=================

This example demonstrates how to use fluids from julia.

Source Code
-----------

.. literalinclude:: check_fluids_can_be_called_from_julia.jl
:language: julia
:linenos:

Requirements
------------

- Python with fluids installed
- PyCall.jl package

Usage Notes
-----------

- 8 microsecond friction factor, 20 microsecond tank creation observed by author
23 changes: 23 additions & 0 deletions docs/language_examples/lisp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
lisp Integration
================

This example demonstrates how to use fluids from lisp.

Source Code
-----------

.. literalinclude:: check_fluids_can_be_called_from_lisp.lisp
:language: lisp
:linenos:

Requirements
------------

- Python with fluids installed
- py4cl: https://github.com/bendudson/py4cl

Usage Notes
-----------

- The example demonstrates basic integration with fluids
- 80 microsecond friction factor, 200 microsecond tank creation observed by author
23 changes: 23 additions & 0 deletions docs/language_examples/nim.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
nim Integration
===============

This example demonstrates how to use fluids from nim.

Source Code
-----------

.. literalinclude:: nim/check_fluids_can_be_called_from_nim.nim
:language: nim
:linenos:

Requirements
------------

- Python with fluids installed
- Nimpy: https://github.com/yglukhov/nimpy

Usage Notes
-----------

- Nim has a great package manager and is easy to read/write. This example took 10 minutes to develop.
- 1.5 microsecond friction factor, 9 microsecond tank creation observed by author; very comparable to pybind11
Loading

0 comments on commit 5e9a06e

Please sign in to comment.