beta-parameterization 2.3.5__tar.gz → 3.0.0__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.
- beta_parameterization-3.0.0/CHANGELOG.md +242 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/CMakeLists.txt +21 -4
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/PKG-INFO +1 -1
- beta_parameterization-3.0.0/include/beta_parameterization.h +263 -0
- beta_parameterization-3.0.0/include/beta_parameterization.hpp +410 -0
- beta_parameterization-3.0.0/python/beta_parameterization/__init__.py +22 -0
- beta_parameterization-3.0.0/python/beta_parameterization/_cdefs.py +101 -0
- beta_parameterization-3.0.0/python/beta_parameterization/api.py +388 -0
- beta_parameterization-3.0.0/python/tests/test_api.py +153 -0
- beta_parameterization-3.0.0/src/beta_parameterization_c_api_mod.f08 +511 -0
- beta_parameterization-3.0.0/src/beta_parameterization_mod.f08 +1419 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/src/beta_parameterization_workers_mod.f08 +82 -40
- beta_parameterization-3.0.0/tests/beta_param_bitwise_test.f08 +252 -0
- beta_parameterization-3.0.0/tests/beta_param_boundary_test.f08 +148 -0
- beta_parameterization-3.0.0/tests/beta_param_golden_test.f08 +152 -0
- beta_parameterization-3.0.0/tests/beta_param_interleave_test.f08 +378 -0
- beta_parameterization-3.0.0/tests/beta_param_lifecycle_test.f08 +124 -0
- beta_parameterization-3.0.0/tests/beta_param_minimality_test.f08 +260 -0
- beta_parameterization-3.0.0/tests/beta_param_outputs_test.f08 +132 -0
- beta_parameterization-3.0.0/tests/beta_param_property_test.f08 +157 -0
- beta_parameterization-3.0.0/tests/beta_param_resolve_test.f08 +53 -0
- beta_parameterization-3.0.0/tests/beta_param_standalone_test.f08 +115 -0
- beta_parameterization-3.0.0/tests/beta_param_status_test.f08 +32 -0
- beta_parameterization-3.0.0/tests/beta_pes_sweep.f08 +231 -0
- beta_parameterization-3.0.0/tests/c_api_smoke_test.cpp +213 -0
- beta_parameterization-3.0.0/tests/golden_capture.f08 +113 -0
- beta_parameterization-3.0.0/tests/thread_stress_test.cpp +168 -0
- beta_parameterization-2.3.5/include/beta_parameterization.h +0 -207
- beta_parameterization-2.3.5/include/beta_parameterization.hpp +0 -292
- beta_parameterization-2.3.5/python/beta_parameterization/__init__.py +0 -23
- beta_parameterization-2.3.5/python/beta_parameterization/_cdefs.py +0 -59
- beta_parameterization-2.3.5/python/beta_parameterization/api.py +0 -297
- beta_parameterization-2.3.5/python/tests/test_api.py +0 -185
- beta_parameterization-2.3.5/src/beta_parameterization_c_api_mod.f08 +0 -425
- beta_parameterization-2.3.5/src/beta_parameterization_mod.f08 +0 -828
- beta_parameterization-2.3.5/tests/beta_param_breakdown_test.f08 +0 -126
- beta_parameterization-2.3.5/tests/beta_param_com_test.f08 +0 -97
- beta_parameterization-2.3.5/tests/beta_param_core_test.f08 +0 -105
- beta_parameterization-2.3.5/tests/beta_param_error_test.f08 +0 -154
- beta_parameterization-2.3.5/tests/beta_param_golden_test.f08 +0 -165
- beta_parameterization-2.3.5/tests/beta_param_node_set_test.f08 +0 -335
- beta_parameterization-2.3.5/tests/c_api_smoke_test.cpp +0 -214
- beta_parameterization-2.3.5/tests/golden_capture.f08 +0 -88
- beta_parameterization-2.3.5/tests/thread_stress_test.cpp +0 -60
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/.gitignore +0 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/LICENSE +0 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/ci/build-wheel.sh +0 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/pyproject.toml +0 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/python/beta_parameterization/_libloader.py +0 -0
- {beta_parameterization-2.3.5 → beta_parameterization-3.0.0}/tests/test_utils_mod.f08 +0 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. Versions follow
|
|
4
|
+
semantic versioning; the format follows [Keep a Changelog](https://keepachangelog.com).
|
|
5
|
+
|
|
6
|
+
## 3.0.0
|
|
7
|
+
|
|
8
|
+
Adoption of the three-tier shape parameterization contract against
|
|
9
|
+
`shape_core_mod` (fortran-foundations 2.4.0). Every public surface — Fortran,
|
|
10
|
+
C, C++, Python — changes. Read the breaking-change list before upgrading;
|
|
11
|
+
nothing in 2.x compiles against 3.0.0 unchanged.
|
|
12
|
+
|
|
13
|
+
### BREAKING: thread-safety promise withdrawn
|
|
14
|
+
|
|
15
|
+
**The 2.x guarantee that one cache serves concurrent computes from many threads
|
|
16
|
+
is gone.** It was never true once the cache started tracking recompute state.
|
|
17
|
+
|
|
18
|
+
| object | 3.0.0 rule |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `tables_t` / `beta_param_tables_t*` / `Tables` | immutable after creation; share across threads for concurrent reads |
|
|
21
|
+
| `node_set_t` / `beta_param_node_set_t*` / `NodeSet` | immutable after build; share across threads for concurrent reads |
|
|
22
|
+
| `cache_t` / `beta_param_cache_t*` / `Cache` / Python `Cache` | **THREAD-CONFINED**; every compute mutates it; concurrent use from more than one thread is undefined |
|
|
23
|
+
|
|
24
|
+
The supported pattern is one shared `tables_t` plus one cache per thread, built
|
|
25
|
+
with `cache_init_shared_s` / `beta_param_cache_create_shared()` /
|
|
26
|
+
`Tables`-taking `Cache` constructor. Callers that fanned out one 2.x cache
|
|
27
|
+
across an OpenMP region **must** hoist a per-thread cache; the old code will
|
|
28
|
+
race silently. C++ `Cache` compute methods are no longer `const` — the compiler
|
|
29
|
+
catches most of these at the call site.
|
|
30
|
+
|
|
31
|
+
**Fortran callers of `cache_init_shared_s` MUST declare their `tables_t` with
|
|
32
|
+
the `target` attribute.** The cache stores a pointer to it, and a pointer
|
|
33
|
+
associated with a non-target dummy becomes undefined when that procedure
|
|
34
|
+
returns (F2018 8.5.17). Without `target` the code compiles, links and usually
|
|
35
|
+
appears to work — then reads freed memory. Declare
|
|
36
|
+
`type(tables_t), target :: tables`.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **In-library volume conservation.** `conserve_volume` is a cache/standalone
|
|
41
|
+
creation flag. The factor `c = (2 / Σᵢ wᵢ Rᵢ³)^(1/3)` is computed on the
|
|
42
|
+
internal GL-512 set over the COM-corrected, unscaled shape, after validation,
|
|
43
|
+
and applied to radii, dR/dθ and the polar radii — never to β-space values.
|
|
44
|
+
Consumers that rescaled shapes themselves (wmmm's
|
|
45
|
+
`compute_volume_factor_from_dense_f`) should drop their copy.
|
|
46
|
+
- `apply_com` as a creation flag, replacing the separate
|
|
47
|
+
`*_with_com_shift` entry points.
|
|
48
|
+
- `tables_t` — a shared, immutable tables level (normalization constants,
|
|
49
|
+
Gauss-Legendre set, Legendre tables at the primary thetas) with
|
|
50
|
+
`tables_init_s` / `tables_free_s` / `tables_max_l_f` / `tables_n_thetas_f`.
|
|
51
|
+
- `status_message_f(status)` (C: `beta_param_status_message`) — one pure lookup
|
|
52
|
+
returning a fixed string per code.
|
|
53
|
+
- `cache_radius_grid_unchecked_s` — the rendering/diagnostic path: no validity
|
|
54
|
+
gate, no volume scaling, usage errors only, so a rejected shape still yields
|
|
55
|
+
its outline. Its radii are UNSCALED even on a `conserve_volume` cache; mixing
|
|
56
|
+
it with the checked path draws two outlines of different size for one shape.
|
|
57
|
+
- `cache_recompute_count_f` plus the public intermediate indices
|
|
58
|
+
`BETA_PARAM_I_RESOLVED`, `_I_MIN_RADIUS`, `_I_VOLUME`, `_I_RADII`, `_I_DERIV`
|
|
59
|
+
— always-on recompute counters for cache-minimality testing.
|
|
60
|
+
- `BETA_PARAM_ERROR_NODE_SET_MISMATCH` (106) for an unbuilt node set or one
|
|
61
|
+
whose `max_l` is below the cache's `n_params`.
|
|
62
|
+
- Public constants for the two tier caps, so callers can check before creating
|
|
63
|
+
anything: `SHAPE_CACHE_MAX_PARAMS` (8) and `SHAPE_STANDALONE_MAX_PARAMS` (64)
|
|
64
|
+
re-exported from Fortran, `BETA_PARAM_CACHE_MAX_PARAMS` (8) and
|
|
65
|
+
`BETA_PARAM_MAX_PARAMS_LIMIT` (64) in the C header,
|
|
66
|
+
`beta_param::cache_max_params` / `beta_param::max_params_limit` in the C++
|
|
67
|
+
header, and `CACHE_MAX_PARAMS` (8) / `MAX_BETA_PARAMS_LIMIT` (64) in Python.
|
|
68
|
+
- The documented dependency map lives in the module header of
|
|
69
|
+
`src/beta_parameterization_mod.f08`: five intermediates, every mask = all
|
|
70
|
+
`n_params` bits.
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- **BREAKING: the cached tier now caps `n_params` at 8, down from 64.** A cache
|
|
75
|
+
carries the recompute engine, whose per-intermediate dependency masks are
|
|
76
|
+
fixed-width, so `shape_core`'s `SHAPE_CACHE_MAX_PARAMS` = 8 is the hard limit.
|
|
77
|
+
`cache_init_s` / `cache_init_shared_s` reject `n_params > 8` with
|
|
78
|
+
`SHAPE_ERROR_TOO_MANY_PARAMS` (1) and `n_params < 1` with
|
|
79
|
+
`SHAPE_ERROR_INVALID_INIT` (5) — the engine check runs before any table is
|
|
80
|
+
built, so nothing is allocated. **The standalone tier is unaffected and still
|
|
81
|
+
accepts up to 64** (`SHAPE_STANDALONE_MAX_PARAMS`): it constructs no engine.
|
|
82
|
+
2.x accepted `max_beta_params` up to 64 for the cache, so any consumer that
|
|
83
|
+
created a cache with more than 8 parameters — wmmm's
|
|
84
|
+
`number_of_deformation_parameters = 20` is the known case — fails at cache
|
|
85
|
+
creation and must either reduce its parameter count or move to the standalone
|
|
86
|
+
tier. Beta PES calculations realistically stay within 8 dimensions; wmmm's
|
|
87
|
+
20 existed for fos→beta conversion, which is obsolete now that fos works on
|
|
88
|
+
the radius grid directly.
|
|
89
|
+
- **BREAKING: the internal uniform grid is gone.** 2.x caches took `n_grid` and
|
|
90
|
+
generated their own uniform theta grid. 3.0.0 takes an explicit **primary
|
|
91
|
+
theta set** — `tables_init_s(tables, max_l, thetas, status)`,
|
|
92
|
+
`cache_init_s(cache, n_params, thetas, ...)`. The caller owns the grid.
|
|
93
|
+
Pole values (θ = 0, π) are rejected as cache input; get them analytically
|
|
94
|
+
from `cache_resolve_shape_s`'s `r_north` / `r_south`.
|
|
95
|
+
- **BREAKING: all `message` arguments removed** from every entry point in
|
|
96
|
+
Fortran, C, C++ and Python. Diagnostics are the integer status plus
|
|
97
|
+
`status_message_f`. No per-call message formatting exists anywhere.
|
|
98
|
+
- **BREAKING (bitwise): the COM correction is now Newton's method** on the
|
|
99
|
+
numerator of the COM integral (`N(β10) = Σᵢ wᵢ xᵢ Rᵢ⁴`,
|
|
100
|
+
`N'(β10) = 4·C₁·Σᵢ wᵢ xᵢ² Rᵢ³`), replacing 2.x fixed-point iteration. The
|
|
101
|
+
tolerance (`|z_cm| < 1e-5`) and iteration cap (50) are unchanged, so the same
|
|
102
|
+
shapes converge — but **corrected β₁₀ and every downstream radius differ in
|
|
103
|
+
the last bits from 2.x**. Goldens were re-baselined; consumers pinning exact
|
|
104
|
+
values must re-baseline too.
|
|
105
|
+
- **BREAKING: `beta_con` is off the public surface.** 2.x
|
|
106
|
+
`cache_resolve_shape` returned the resolved coefficient array and
|
|
107
|
+
`compute_radius_and_derivative` took it back as an argument. 3.0.0 keeps
|
|
108
|
+
resolved coefficients inside the cache as intermediate 1;
|
|
109
|
+
`cache_resolve_shape_s` returns only `corrected_beta10`, `r_north`, `r_south`
|
|
110
|
+
and `volume_factor`, and node evaluation takes `(cache, node_set, params)`.
|
|
111
|
+
- Type-bound methods (`cache%init`, `cache%compute_radius_grid`, …) replaced by
|
|
112
|
+
free subroutines (`cache_init_s`, `cache_radius_grid_s`, …), matching the
|
|
113
|
+
contract's naming.
|
|
114
|
+
- Standalone tier: `compute_radius_grid_standalone_s(params, thetas,
|
|
115
|
+
conserve_volume, apply_com, radii, status)` and
|
|
116
|
+
`compute_radius_and_derivative_standalone_s(...)`. `n_params = size(params)`,
|
|
117
|
+
accepted up to the **standalone** cap of 64
|
|
118
|
+
(`SHAPE_STANDALONE_MAX_PARAMS` = `MAX_BETA_PARAMS_LIMIT`); above →
|
|
119
|
+
`SHAPE_ERROR_TOO_MANY_PARAMS`, never silent truncation. The
|
|
120
|
+
`max_beta_params` padding argument is removed. Tier 1 never constructs an
|
|
121
|
+
engine, which is why it keeps the higher cap.
|
|
122
|
+
- Failure semantics are now uniform: on ANY nonzero status inside a checked
|
|
123
|
+
cached compute the library zero-fills every output and invalidates the whole
|
|
124
|
+
engine, so the next call runs cold. Usage errors follow the contract's
|
|
125
|
+
normative order — a buffer-size mismatch (104) is reported before a node-set
|
|
126
|
+
mismatch (106).
|
|
127
|
+
- Minimum fortran-foundations is **2.4.0** (`shape_core_mod`); gcc-opts stays at
|
|
128
|
+
**2.0.0**.
|
|
129
|
+
|
|
130
|
+
### Changed: status codes
|
|
131
|
+
|
|
132
|
+
Shared contract codes (0–99) come from `shape_core_mod`: `SHAPE_VALID` 0,
|
|
133
|
+
`SHAPE_ERROR_TOO_MANY_PARAMS` 1, `SHAPE_ERROR_CACHE_NOT_INITIALIZED` 2,
|
|
134
|
+
`SHAPE_ERROR_INVALID_GRID` 3 (theta floor: `size(thetas) >= 2`),
|
|
135
|
+
`SHAPE_ERROR_WRONG_PARAM_COUNT` 4, `SHAPE_ERROR_INVALID_INIT` 5,
|
|
136
|
+
`SHAPE_ERROR_TABLES_NOT_INITIALIZED` 6.
|
|
137
|
+
|
|
138
|
+
Library codes are renamed `LEGENDRE_*` → `BETA_PARAM_ERROR_*` and renumbered
|
|
139
|
+
≥ 100. This range is **append-only** from 3.0.0 on:
|
|
140
|
+
|
|
141
|
+
| old (2.x) | new (3.0.0) |
|
|
142
|
+
|---|---|
|
|
143
|
+
| `LEGENDRE_ERROR_NORTH_POLE` 1 | `BETA_PARAM_ERROR_NORTH_POLE` 100 |
|
|
144
|
+
| `LEGENDRE_ERROR_SOUTH_POLE` 2 | `BETA_PARAM_ERROR_SOUTH_POLE` 101 |
|
|
145
|
+
| `LEGENDRE_ERROR_INTERIOR_NEGATIVE` 4 | `BETA_PARAM_ERROR_INTERIOR_NEGATIVE` 102 |
|
|
146
|
+
| `LEGENDRE_ERROR_COM_NOT_CONVERGED` 7 | `BETA_PARAM_ERROR_COM_NOT_CONVERGED` 103 |
|
|
147
|
+
| `LEGENDRE_ERROR_INVALID_BUFFER_SIZE` 8 | `BETA_PARAM_ERROR_INVALID_BUFFER_SIZE` 104 |
|
|
148
|
+
| `LEGENDRE_ERROR_POLE_NODE` 9 | `BETA_PARAM_ERROR_POLE_NODE` 105 |
|
|
149
|
+
| — (new) | `BETA_PARAM_ERROR_NODE_SET_MISMATCH` 106 |
|
|
150
|
+
| `LEGENDRE_ERROR_EMPTY_PARAMS` 3 | → shared 4 (compute) / 5 (init) |
|
|
151
|
+
| `LEGENDRE_ERROR_INVALID_MAX_PARAMS` 5 | → shared 5 / 3 / 2 by cause |
|
|
152
|
+
| `LEGENDRE_ERROR_TOO_MANY_PARAMS` 6 | → shared 1 |
|
|
153
|
+
| `LEGENDRE_ERROR_NO_UNIFORM_GRID` 10 | removed (no uniform grid) |
|
|
154
|
+
|
|
155
|
+
Note that the old and new numbering overlap: 2.x code 1 meant "north pole",
|
|
156
|
+
3.0.0 code 1 means "too many params". Callers comparing raw integers must be
|
|
157
|
+
updated, not merely recompiled.
|
|
158
|
+
|
|
159
|
+
### Changed: C API
|
|
160
|
+
|
|
161
|
+
Handle-based, with statuses reported through out-parameters instead of
|
|
162
|
+
in-band returns:
|
|
163
|
+
|
|
164
|
+
- `beta_param_tables_create(max_l, thetas, n_thetas, int* status)` /
|
|
165
|
+
`beta_param_tables_destroy` — new handle type `beta_param_tables_t*`.
|
|
166
|
+
- `beta_param_cache_create(n_params, thetas, n_thetas, conserve_volume,
|
|
167
|
+
apply_com, int* status)` and
|
|
168
|
+
`beta_param_cache_create_shared(tables, n_params, conserve_volume, apply_com,
|
|
169
|
+
int* status)` — both return `NULL` on failure and write the rejecting code to
|
|
170
|
+
the nullable `status` out-param. The 2.x `n_grid` + `message` arguments are
|
|
171
|
+
gone.
|
|
172
|
+
- Computes drop the `compute_` infix and the `_with_com_shift` variants:
|
|
173
|
+
`beta_param_cache_radius_grid`, `_radius_and_derivative`,
|
|
174
|
+
`_radius_grid_unchecked`, `_resolve_shape`, `_node_radius_and_derivative`,
|
|
175
|
+
`beta_param_radius_grid_standalone`, `_radius_and_derivative_standalone`.
|
|
176
|
+
Each returns the status code directly.
|
|
177
|
+
- `beta_param_status_message(int)` returns a static string; no caller-supplied
|
|
178
|
+
message buffers anywhere.
|
|
179
|
+
- Lifetime rule: a tables handle passed to `beta_param_cache_create_shared()`
|
|
180
|
+
or `beta_param_node_set_create()` must outlive everything built from it;
|
|
181
|
+
`beta_param_cache_destroy()` never frees shared tables.
|
|
182
|
+
|
|
183
|
+
### Changed: C++ header
|
|
184
|
+
|
|
185
|
+
`beta_parameterization.hpp` (C++20, header-only) exposes `Tables`, `Cache` and
|
|
186
|
+
`NodeSet` RAII wrappers. `Cache` is move-only and thread-confined; its compute
|
|
187
|
+
methods are non-`const`. Status strings come from `beta_param_status_message`.
|
|
188
|
+
The 2.x concurrent-compute documentation is replaced, not amended.
|
|
189
|
+
|
|
190
|
+
### Changed: Python wheel
|
|
191
|
+
|
|
192
|
+
- **BREAKING: `NodeSet` is removed.** BetaRender's single-set usage maps onto
|
|
193
|
+
the primary theta set. Node sets return to Python only when a consumer needs
|
|
194
|
+
a genuine second set — the same principle that keeps `tables_t` out of
|
|
195
|
+
Python.
|
|
196
|
+
- **BREAKING: `theta_grid(n)` is now the OPEN uniform grid**
|
|
197
|
+
`theta_i = i·π/(n+1), i = 1..n`. The 2.x closed `linspace(0, π, n)` includes
|
|
198
|
+
both poles, which the pole guard now rejects as cache input. Close plotted
|
|
199
|
+
curves with the analytic `r_north` / `r_south` from `resolve_shape`.
|
|
200
|
+
- Module-level tier 1: `radius_grid(params, thetas, conserve_volume=False,
|
|
201
|
+
apply_com=False)`, `radius_and_derivative(...)`.
|
|
202
|
+
- `Cache(n_params, thetas, conserve_volume=False, apply_com=False)` with
|
|
203
|
+
`.radius_grid`, `.radius_and_derivative`, `.radius_grid_unchecked`,
|
|
204
|
+
`.resolve_shape`. Thread-confined.
|
|
205
|
+
- **Returns are result objects, not exceptions**: `RadiusGridResult`,
|
|
206
|
+
`RadiusDerivativeResult`, `ResolvedShape`, each with `.ok`, `.status` and a
|
|
207
|
+
`.message` property. Shape-validation failures come back as a status-carrying
|
|
208
|
+
result; `BetaParamError` is raised only for usage errors (closed handle,
|
|
209
|
+
non-1-D params, create failure).
|
|
210
|
+
- The `Status` enum is renumbered per the table above.
|
|
211
|
+
|
|
212
|
+
### Removed
|
|
213
|
+
|
|
214
|
+
- Concurrent-compute-on-one-cache support (see the breaking section above).
|
|
215
|
+
- The internally generated uniform theta grid and
|
|
216
|
+
`LEGENDRE_ERROR_NO_UNIFORM_GRID`.
|
|
217
|
+
- All `message` output arguments and the message-formatting code behind them.
|
|
218
|
+
- `*_with_com_shift` entry points (Fortran, C), superseded by the `apply_com`
|
|
219
|
+
creation flag.
|
|
220
|
+
- `beta_con` from every public signature.
|
|
221
|
+
- The `max_beta_params` padding argument on the standalone entry points.
|
|
222
|
+
- Python `NodeSet`.
|
|
223
|
+
|
|
224
|
+
### Migration sketch
|
|
225
|
+
|
|
226
|
+
```fortran
|
|
227
|
+
! 2.x
|
|
228
|
+
call cache%init(max_beta_params = 4_ik, n_grid = 80_ik, error_code = ec, message = msg)
|
|
229
|
+
call cache%compute_radius_grid_with_com_shift(params, radii, ec, msg)
|
|
230
|
+
call cache%destroy()
|
|
231
|
+
|
|
232
|
+
! 3.0.0 — the caller owns the theta set; flags are set once, at creation
|
|
233
|
+
thetas = [(i * PI / 81.0_rk, i = 1, 80)] ! open grid: no poles
|
|
234
|
+
call cache_init_s(cache, n_params = 4_ik, thetas = thetas, &
|
|
235
|
+
conserve_volume = .false., apply_com = .true., status = status)
|
|
236
|
+
call cache_radius_grid_s(cache, params, radii, status)
|
|
237
|
+
call cache_free_s(cache)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## 2.3.4 and earlier
|
|
241
|
+
|
|
242
|
+
No changelog was kept before 3.0.0. See the git history.
|
|
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.20)
|
|
|
3
3
|
include(FetchContent)
|
|
4
4
|
|
|
5
5
|
project(beta-parameterization
|
|
6
|
-
VERSION
|
|
6
|
+
VERSION 3.0.0
|
|
7
7
|
LANGUAGES Fortran CXX
|
|
8
8
|
DESCRIPTION "Beta parameterization for nuclear physics applications"
|
|
9
9
|
)
|
|
@@ -24,7 +24,7 @@ FetchContent_MakeAvailable(GCC-Compiler-Options)
|
|
|
24
24
|
FetchContent_Declare(
|
|
25
25
|
Fortran-Foundations
|
|
26
26
|
GIT_REPOSITORY https://github.com/AleksanderAugustyn/Fortran-Foundations.git
|
|
27
|
-
GIT_TAG 2.
|
|
27
|
+
GIT_TAG 2.4.0
|
|
28
28
|
)
|
|
29
29
|
FetchContent_MakeAvailable(Fortran-Foundations)
|
|
30
30
|
|
|
@@ -118,7 +118,8 @@ set_target_properties(beta_param_test_utils PROPERTIES
|
|
|
118
118
|
target_include_directories(beta_param_test_utils PUBLIC
|
|
119
119
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/mod_files_tests>)
|
|
120
120
|
|
|
121
|
-
set(BETA_PARAM_TEST_SUITES
|
|
121
|
+
set(BETA_PARAM_TEST_SUITES status lifecycle resolve outputs standalone bitwise minimality
|
|
122
|
+
interleave boundary property golden)
|
|
122
123
|
foreach (suite IN LISTS BETA_PARAM_TEST_SUITES)
|
|
123
124
|
add_executable(beta_param_${suite}_test tests/beta_param_${suite}_test.f08)
|
|
124
125
|
target_link_libraries(beta_param_${suite}_test PRIVATE
|
|
@@ -134,19 +135,35 @@ endforeach ()
|
|
|
134
135
|
set_source_files_properties(tests/beta_param_golden_test.f08 PROPERTIES
|
|
135
136
|
COMPILE_OPTIONS "-Wno-conversion-extra;-Wno-error=conversion-extra")
|
|
136
137
|
|
|
138
|
+
# Capture tool for the golden baseline: an executable, never a test.
|
|
137
139
|
add_executable(golden_capture tests/golden_capture.f08)
|
|
138
140
|
target_link_libraries(golden_capture PRIVATE
|
|
139
141
|
beta_parameterization beta_param_test_utils beta_parameterization_flags)
|
|
140
142
|
set_target_properties(golden_capture PROPERTIES
|
|
141
143
|
Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mod_files_tests/capture)
|
|
142
144
|
|
|
145
|
+
# PES-range sweep: 1.55M shapes, far too slow for ctest. An executable driven
|
|
146
|
+
# by an explicit custom target, never registered with add_test.
|
|
147
|
+
add_executable(beta_pes_sweep tests/beta_pes_sweep.f08)
|
|
148
|
+
target_link_libraries(beta_pes_sweep PRIVATE
|
|
149
|
+
beta_parameterization beta_param_test_utils beta_parameterization_flags)
|
|
150
|
+
set_target_properties(beta_pes_sweep PROPERTIES
|
|
151
|
+
Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mod_files_tests/sweep)
|
|
152
|
+
add_custom_target(test_beta_pes_sweep
|
|
153
|
+
COMMAND beta_pes_sweep
|
|
154
|
+
DEPENDS beta_pes_sweep
|
|
155
|
+
COMMENT "Running the PES-range sweep (1.55M + 172.8k shapes)")
|
|
156
|
+
|
|
157
|
+
# C API smoke test: links the SHARED library, the binary the bindings load.
|
|
143
158
|
add_executable(c_api_smoke_test tests/c_api_smoke_test.cpp)
|
|
144
159
|
target_link_libraries(c_api_smoke_test PRIVATE beta_parameterization_cxx)
|
|
145
160
|
add_test(NAME c_api_smoke COMMAND c_api_smoke_test)
|
|
146
161
|
|
|
162
|
+
# Thread model of 3.0.0: shared tables, per-thread caches, via the C++ wrapper.
|
|
147
163
|
find_package(Threads REQUIRED)
|
|
148
164
|
add_executable(thread_stress_test tests/thread_stress_test.cpp)
|
|
149
|
-
target_link_libraries(thread_stress_test PRIVATE
|
|
165
|
+
target_link_libraries(thread_stress_test PRIVATE
|
|
166
|
+
beta_parameterization_cxx Threads::Threads)
|
|
150
167
|
add_test(NAME thread_stress COMMAND thread_stress_test)
|
|
151
168
|
|
|
152
169
|
endif ()
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file beta_parameterization.h
|
|
3
|
+
* @brief C API for the Fortran beta parameterization library (v3.0.0).
|
|
4
|
+
*
|
|
5
|
+
* Three handle types, from shared to per-shape:
|
|
6
|
+
* - `beta_param_tables_t` — everything determined by `max_l` and the
|
|
7
|
+
* primary theta set (normalization constants, Gauss-Legendre tables,
|
|
8
|
+
* Legendre tables at the primary thetas). Built once, shared read-only.
|
|
9
|
+
* - `beta_param_node_set_t` — an extra set of evaluation thetas with its own
|
|
10
|
+
* Legendre tables, sized to one tables handle. Immutable after creation.
|
|
11
|
+
* - `beta_param_cache_t` — per-shape working state: the recompute engine
|
|
12
|
+
* and every per-shape buffer. Mutated by every compute call.
|
|
13
|
+
*
|
|
14
|
+
* Two tiers of computation:
|
|
15
|
+
* - Cached: create a cache once, call the `beta_param_cache_*` functions for
|
|
16
|
+
* many shapes. Only the intermediates invalidated by the changed
|
|
17
|
+
* parameters are recomputed.
|
|
18
|
+
* - Standalone: one-off calls that build, use and discard their own tables.
|
|
19
|
+
*
|
|
20
|
+
* Thread safety (BREAKING CHANGE at 3.0.0 — the 2.x promise is withdrawn):
|
|
21
|
+
* A `beta_param_cache_t*` is THREAD-CONFINED. It is mutated by every compute
|
|
22
|
+
* call; concurrent use of one cache from more than one thread is undefined.
|
|
23
|
+
* Give every thread its own cache. `beta_param_tables_t*` and
|
|
24
|
+
* `beta_param_node_set_t*` are immutable after creation and may be shared
|
|
25
|
+
* across threads for concurrent reads, including as the backing tables of
|
|
26
|
+
* per-thread caches created with beta_param_cache_create_shared().
|
|
27
|
+
*
|
|
28
|
+
* Lifetime:
|
|
29
|
+
* A tables handle passed to beta_param_cache_create_shared() or
|
|
30
|
+
* beta_param_node_set_create() MUST outlive every cache and node set built
|
|
31
|
+
* from it — the cache/node set holds a reference, not a copy. Destroy order:
|
|
32
|
+
* node sets and caches first, their tables last.
|
|
33
|
+
*
|
|
34
|
+
* Diagnostics:
|
|
35
|
+
* There are no message buffers. `_create` functions return NULL on failure
|
|
36
|
+
* and write the reason to the nullable `int* status` out-parameter (pass
|
|
37
|
+
* NULL to ignore it). Every other function returns the status code directly;
|
|
38
|
+
* BETA_PARAM_VALID (0) means success. beta_param_status_message() maps a code
|
|
39
|
+
* to a fixed, static, null-terminated string; the returned pointer is owned
|
|
40
|
+
* by the library, never freed by the caller, and is safe to read from any
|
|
41
|
+
* thread.
|
|
42
|
+
*
|
|
43
|
+
* Failure behavior:
|
|
44
|
+
* On any nonzero status from a compute function, every output buffer is
|
|
45
|
+
* zero-filled and the cache is returned to a cold state — the next call
|
|
46
|
+
* recomputes from scratch. No partially updated results are ever visible.
|
|
47
|
+
* A NULL handle passed into a compute function returns
|
|
48
|
+
* BETA_PARAM_ERROR_CACHE_NOT_INITIALIZED (2).
|
|
49
|
+
*
|
|
50
|
+
* Precondition — finite input:
|
|
51
|
+
* `params` and `thetas` must be finite. Non-finite input is undefined
|
|
52
|
+
* behavior: the library cannot detect NaN under fast-math, so validation
|
|
53
|
+
* comparisons silently pass and the call returns BETA_PARAM_VALID (0) with
|
|
54
|
+
* NaN outputs. Screen inputs before calling.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
#ifndef BETA_PARAMETERIZATION_H
|
|
58
|
+
#define BETA_PARAMETERIZATION_H
|
|
59
|
+
|
|
60
|
+
#ifdef __cplusplus
|
|
61
|
+
extern "C" {
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
/* --- Limits --- */
|
|
65
|
+
/** Highest Legendre order a tables handle may be built for. */
|
|
66
|
+
#define BETA_PARAM_MAX_PARAMS_LIMIT 64
|
|
67
|
+
/** Highest n_params a cache (cached tier) accepts. */
|
|
68
|
+
#define BETA_PARAM_CACHE_MAX_PARAMS 8
|
|
69
|
+
|
|
70
|
+
/* --- Shared contract status codes (0-99, identical numbers in every
|
|
71
|
+
* shape-parameterization library) --- */
|
|
72
|
+
#define BETA_PARAM_VALID 0
|
|
73
|
+
#define BETA_PARAM_ERROR_TOO_MANY_PARAMS 1
|
|
74
|
+
#define BETA_PARAM_ERROR_CACHE_NOT_INITIALIZED 2
|
|
75
|
+
#define BETA_PARAM_ERROR_INVALID_GRID 3
|
|
76
|
+
#define BETA_PARAM_ERROR_WRONG_PARAM_COUNT 4
|
|
77
|
+
#define BETA_PARAM_ERROR_INVALID_INIT 5
|
|
78
|
+
#define BETA_PARAM_ERROR_TABLES_NOT_INITIALIZED 6
|
|
79
|
+
|
|
80
|
+
/* --- Library status codes (>= 100, append-only after 3.0.0) --- */
|
|
81
|
+
#define BETA_PARAM_ERROR_NORTH_POLE 100
|
|
82
|
+
#define BETA_PARAM_ERROR_SOUTH_POLE 101
|
|
83
|
+
#define BETA_PARAM_ERROR_INTERIOR_NEGATIVE 102
|
|
84
|
+
#define BETA_PARAM_ERROR_COM_NOT_CONVERGED 103
|
|
85
|
+
#define BETA_PARAM_ERROR_INVALID_BUFFER_SIZE 104
|
|
86
|
+
#define BETA_PARAM_ERROR_POLE_NODE 105
|
|
87
|
+
#define BETA_PARAM_ERROR_NODE_SET_MISMATCH 106
|
|
88
|
+
|
|
89
|
+
/* --- Opaque handles --- */
|
|
90
|
+
typedef struct beta_param_tables beta_param_tables_t;
|
|
91
|
+
typedef struct beta_param_cache beta_param_cache_t;
|
|
92
|
+
typedef struct beta_param_node_set beta_param_node_set_t;
|
|
93
|
+
|
|
94
|
+
/* --- Diagnostics --- */
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Fixed description of a status code. Never NULL; unknown codes map to an
|
|
98
|
+
* "unknown status code" string. The pointer is to static storage: do not free
|
|
99
|
+
* it, and it stays valid for the life of the process.
|
|
100
|
+
*/
|
|
101
|
+
const char* beta_param_status_message(int status);
|
|
102
|
+
|
|
103
|
+
/* --- Tables lifecycle --- */
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Build the shared immutable level. Returns NULL on failure.
|
|
107
|
+
*
|
|
108
|
+
* @param max_l 1 .. BETA_PARAM_MAX_PARAMS_LIMIT
|
|
109
|
+
* @param thetas Primary theta set in radians; at least 2 entries, none at
|
|
110
|
+
* or beyond a pole (cos(theta)^2 == 1 in double precision)
|
|
111
|
+
* @param n_thetas Number of entries in thetas
|
|
112
|
+
* @param status Nullable; receives BETA_PARAM_VALID or the rejecting code
|
|
113
|
+
*/
|
|
114
|
+
beta_param_tables_t* beta_param_tables_create(
|
|
115
|
+
int max_l, const double* thetas, int n_thetas, int* status);
|
|
116
|
+
|
|
117
|
+
/** Destroy a tables handle. NULL-safe. Every cache and node set built from it
|
|
118
|
+
* must already be destroyed. */
|
|
119
|
+
void beta_param_tables_destroy(beta_param_tables_t* tables);
|
|
120
|
+
|
|
121
|
+
/* --- Cache lifecycle --- */
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Create a cache that owns private tables built with max_l = n_params.
|
|
125
|
+
* Returns NULL on failure.
|
|
126
|
+
*
|
|
127
|
+
* @param n_params 1 .. BETA_PARAM_CACHE_MAX_PARAMS; the exact length
|
|
128
|
+
* every later params array must have
|
|
129
|
+
* @param thetas Primary theta set in radians (see tables_create)
|
|
130
|
+
* @param n_thetas Number of entries in thetas
|
|
131
|
+
* @param conserve_volume Nonzero: rescale radii to fixed volume
|
|
132
|
+
* @param apply_com Nonzero: apply the centre-of-mass correction
|
|
133
|
+
* @param status Nullable; receives the rejecting code on failure
|
|
134
|
+
*/
|
|
135
|
+
beta_param_cache_t* beta_param_cache_create(
|
|
136
|
+
int n_params, const double* thetas, int n_thetas,
|
|
137
|
+
int conserve_volume, int apply_com, int* status);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Create a cache over caller-owned shared tables. Returns NULL on failure.
|
|
141
|
+
* The tables handle MUST outlive the cache; it is referenced, not copied, and
|
|
142
|
+
* beta_param_cache_destroy() never frees it.
|
|
143
|
+
*
|
|
144
|
+
* @param tables Tables handle; n_params must not exceed its max_l
|
|
145
|
+
* @param n_params 1 .. BETA_PARAM_CACHE_MAX_PARAMS
|
|
146
|
+
* @param conserve_volume Nonzero: rescale radii to fixed volume
|
|
147
|
+
* @param apply_com Nonzero: apply the centre-of-mass correction
|
|
148
|
+
* @param status Nullable; receives the rejecting code on failure
|
|
149
|
+
*/
|
|
150
|
+
beta_param_cache_t* beta_param_cache_create_shared(
|
|
151
|
+
const beta_param_tables_t* tables, int n_params,
|
|
152
|
+
int conserve_volume, int apply_com, int* status);
|
|
153
|
+
|
|
154
|
+
/** Destroy a cache. NULL-safe. Shared tables are left untouched. */
|
|
155
|
+
void beta_param_cache_destroy(beta_param_cache_t* cache);
|
|
156
|
+
|
|
157
|
+
/* --- Node-set lifecycle --- */
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Build an extra evaluation set (thetas plus Legendre P_k and P_k' tables)
|
|
161
|
+
* sized to `tables`. Returns NULL on failure — including a pole node, which is
|
|
162
|
+
* rejected with BETA_PARAM_ERROR_POLE_NODE; use the resolve_shape polar radii
|
|
163
|
+
* for the poles instead.
|
|
164
|
+
*
|
|
165
|
+
* @param tables Tables handle; must outlive the node set
|
|
166
|
+
* @param thetas Node angles in radians; any order, need not be uniform
|
|
167
|
+
* @param n_thetas Number of nodes (at least 2)
|
|
168
|
+
* @param status Nullable; receives the rejecting code on failure
|
|
169
|
+
*/
|
|
170
|
+
beta_param_node_set_t* beta_param_node_set_create(
|
|
171
|
+
const beta_param_tables_t* tables, const double* thetas, int n_thetas,
|
|
172
|
+
int* status);
|
|
173
|
+
|
|
174
|
+
/** Destroy a node set. NULL-safe. */
|
|
175
|
+
void beta_param_node_set_destroy(beta_param_node_set_t* node_set);
|
|
176
|
+
|
|
177
|
+
/* --- Cached computes ---
|
|
178
|
+
*
|
|
179
|
+
* Every one of these mutates the cache (thread-confined, see above). `params`
|
|
180
|
+
* must hold exactly the cache's n_params entries, else
|
|
181
|
+
* BETA_PARAM_ERROR_WRONG_PARAM_COUNT. Output buffer lengths must equal the
|
|
182
|
+
* cache's theta count (or the node set's node count), else
|
|
183
|
+
* BETA_PARAM_ERROR_INVALID_BUFFER_SIZE. Radii and derivatives are
|
|
184
|
+
* COM-corrected and volume-scaled per the cache's flags.
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
/** R(theta) at the cache's primary thetas. `n_radii` must equal that count. */
|
|
188
|
+
int beta_param_cache_radius_grid(
|
|
189
|
+
beta_param_cache_t* cache, const double* params, int n_params,
|
|
190
|
+
double* radii, int n_radii);
|
|
191
|
+
|
|
192
|
+
/** R(theta) and dR/dtheta at the cache's primary thetas. */
|
|
193
|
+
int beta_param_cache_radius_and_derivative(
|
|
194
|
+
beta_param_cache_t* cache, const double* params, int n_params,
|
|
195
|
+
double* radii, double* dr_dthetas, int n_radii);
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* R(theta) at the primary thetas with NO validation gates and NO volume
|
|
199
|
+
* scaling — the rendering/diagnostic path. It reports usage errors only (not
|
|
200
|
+
* initialized, wrong parameter count, buffer size, COM non-convergence), so a
|
|
201
|
+
* shape rejected by the checked path still yields its (partly negative)
|
|
202
|
+
* outline instead of a zero-filled buffer.
|
|
203
|
+
*
|
|
204
|
+
* CAUTION: the radii are UNSCALED even on a cache created with
|
|
205
|
+
* conserve_volume = 1 — this path never computes the volume factor. Mixing it
|
|
206
|
+
* with beta_param_cache_radius_grid() on such a cache draws two outlines of
|
|
207
|
+
* different size for one shape; scale by beta_param_cache_resolve_shape()'s
|
|
208
|
+
* volume_factor if the sizes must agree.
|
|
209
|
+
*/
|
|
210
|
+
int beta_param_cache_radius_grid_unchecked(
|
|
211
|
+
beta_param_cache_t* cache, const double* params, int n_params,
|
|
212
|
+
double* radii, int n_radii);
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Resolve a shape without evaluating a grid: the COM-corrected beta10, the
|
|
216
|
+
* analytic polar radii, and the applied volume factor.
|
|
217
|
+
*
|
|
218
|
+
* `corrected_beta10` is a beta-space value and is never volume-scaled;
|
|
219
|
+
* `r_north` and `r_south` are scaled. `volume_factor` is exactly 1.0 when the
|
|
220
|
+
* cache was created with conserve_volume = 0.
|
|
221
|
+
*/
|
|
222
|
+
int beta_param_cache_resolve_shape(
|
|
223
|
+
beta_param_cache_t* cache, const double* params, int n_params,
|
|
224
|
+
double* corrected_beta10, double* r_north, double* r_south,
|
|
225
|
+
double* volume_factor);
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* R(theta) and dR/dtheta at a node set's thetas. The node set must be built
|
|
229
|
+
* from tables whose max_l is at least the cache's n_params, else
|
|
230
|
+
* BETA_PARAM_ERROR_NODE_SET_MISMATCH. `n_nodes` must equal the node set's node
|
|
231
|
+
* count. This evaluation is not cached; the resolve/validation/volume
|
|
232
|
+
* intermediates behind it are.
|
|
233
|
+
*/
|
|
234
|
+
int beta_param_cache_node_radius_and_derivative(
|
|
235
|
+
beta_param_cache_t* cache, const beta_param_node_set_t* node_set,
|
|
236
|
+
const double* params, int n_params,
|
|
237
|
+
double* radii, double* dr_dthetas, int n_nodes);
|
|
238
|
+
|
|
239
|
+
/* --- Standalone computes (tier 1) ---
|
|
240
|
+
*
|
|
241
|
+
* One-off: tables are built, used and discarded per call — no handle, nothing
|
|
242
|
+
* to free, no engine. `n_params` may be 1 .. BETA_PARAM_MAX_PARAMS_LIMIT (the
|
|
243
|
+
* cached-tier cap does not apply); above that,
|
|
244
|
+
* BETA_PARAM_ERROR_TOO_MANY_PARAMS, never silent truncation. Output buffers
|
|
245
|
+
* hold n_thetas doubles. Outputs are zero-filled on failure.
|
|
246
|
+
*/
|
|
247
|
+
|
|
248
|
+
int beta_param_radius_grid_standalone(
|
|
249
|
+
const double* params, int n_params,
|
|
250
|
+
const double* thetas, int n_thetas,
|
|
251
|
+
int conserve_volume, int apply_com, double* radii);
|
|
252
|
+
|
|
253
|
+
int beta_param_radius_and_derivative_standalone(
|
|
254
|
+
const double* params, int n_params,
|
|
255
|
+
const double* thetas, int n_thetas,
|
|
256
|
+
int conserve_volume, int apply_com,
|
|
257
|
+
double* radii, double* dr_dthetas);
|
|
258
|
+
|
|
259
|
+
#ifdef __cplusplus
|
|
260
|
+
}
|
|
261
|
+
#endif
|
|
262
|
+
|
|
263
|
+
#endif /* BETA_PARAMETERIZATION_H */
|