You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This folder contains Ard's Python-Julia integration utilities for FLOWFarm.
4
4
5
+
## Julia setup (required before first use)
6
+
7
+
FLOWFarm runs inside Julia via [JuliaCall](https://juliapy.github.io/PythonCall.jl/stable/). You need Julia installed before running any FLOWFarm components. Users who do not use FLOWFarm do not need Julia at all — it is loaded lazily only when a FLOWFarm component is initialized.
8
+
9
+
### 1. Install Julia via juliaup (recommended)
10
+
11
+
[juliaup](https://github.com/JuliaLang/juliaup) is the official Julia version manager. Install it with:
12
+
13
+
```bash
14
+
curl -fsSL https://install.julialang.org | sh
15
+
```
16
+
17
+
Install any recent stable Julia release (1.10 or later):
18
+
19
+
```bash
20
+
juliaup add release
21
+
juliaup default release
22
+
```
23
+
24
+
Verify:
25
+
26
+
```bash
27
+
julia --version
28
+
```
29
+
30
+
Ard's Julia environment has no hard version pin. The `Manifest.toml` is not committed to the repository — it is generated locally the first time you run a FLOWFarm component, so it will always match your installed Julia version. If you need to generate it ahead of time (e.g. on a cluster before a job runs), see step 2.
31
+
32
+
### 2. Pre-generate the Julia environment (optional)
33
+
34
+
On first use Ard will resolve and instantiate the Julia environment automatically. If you prefer to do this ahead of time — for example on an HPC cluster node without internet access at runtime — run once from your terminal:
35
+
36
+
```bash
37
+
julia --project="<path-to-ard>/ard/flowfarm/julia_env" -e "using Pkg; Pkg.resolve(); Pkg.instantiate()"
38
+
```
39
+
40
+
Replace `<path-to-ard>` with the absolute path to the `Ard` directory. This downloads FLOWFarm and its dependencies. It may take several minutes on first run.
41
+
42
+
### 3. Install the JuliaCall Python package
43
+
44
+
```bash
45
+
pip install juliacall
46
+
```
47
+
48
+
`juliacall` is not listed in Ard's core dependencies because it is only needed for FLOWFarm. Install it separately before using FLOWFarm components.
49
+
5
50
## What this integration does
6
51
7
52
- Boots Julia through JuliaCall.
8
53
- Activates Ard's local Julia environment (`julia_env`).
9
54
- Loads FLOWFarm and builds farm and sparse structs for Ard components.
10
55
- Exposes helper functions used by the component wrapper in `ard/farm_aero/flowfarm.py`.
11
56
12
-
## Threading behavior
57
+
## Threading and parallelism
58
+
59
+
### OpenMDAO does not multithread
13
60
14
-
- Ard supports Julia threading through JuliaCall.
15
-
- The FLOWFarm update callback used by Ard is implemented in pure Julia (not Python callback) to avoid PythonCall thread-safety crashes.
16
-
- If you configure Julia threads with environment variables, set them **before** importing Ard/JuliaCall.
61
+
OpenMDAO is single-threaded by design. Its solver loops (Newton, Gauss-Seidel, NLBGS, etc.) are serial. The only parallelism OpenMDAO exposes is MPI-based **process** parallelism via `ParallelGroup`, which spawns separate processes — not threads. This means OpenMDAO will never call the FLOWFarm component from multiple threads simultaneously, so there is no concurrency risk from the OpenMDAO layer.
17
62
18
-
Recommended JuliaCall env options for threaded runs:
63
+
### Julia internal threading (FLOWFarm parallelism)
19
64
20
-
-`PYTHON_JULIACALL_THREADS=<N or auto>`
21
-
-`PYTHON_JULIACALL_HANDLE_SIGNALS=yes`
22
-
- (optional) `OPENBLAS_NUM_THREADS=1`, `OMP_NUM_THREADS=1` to avoid nested thread oversubscription
65
+
Threading in this integration refers to Julia's own thread pool, which FLOWFarm can use internally to parallelize wake calculations across turbines. This is separate from and independent of OpenMDAO.
66
+
67
+
Julia's thread count is fixed at startup and cannot be changed at runtime. Configure it **before** importing Ard or JuliaCall:
68
+
69
+
```python
70
+
import os
71
+
os.environ["PYTHON_JULIACALL_THREADS"] ="4"# or "auto" to use all cores
For threaded runs on shared-memory machines, also consider limiting BLAS and OpenMP thread pools to avoid nested oversubscription (Julia threads × BLAS threads × cores):
76
+
77
+
```python
78
+
os.environ["OPENBLAS_NUM_THREADS"] ="1"
79
+
os.environ["OMP_NUM_THREADS"] ="1"
80
+
```
81
+
82
+
These must be set before the first `import ard` call in your script or notebook.
83
+
84
+
### Why a pure Julia callback
85
+
86
+
The FLOWFarm update callback in Ard is implemented entirely in Julia (not as a Python callable passed into Julia). This is required for thread safety: JuliaCall does not support calling back into Python from Julia threads other than the main thread. Using a pure Julia callback avoids this restriction and allows FLOWFarm to use all available Julia threads.
23
87
24
88
## Tolerance behavior
25
89
@@ -42,11 +106,45 @@ modeling_options:
42
106
43
107
## Troubleshooting
44
108
45
-
- Kernel/process crash when threads > 1:
46
-
- Ensure pure Julia callback path is active (current Ard default).
47
-
- Ensure thread env vars are set before importing Ard.
48
-
- Start with `PYTHON_JULIACALL_THREADS=1`, then increase.
49
-
- Julia environment mismatch errors:
50
-
- Re-instantiate the local Julia env in `julia_env`.
51
-
- Confirm FLOWFarm revision/pin is compatible with your Julia runtime.
109
+
### Julia manifest warnings on first run
110
+
111
+
If you see warnings like "manifest resolved with a different julia version" or "project dependencies have changed since the manifest was last resolved", it means the local `Manifest.toml` is missing or stale. Ard will attempt to rebuild it automatically. If it does not, run:
112
+
113
+
```bash
114
+
julia --project="<path-to-ard>/ard/flowfarm/julia_env" -e "using Pkg; Pkg.resolve(); Pkg.instantiate()"
115
+
```
116
+
117
+
Then restart your Jupyter kernel. The `Manifest.toml` is not committed to the repository — it is always generated locally for your Julia version.
118
+
119
+
### Revise / DistributedExt error in Jupyter
120
+
121
+
```
122
+
Error during loading of extension DistributedExt of Revise
123
+
```
124
+
125
+
This comes from your **global** Julia environment, not Ard's. JuliaCall triggers the IPython/Jupyter juliacall extension on import, which loads Revise from your global env. Fix it by running:
126
+
127
+
```bash
128
+
julia -e "using Pkg; Pkg.add(\"Distributed\"); Pkg.resolve()"
129
+
```
130
+
131
+
### Wrong Julia version being used
132
+
133
+
If Julia 1.11+ is picked up instead of 1.10, check your `PATH`. `juliaup default 1.10` sets the default for commands run via juliaup, but if `/opt/homebrew/bin/julia` or another system Julia takes precedence in your shell, JuliaCall may use that instead.
134
+
135
+
To force a specific version for a notebook session, add this to the **first cell** before any other imports:
0 commit comments