nanodisort 0.1.0.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nanodisort-0.1.0.dev1/.github/workflows/build.yml +59 -0
- nanodisort-0.1.0.dev1/.github/workflows/lint.yml +8 -0
- nanodisort-0.1.0.dev1/.github/workflows/test.yml +49 -0
- nanodisort-0.1.0.dev1/.gitignore +14 -0
- nanodisort-0.1.0.dev1/.pre-commit-config.yaml +15 -0
- nanodisort-0.1.0.dev1/.python-version +1 -0
- nanodisort-0.1.0.dev1/AGENTS.md +93 -0
- nanodisort-0.1.0.dev1/CITATION.cff +15 -0
- nanodisort-0.1.0.dev1/CMakeLists.txt +48 -0
- nanodisort-0.1.0.dev1/PKG-INFO +105 -0
- nanodisort-0.1.0.dev1/README.md +84 -0
- nanodisort-0.1.0.dev1/benchmarks/benchmark_batch.py +94 -0
- nanodisort-0.1.0.dev1/benchmarks/pytest.ini +7 -0
- nanodisort-0.1.0.dev1/docs/api/index.rst +10 -0
- nanodisort-0.1.0.dev1/docs/api/nanodisort.rst +94 -0
- nanodisort-0.1.0.dev1/docs/api/nanodisort.utils.phase_functions.rst +4 -0
- nanodisort-0.1.0.dev1/docs/conf.py +80 -0
- nanodisort-0.1.0.dev1/docs/dev.rst +107 -0
- nanodisort-0.1.0.dev1/docs/examples/getting_started.ipynb +186 -0
- nanodisort-0.1.0.dev1/docs/index.rst +132 -0
- nanodisort-0.1.0.dev1/docs/references.bib +61 -0
- nanodisort-0.1.0.dev1/docs/references.rst +4 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/COPYING +339 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/DISORT2.doc +1267 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/HOWTO_cdisort +214 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/Makefile_cdisort +76 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/README_cdisort +88 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/cdisort.c +11847 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/cdisort.h +1303 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/disotest.c +3023 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/locate.c +119 -0
- nanodisort-0.1.0.dev1/ext/cdisort-2.1.3/locate.h +40 -0
- nanodisort-0.1.0.dev1/pyproject.toml +129 -0
- nanodisort-0.1.0.dev1/src/nanodisort/__init__.py +294 -0
- nanodisort-0.1.0.dev1/src/nanodisort/_core.cpp +1019 -0
- nanodisort-0.1.0.dev1/src/nanodisort/_version.py +8 -0
- nanodisort-0.1.0.dev1/src/nanodisort/thread_pool.cpp +48 -0
- nanodisort-0.1.0.dev1/src/nanodisort/thread_pool.h +38 -0
- nanodisort-0.1.0.dev1/src/nanodisort/utils/__init__.py +5 -0
- nanodisort-0.1.0.dev1/src/nanodisort/utils/phase_functions.py +502 -0
- nanodisort-0.1.0.dev1/tests/__init__.py +1 -0
- nanodisort-0.1.0.dev1/tests/test_batch.py +428 -0
- nanodisort-0.1.0.dev1/tests/test_core.py +255 -0
- nanodisort-0.1.0.dev1/tests/test_disotest.py +1135 -0
- nanodisort-0.1.0.dev1/tests/test_error_handling.py +273 -0
- nanodisort-0.1.0.dev1/uv.lock +3449 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: Build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build_wheels:
|
|
10
|
+
name: Build wheels on ${{ matrix.os }}
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Build wheels
|
|
21
|
+
uses: pypa/cibuildwheel@v3.4.1
|
|
22
|
+
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
|
26
|
+
path: ./wheelhouse/*.whl
|
|
27
|
+
|
|
28
|
+
build_sdist:
|
|
29
|
+
name: Build source distribution
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Build sdist
|
|
35
|
+
run: pipx run build --sdist
|
|
36
|
+
|
|
37
|
+
- uses: actions/upload-artifact@v4
|
|
38
|
+
with:
|
|
39
|
+
name: cibw-sdist
|
|
40
|
+
path: dist/*.tar.gz
|
|
41
|
+
|
|
42
|
+
upload_pypi:
|
|
43
|
+
name: Publish to PyPI
|
|
44
|
+
needs: [build_wheels, build_sdist]
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
47
|
+
environment:
|
|
48
|
+
name: pypi
|
|
49
|
+
url: https://pypi.org/p/nanodisort
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/download-artifact@v4
|
|
54
|
+
with:
|
|
55
|
+
pattern: cibw-*
|
|
56
|
+
path: dist
|
|
57
|
+
merge-multiple: true
|
|
58
|
+
|
|
59
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test on ${{ matrix.os }} / Python ${{ matrix.python-version }}
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, macos-latest]
|
|
17
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install uv
|
|
28
|
+
uses: astral-sh/setup-uv@v3
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: |
|
|
34
|
+
uv sync --all-packages --all-extras
|
|
35
|
+
|
|
36
|
+
- name: Build extension
|
|
37
|
+
run: |
|
|
38
|
+
uv pip install -ve .
|
|
39
|
+
|
|
40
|
+
- name: Run tests
|
|
41
|
+
run: |
|
|
42
|
+
uv run pytest --cov=nanodisort --cov-report=xml --cov-report=term
|
|
43
|
+
|
|
44
|
+
- name: Upload coverage to Codecov
|
|
45
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
|
46
|
+
uses: codecov/codecov-action@v4
|
|
47
|
+
with:
|
|
48
|
+
file: ./coverage.xml
|
|
49
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.14.7
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
- repo: https://github.com/ComPWA/taplo-pre-commit
|
|
9
|
+
rev: v0.9.3
|
|
10
|
+
hooks:
|
|
11
|
+
- id: taplo-format
|
|
12
|
+
- repo: https://github.com/kynan/nbstripout
|
|
13
|
+
rev: 0.8.1
|
|
14
|
+
hooks:
|
|
15
|
+
- id: nbstripout
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to coding agents when working with this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
nanodisort is a Python binding for cdisort, a C implementation of the DISORT (Discrete Ordinates Radiative Transfer) solver. It provides a Pythonic interface to solve the radiative transfer equation in plane-parallel atmospheres with support for multiple scattering, absorption, emission, and various boundary conditions.
|
|
8
|
+
|
|
9
|
+
## Build & Development Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Setup development environment
|
|
13
|
+
uv sync --dev
|
|
14
|
+
|
|
15
|
+
# (Re)build C++ extension module
|
|
16
|
+
uv pip install -ve .
|
|
17
|
+
|
|
18
|
+
# Run all tests
|
|
19
|
+
uv run task test
|
|
20
|
+
|
|
21
|
+
# Run tests with coverage
|
|
22
|
+
uv run task test-cov
|
|
23
|
+
|
|
24
|
+
# Run a single test file
|
|
25
|
+
uv run pytest tests/test_disotest.py -v
|
|
26
|
+
|
|
27
|
+
# Run a specific test
|
|
28
|
+
uv run pytest tests/test_disotest.py::TestDisort01::test_case_1a -v
|
|
29
|
+
|
|
30
|
+
# Lint
|
|
31
|
+
uv run task lint
|
|
32
|
+
|
|
33
|
+
# Format
|
|
34
|
+
uv run task format
|
|
35
|
+
|
|
36
|
+
# Check (lint + format check)
|
|
37
|
+
uv run task check
|
|
38
|
+
|
|
39
|
+
# Build docs
|
|
40
|
+
uv run task docs
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
### Directory Structure
|
|
46
|
+
|
|
47
|
+
- `src/nanodisort/` - Python package with C++ bindings
|
|
48
|
+
- `src/nanodisort/_core.cpp` - nanobind C++ extension wrapping cdisort
|
|
49
|
+
- `src/nanodisort/utils/phase_functions.py` - Phase function moment generators
|
|
50
|
+
- `ext/cdisort-2.1.3/` - Vendored cdisort C library
|
|
51
|
+
- `tests/` - pytest test suite
|
|
52
|
+
- `benchmarks/` - pytest-benchmark suite
|
|
53
|
+
|
|
54
|
+
### Build System
|
|
55
|
+
|
|
56
|
+
- scikit-build-core for Python/CMake integration
|
|
57
|
+
- nanobind for C++17/Python bindings
|
|
58
|
+
- CMake builds cdisort as a static library, then links to the `_core` extension
|
|
59
|
+
|
|
60
|
+
### Core Components
|
|
61
|
+
|
|
62
|
+
**DisortState** (`__init__.py` wraps `_core.cpp`): Main solver interface
|
|
63
|
+
|
|
64
|
+
- Configure dimensions: `nstr`, `nlyr`, `nmom`, `ntau`, `numu`, `nphi`
|
|
65
|
+
- Set flags: `usrtau`, `usrang`, `lamber`, `planck`, `onlyfl`, `quiet`, `intensity_correction`, `spher`
|
|
66
|
+
- Set boundary conditions: `fbeam`, `umu0`, `phi0`, `fisot`, `albedo`, etc.
|
|
67
|
+
- Set optical properties: `dtauc` (layer optical depths), `ssalb` (single scattering albedo), `pmom` (phase function moments)
|
|
68
|
+
- Call `allocate()` then `solve()`
|
|
69
|
+
- Read outputs: `rfldir`, `rfldn`, `flup`, `dfdt`, `uu` (intensity), etc.
|
|
70
|
+
|
|
71
|
+
**Phase Functions** (`utils/phase_functions.py`): Generate Legendre moment arrays
|
|
72
|
+
|
|
73
|
+
- `isotropic(nmom)`, `rayleigh(nmom)`, `henyey_greenstein(gg, nmom)`
|
|
74
|
+
- `haze_l(nmom)`, `cloud_c1(nmom)` - tabulated aerosol/cloud phase functions
|
|
75
|
+
|
|
76
|
+
### Array Conventions
|
|
77
|
+
|
|
78
|
+
- C++ bindings handle Fortran-to-C array order conversion automatically
|
|
79
|
+
- `pmom` array shape: `(nmom_nstr+1, nlyr)` in C order
|
|
80
|
+
- `uu` intensity output shape: `(numu, ntau, nphi)` in C order
|
|
81
|
+
|
|
82
|
+
### Testing
|
|
83
|
+
|
|
84
|
+
- `test_disotest.py` - Ported tests from cdisort's disotest.c, validated against Van de Hulst, Sweigart, Garcia-Siewert benchmarks
|
|
85
|
+
- `test_core.py` - Basic solver functionality
|
|
86
|
+
- `test_batch.py` - Batch solve tests
|
|
87
|
+
- `test_error_handling.py` - Error condition tests
|
|
88
|
+
|
|
89
|
+
## Key Implementation Details
|
|
90
|
+
|
|
91
|
+
- Error handling: cdisort calls a registered callback that throws C++ exceptions, converted to Python RuntimeError by nanobind
|
|
92
|
+
- Memory: `DisortState.allocate()` must be called after setting dimensions and before setting arrays or calling `solve()`
|
|
93
|
+
- The `nmom` parameter controls phase function truncation; set `nmom >= nstr` for proper scattering
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
type: software
|
|
4
|
+
title: nanodisort
|
|
5
|
+
abstract: Python bindings for CDISORT, a C implementation of the DISORT (Discrete Ordinates Radiative Transfer) solver for plane-parallel atmospheres.
|
|
6
|
+
version: 0.1.0
|
|
7
|
+
license: GPL-3.0-or-later
|
|
8
|
+
repository-code: https://github.com/eradiate/nanodisort
|
|
9
|
+
authors:
|
|
10
|
+
- family-names: Leroy
|
|
11
|
+
given-names: Vincent
|
|
12
|
+
email: vincent.leroy@rayference.eu
|
|
13
|
+
- family-names: Emde
|
|
14
|
+
given-names: Claudia
|
|
15
|
+
email: claudia.emde@rayference.eu
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15...3.27)
|
|
2
|
+
project(nanodisort VERSION 0.1.0 LANGUAGES C CXX)
|
|
3
|
+
|
|
4
|
+
# Set C++17 standard
|
|
5
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
6
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
|
+
|
|
8
|
+
# Find Python and nanobind
|
|
9
|
+
find_package(Python 3.9 REQUIRED COMPONENTS Interpreter Development.Module)
|
|
10
|
+
find_package(nanobind CONFIG REQUIRED)
|
|
11
|
+
find_package(Threads REQUIRED)
|
|
12
|
+
|
|
13
|
+
# cdisort library sources
|
|
14
|
+
set(CDISORT_SOURCES
|
|
15
|
+
ext/cdisort-2.1.3/cdisort.c
|
|
16
|
+
ext/cdisort-2.1.3/locate.c
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
set(CDISORT_HEADERS
|
|
20
|
+
ext/cdisort-2.1.3/cdisort.h
|
|
21
|
+
ext/cdisort-2.1.3/locate.h
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Build static cdisort library
|
|
25
|
+
add_library(cdisort STATIC ${CDISORT_SOURCES} ${CDISORT_HEADERS})
|
|
26
|
+
target_include_directories(cdisort PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ext/cdisort-2.1.3)
|
|
27
|
+
target_compile_options(cdisort PRIVATE
|
|
28
|
+
-O3
|
|
29
|
+
-fPIC # Position independent code for shared library
|
|
30
|
+
)
|
|
31
|
+
target_link_libraries(cdisort PUBLIC m) # Link math library
|
|
32
|
+
|
|
33
|
+
# Python extension module using nanobind
|
|
34
|
+
nanobind_add_module(_core
|
|
35
|
+
src/nanodisort/_core.cpp
|
|
36
|
+
src/nanodisort/thread_pool.cpp
|
|
37
|
+
NB_STATIC # Use static linking with nanobind
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Link cdisort library to Python extension
|
|
41
|
+
target_link_libraries(_core PRIVATE cdisort Threads::Threads)
|
|
42
|
+
target_include_directories(_core PRIVATE
|
|
43
|
+
${CMAKE_CURRENT_SOURCE_DIR}/ext/cdisort-2.1.3
|
|
44
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src/nanodisort
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Install the extension module
|
|
48
|
+
install(TARGETS _core LIBRARY DESTINATION nanodisort COMPONENT python)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: nanodisort
|
|
3
|
+
Version: 0.1.0.dev1
|
|
4
|
+
Summary: Python bindings for cdisort radiative transfer solver
|
|
5
|
+
Author-Email: Vincent Leroy <vincent.leroy@rayference.eu>
|
|
6
|
+
License: GPL-3.0-or-later
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Science/Research
|
|
9
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
18
|
+
Requires-Python: <3.14,>=3.9
|
|
19
|
+
Requires-Dist: numpy>=1.20
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# nanodisort
|
|
23
|
+
|
|
24
|
+
Python bindings for [CDISORT](http://www.libradtran.org/doku.php?id=cdisort), a C implementation of the DISORT (Discrete Ordinates Radiative Transfer) solver.
|
|
25
|
+
|
|
26
|
+
## Overview
|
|
27
|
+
|
|
28
|
+
DISORT is a widely-used radiative transfer solver for plane-parallel atmospheres. It uses the discrete ordinates method to solve the radiative transfer equation with support for:
|
|
29
|
+
|
|
30
|
+
- Multiple scattering
|
|
31
|
+
- Absorption and emission
|
|
32
|
+
- Thermal emission (Planck function)
|
|
33
|
+
- Various boundary conditions
|
|
34
|
+
- Pseudo-spherical geometry for direct beam
|
|
35
|
+
|
|
36
|
+
The CDISORT library offers improved performance over the original Fortran version through dynamic memory allocation and full double precision arithmetic.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
### Prerequisites
|
|
41
|
+
|
|
42
|
+
- Python 3.9 to 3.13
|
|
43
|
+
- NumPy 1.20 or later
|
|
44
|
+
|
|
45
|
+
### From source
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/rayference/nanodisort.git
|
|
49
|
+
cd nanodisort
|
|
50
|
+
uv sync --dev
|
|
51
|
+
uv pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quickstart
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import nanodisort as nd
|
|
58
|
+
|
|
59
|
+
# Create solver state
|
|
60
|
+
state = nd.DisortState()
|
|
61
|
+
|
|
62
|
+
# Configure dimensions
|
|
63
|
+
state.nstr = 8 # Number of streams
|
|
64
|
+
state.nlyr = 6 # Number of layers
|
|
65
|
+
state.nmom = 8 # Number of phase function moments
|
|
66
|
+
state.ntau = 5 # Number of output optical depths
|
|
67
|
+
state.numu = 4 # Number of output polar angles
|
|
68
|
+
state.nphi = 3 # Number of output azimuthal angles
|
|
69
|
+
|
|
70
|
+
# Allocate memory
|
|
71
|
+
state.allocate()
|
|
72
|
+
|
|
73
|
+
# Set optical properties, geometry, boundary conditions
|
|
74
|
+
# ... (see documentation)
|
|
75
|
+
|
|
76
|
+
# Solve
|
|
77
|
+
state.solve()
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later), consistent with the CDISORT library it wraps.
|
|
83
|
+
|
|
84
|
+
## Acknowledgments
|
|
85
|
+
|
|
86
|
+
nanodisort authors are grateful to the developers of the many implementations of DISORT, and, in particular, to
|
|
87
|
+
|
|
88
|
+
- Timothy E. Dowling (original CDISORT C translation);
|
|
89
|
+
- Robert Buras (phase function extensions);
|
|
90
|
+
- Arve Kylling (pseudo-spherical approximation, testing);
|
|
91
|
+
- the original DISORT Fortran authors.
|
|
92
|
+
|
|
93
|
+
## Citation
|
|
94
|
+
|
|
95
|
+
If you use nanodisort in your research, please cite the [CDISORT paper](https://doi.org/10.1016/j.jqsrt.2011.03.019) and the nanodisort repository:
|
|
96
|
+
|
|
97
|
+
```bibtex
|
|
98
|
+
@software{Leroy_nanodisort,
|
|
99
|
+
author = {Leroy, Vincent and Emde, Claudia},
|
|
100
|
+
license = {GPL-3.0-or-later},
|
|
101
|
+
title = {{nanodisort}},
|
|
102
|
+
url = {https://github.com/eradiate/nanodisort},
|
|
103
|
+
version = {0.1.0}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# nanodisort
|
|
2
|
+
|
|
3
|
+
Python bindings for [CDISORT](http://www.libradtran.org/doku.php?id=cdisort), a C implementation of the DISORT (Discrete Ordinates Radiative Transfer) solver.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
DISORT is a widely-used radiative transfer solver for plane-parallel atmospheres. It uses the discrete ordinates method to solve the radiative transfer equation with support for:
|
|
8
|
+
|
|
9
|
+
- Multiple scattering
|
|
10
|
+
- Absorption and emission
|
|
11
|
+
- Thermal emission (Planck function)
|
|
12
|
+
- Various boundary conditions
|
|
13
|
+
- Pseudo-spherical geometry for direct beam
|
|
14
|
+
|
|
15
|
+
The CDISORT library offers improved performance over the original Fortran version through dynamic memory allocation and full double precision arithmetic.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
|
|
21
|
+
- Python 3.9 to 3.13
|
|
22
|
+
- NumPy 1.20 or later
|
|
23
|
+
|
|
24
|
+
### From source
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git clone https://github.com/rayference/nanodisort.git
|
|
28
|
+
cd nanodisort
|
|
29
|
+
uv sync --dev
|
|
30
|
+
uv pip install -e .
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quickstart
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import nanodisort as nd
|
|
37
|
+
|
|
38
|
+
# Create solver state
|
|
39
|
+
state = nd.DisortState()
|
|
40
|
+
|
|
41
|
+
# Configure dimensions
|
|
42
|
+
state.nstr = 8 # Number of streams
|
|
43
|
+
state.nlyr = 6 # Number of layers
|
|
44
|
+
state.nmom = 8 # Number of phase function moments
|
|
45
|
+
state.ntau = 5 # Number of output optical depths
|
|
46
|
+
state.numu = 4 # Number of output polar angles
|
|
47
|
+
state.nphi = 3 # Number of output azimuthal angles
|
|
48
|
+
|
|
49
|
+
# Allocate memory
|
|
50
|
+
state.allocate()
|
|
51
|
+
|
|
52
|
+
# Set optical properties, geometry, boundary conditions
|
|
53
|
+
# ... (see documentation)
|
|
54
|
+
|
|
55
|
+
# Solve
|
|
56
|
+
state.solve()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later), consistent with the CDISORT library it wraps.
|
|
62
|
+
|
|
63
|
+
## Acknowledgments
|
|
64
|
+
|
|
65
|
+
nanodisort authors are grateful to the developers of the many implementations of DISORT, and, in particular, to
|
|
66
|
+
|
|
67
|
+
- Timothy E. Dowling (original CDISORT C translation);
|
|
68
|
+
- Robert Buras (phase function extensions);
|
|
69
|
+
- Arve Kylling (pseudo-spherical approximation, testing);
|
|
70
|
+
- the original DISORT Fortran authors.
|
|
71
|
+
|
|
72
|
+
## Citation
|
|
73
|
+
|
|
74
|
+
If you use nanodisort in your research, please cite the [CDISORT paper](https://doi.org/10.1016/j.jqsrt.2011.03.019) and the nanodisort repository:
|
|
75
|
+
|
|
76
|
+
```bibtex
|
|
77
|
+
@software{Leroy_nanodisort,
|
|
78
|
+
author = {Leroy, Vincent and Emde, Claudia},
|
|
79
|
+
license = {GPL-3.0-or-later},
|
|
80
|
+
title = {{nanodisort}},
|
|
81
|
+
url = {https://github.com/eradiate/nanodisort},
|
|
82
|
+
version = {0.1.0}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import nanodisort as nd
|
|
4
|
+
from nanodisort.utils import phase_functions as pf
|
|
5
|
+
|
|
6
|
+
# Benchmark parameters
|
|
7
|
+
NSTR = 16
|
|
8
|
+
NLYR = 120
|
|
9
|
+
NMOM = 16
|
|
10
|
+
NBATCH = 100
|
|
11
|
+
|
|
12
|
+
# Shared configuration applied to both DisortState and BatchSolver
|
|
13
|
+
_shared_config = {
|
|
14
|
+
"nstr": NSTR,
|
|
15
|
+
"nlyr": NLYR,
|
|
16
|
+
"nmom": NMOM,
|
|
17
|
+
"ntau": 0,
|
|
18
|
+
"numu": 0,
|
|
19
|
+
"nphi": 0,
|
|
20
|
+
"usrtau": False,
|
|
21
|
+
"usrang": False,
|
|
22
|
+
"lamber": True,
|
|
23
|
+
"planck": False,
|
|
24
|
+
"onlyfl": True,
|
|
25
|
+
"quiet": True,
|
|
26
|
+
"intensity_correction": False,
|
|
27
|
+
"spher": False,
|
|
28
|
+
"umu0": 0.5,
|
|
29
|
+
"phi0": 0.0,
|
|
30
|
+
"fisot": 0.0,
|
|
31
|
+
"fluor": 0.0,
|
|
32
|
+
"albedo": 0.1,
|
|
33
|
+
"accur": 0.0,
|
|
34
|
+
"wvnmlo": 0.0,
|
|
35
|
+
"wvnmhi": 0.0,
|
|
36
|
+
"btemp": 0.0,
|
|
37
|
+
"ttemp": 0.0,
|
|
38
|
+
"temis": 0.0,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Pre-compute shared data
|
|
42
|
+
_dtauc = np.full((NBATCH, NLYR), 0.5)
|
|
43
|
+
_ssalb = np.random.default_rng(1).uniform(0.5, 1.0, (NBATCH, NLYR))
|
|
44
|
+
_pmom_single = pf.henyey_greenstein(0.7, NMOM).reshape(-1, 1) * np.ones(NLYR)
|
|
45
|
+
_pmom_batch = _pmom_single[:, :, np.newaxis] * np.ones(NBATCH)
|
|
46
|
+
_fbeam = np.full(NBATCH, np.pi)
|
|
47
|
+
_albedo = np.full(NBATCH, 0.1)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _apply_config(target):
|
|
51
|
+
for key, value in _shared_config.items():
|
|
52
|
+
setattr(target, key, value)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _make_single_state() -> nd.DisortState:
|
|
56
|
+
ds = nd.DisortState()
|
|
57
|
+
_apply_config(ds)
|
|
58
|
+
ds.allocate()
|
|
59
|
+
return ds
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _make_batch_solver() -> nd.BatchSolver:
|
|
63
|
+
solver = nd.BatchSolver(nthreads=2)
|
|
64
|
+
_apply_config(solver)
|
|
65
|
+
solver.allocate(NBATCH)
|
|
66
|
+
solver.set_dtauc(_dtauc)
|
|
67
|
+
solver.set_ssalb(_ssalb)
|
|
68
|
+
solver.set_pmom(_pmom_batch)
|
|
69
|
+
solver.set_fbeam(_fbeam)
|
|
70
|
+
solver.set_albedo(_albedo)
|
|
71
|
+
return solver
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class BenchmarkBatch:
|
|
75
|
+
def benchmark_single(self, benchmark):
|
|
76
|
+
ds = _make_single_state()
|
|
77
|
+
|
|
78
|
+
def run():
|
|
79
|
+
for i in range(NBATCH):
|
|
80
|
+
ds.dtauc = _dtauc[i]
|
|
81
|
+
ds.ssalb = _ssalb[i]
|
|
82
|
+
ds.fbeam = _fbeam[i]
|
|
83
|
+
ds.pmom = _pmom_single
|
|
84
|
+
ds.solve()
|
|
85
|
+
|
|
86
|
+
benchmark(run)
|
|
87
|
+
|
|
88
|
+
def benchmark_batch(self, benchmark):
|
|
89
|
+
solver = _make_batch_solver()
|
|
90
|
+
|
|
91
|
+
def run():
|
|
92
|
+
solver.solve()
|
|
93
|
+
|
|
94
|
+
benchmark(run)
|