RustedSciThe 0.4.21

Rust framework for symbolic and numerical computing:BVP ( Newton-Raphson frozen/damped/with collocations ), IVP( BDF, Radau, Backward Euler, LSODE, LSODA, RK45, DoPri), nonlinear equations ( Levenberg, Gavin) and more
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
# RustedSciThe
RustedSciThe is a Rust framework for symbolic and numerical computing.

Build models from equations, prepare analytical derivatives, and solve ODEs,
boundary-value problems, nonlinear systems, and fitting tasks. The maintained
solver families combine configurable numerical backends with parameter reuse,
typed diagnostics, and reproducible test/benchmark workflows.

PROJECT NEWS - October 2026 development highlights:

- The maintained LSODE2, Radau, BDF, and BE routes now have native solver APIs,
  parameter-continuation workflows, detailed diagnostics, and expanded validation.
- The rebuilt BVP_sci solver adds a modern collocation workflow alongside
  BVP_Damp, with adaptive meshes, symbolic frontends, and generated callbacks.
- Nonlinear systems now include a canonical rectangular least-squares LM core;
  fitting APIs build on the shared numerical infrastructure.
- Task-document execution, commented examples, EN/RU guides, and compact
  story/benchmark campaign reports have expanded across solver families.

See [Choose a Solver](#choose-a-solver) and [Guides and Examples](#guides-and-examples)
for current entry points.

##  The RustedSciThe Zen
"
1. Symbolic expressions are documentation that compiles.

2. If users write equations as strings,
they will eventually write a language.

3. DSLs and symbolic algebra belong together.

4. Lambdify early, optimize later.

5. Differentiate analytically.
Finite differences are for debugging and despair.

6. A symbolic Jacobian today saves ten Newton failures tomorrow.

7. The Jacobian decides
whether your method is mathematics
or optimism.

8. Stiff systems forgive nothing.
Analytical Jacobians forgive more.

9. Exact derivatives beat approximate confidence.

10. If an expression can be compiled ahead-of-time,
it probably should be.

11. A solver without statistics is a black box.
Black boxes breed superstition.

12. Measure iterations.
Measure allocations.
Measure regret.

13. Logs are cheaper than debugging.

14. Every numerical method deserves a postprocessor.

15. Plots reveal bugs.
Tables confirm them.

16. The eleventh solver should reuse the first ten.

17. Infrastructure is an algorithm.

18. FFI is a sin.
Try to keep it Rusty. 

19. Borrow from Fortran.
Return with Jacobians and AOT.

20. Ancient libraries deserve reincarnation.
A good numerical method outlives its language.

21. Dense, sparse, and banded:
serious problems need all three.

22. Bandwidth ignored becomes memory wasted.

23. Most nonlinear solvers
are secretly linear solvers.

24. Benchmark before rewriting.
Profile before parallelizing.
Think before GPU-izing.

25. Numerical stability is a feature.

26. Trust convergence criteria.
Distrust convergence.

27. Warnings ignored become papers retracted.

" 

## Features

- **Symbolic modeling:** parse and transform expressions; differentiate and
  simplify them; substitute aliases; construct Jacobians, vectors, and matrices.
- **Two symbolic representations:** the expression-tree `Expr` route and the
  packed `Atom` / borrowed `AtomNative` route, with prepared numerical evaluators.
- **Code generation:** lower supported symbolic models through a shared IR to
  Rust, C, or Zig callbacks; select Lambdify or AOT where the solver supports it.
- **Initial-value ODE solvers:** non-stiff explicit methods, LSODE2, Radau,
  variable-order BDF, and Backward Euler, each with its own documented scope.
- **Boundary-value solvers:** Damped/Frozen Newton and BVP_sci collocation,
  including supported Dense, Sparse, and Banded matrix routes.
- **Nonlinear computation:** square-system root solvers, rectangular
  Levenberg-Marquardt least squares, scalar root finding, curve/kinetic fitting,
  and variable projection for separable models.
- **Reusable workflows:** prepared symbolic models, parameter rebinding,
  continuation and restart in solver APIs that expose those contracts.
- **Numerical infrastructure:** dense, sparse, and banded linear algebra;
  sequential or parallel callback evaluation where supported; typed status and
  error reporting; opt-in telemetry and result postprocessing.
- **Task documents and tooling:** text-based IVP/BVP tasks, recursive symbolic
  aliases, validation, batch execution, plotting, and trajectory visualization.

## Contents

- [Quick Start]#quick-start
- [Features]#features
- [Choose a Solver]#choose-a-solver
- [Symbolic Engine and Backend Choices]#symbolic-engine-and-backend-choices
- [AOT and Parameter Continuation]#aot-and-parameter-continuation
- [Task Documents and CLI]#task-documents-and-cli
- [Guides and Examples]#guides-and-examples
- [Diagnostics, Testing, and Benchmarks]#diagnostics-testing-and-benchmarks
- [Additional Tools and Dependencies]#additional-tools-and-dependencies
- [Executable Mode]#executable-mode
- [Contributing]#contributing

## Quick Start

The crate's core use case is solving nonlinear initial- and boundary-value
problems. This compact example uses Radau and BVP_sci with their default
symbolic frontend, matrix layout, and tolerances.

```rust
use RustedSciThe::numerical::BVP_sci::BvpSciSolver;
use RustedSciThe::numerical::Radau::{RadauConfig, RadauProblem, RadauSolver};
use RustedSciThe::symbolic::symbolic_engine::Expr;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Nonlinear IVP: y' = -y^2, y(0) = 1. Radau defaults to t in [0, 1].
    let problem = RadauProblem::new(
        vec![Expr::parse_expression("-y*y")],
        vec!["y".into()],
        "t",
    );
    let mut ivp = RadauSolver::prepare(problem, RadauConfig::default())?;
    let ivp_solution = ivp.solve(&[1.0])?;
    println!("IVP: y(1) = {:.6}", ivp_solution.y[0]);

    // Nonlinear BVP: y' = y^2, y(0) = 0; the zero function is an exact solution.
    let bvp = BvpSciSolver::builder(
        vec![Expr::parse_expression("y*y")],
        vec!["y".into()],
    )
    .with_mesh_and_initial_state(vec![0.0, 0.5, 1.0], vec![0.0, 0.0, 0.0])
    .with_boundary_callback(|ya, _yb, _parameters, residual| {
        residual[0] = ya[0];
        Ok(())
    })
    .build()?;
    let solution = bvp.solve()?;
    println!("BVP: converged on {} mesh nodes", solution.x.len());
    Ok(())
}
```

Save it as `src/main.rs` in a Cargo project that depends on `RustedSciThe`,
then run it with `cargo run`. For fuller solver configuration, frontend/layout
choices, and continuation, see the solver guides linked below.

## Choose a Solver

The maintained first-tier families are LSODE2, Radau, BDF, BE, BVP_Damp,
BVP_sci, and the modern nonlinear-system infrastructure. Here, **first-tier**
means a supported primary API with guides, typed diagnostics, correctness
coverage, and story/benchmark infrastructure for its supported routes.
It does not imply identical capabilities, unlimited problem sizes, or a universal
performance winner. Legacy/reference implementations are not the recommended
entry points.

| Problem / solver | Method and intended scope | Start here |
|:--|:--|:--|
| IVP: **LSODE2** | LSODE/LSODA-inspired Adams/BDF families; explicit family selection or automatic switching; Dense, Sparse, Banded | [Lambdify guide]examples/lsode2_lambdify_guide.rs |
| IVP: **Radau** | SciPy-inspired fifth-order Radau IIA; adaptive integration; Dense, Sparse, Banded | [Public API guide]examples/radau_public_api_guide.rs |
| IVP: **BDF** | SciPy-inspired variable-order BDF/NDF with adaptive step control; deliberately Dense | [Symbolic continuation]examples/bdf_symbolic_continuation_guide.rs |
| IVP: **Backward Euler** | First-order implicit method with dense Newton solves; explicit fixed-step use for small/medium systems | [Native callbacks]examples/be_native_callbacks_guide.rs |
| IVP: **non-stiff methods** | Explicit methods including RK45 and Dormand-Prince | [Universal ODE example]examples/universal_ode_example.rs |
| BVP: **Damped / Frozen Newton** | Nonlinear boundary-value systems with damping or modified-Newton strategies and configurable linear algebra | [BVP backend guide]examples/bvp_backends_guide.rs |
| BVP: **BVP_sci** | SciPy-like fourth-order collocation, residual control, adaptive mesh, unknown parameters, singular terms, and spline output; Dense, Sparse, Banded | [Lambdify builder guide]examples/bvp_sci_lambdify_guide.rs |
| **Nonlinear systems** | Newton, damped Newton, classical/backtracking/MINPACK-style/Nielsen LM variants, trust-region methods, Powell dogleg; dense linear algebra | [Modern nonlinear guide]examples/nonlinear_systems_modern_guide.rs |
| **Nonlinear least squares** | Separate f64 rectangular LM core with QR/trust-region machinery, typed termination, and symbolic or numerical residuals | [Least-squares API]src/numerical/Nonlinear_systems/NONLINEAR_SYSTEMS_USER_GUIDE_EN.md#rectangular-least-squares-problems |
| **Fitting and parameter estimation** | Symbolic curve fitting, kinetic fitting, and variable projection (VarPro) for separable models | [Universal fitting]examples/universal_fitting_guide.rs, [VarPro]examples/varpro_fitting_guide.rs |
| **Scalar roots** | Brent, bisection, secant, and Newton root finding | [Scalar root API]src/numerical/Nonlinear_systems/scalar_root.rs |

Use the native solver API for detailed numerical and backend configuration.
[UniversalODESolver](src/numerical/ODE_api2.rs) and the
[shared BVP API](src/numerical/BVP_api.rs) provide convenient access for
prototyping across solver families.

Standalone BDF, BE, and nonlinear-system solvers intentionally use dense linear
algebra. For sparse/banded BDF integration, select the BDF family in LSODE2.
BE's optional legacy step heuristic is not adaptive error control. Radau's
maintained implementation has order five; archived order variants are not its
public numerical core.

Root finding seeks a zero of a residual vector; least squares minimizes its
norm and can handle rectangular systems. Fitting APIs build on this distinction.
The symbolic least-squares API also supports user-declared positive variables
for models whose domain requires them, including logarithmic equations.
The older Gavin implementations remain legacy work under review and are not
the recommended fitting path.

## Symbolic Engine and Backend Choices

RustedSciThe started with analytical Jacobians for combustion, chemical kinetics,
and heat/mass transfer. Its symbolic infrastructure now supports IVP, BVP,
nonlinear-system, and fitting workflows.

The engine includes:

- Expression parsing and construction, symbolic differentiation, simplification,
  substitution, and derivative checks against numerical differences.
- Indexed variables, symbolic vectors/matrices, Jacobian construction, and
  structural sparsity analysis.
- **Expr** expression trees and **Atom/AtomNative** packed representations.
  AtomNative provides borrowed access to expressions, normalization,
  differentiation, reusable workspaces, and prepared numerical evaluators.
- Conversion of symbolic models into callable numerical functions (Lambdify),
  including parameterized prepared models in the supported solver APIs.
- A shared code-generation IR and Rust/C/Zig source generation with optimization
  passes such as common-subexpression elimination.
- Taylor expansions, numerical quadrature, and symbolic integration for
  supported elementary expression classes.

Start with the [symbolic construction guide](examples/symbolic/symbolic_construction_guide.rs)
and [derivatives guide](examples/symbolic/symbolic_derivatives_guide.rs).
The engine is a scientific modeling layer, not a claim of unrestricted
computer-algebra coverage.

Solver configuration separates several choices:

| Axis | Choices | What changes |
|:--|:--|:--|
| Model input | Symbolic equations or numerical callbacks | Who supplies the model and derivatives |
| Symbolic frontend | ExprLegacy / AtomNative | Representation used for symbolic preparation |
| Callback execution | Lambdify / AOT | In-process evaluation or generated compiled callbacks |
| Linear layout/backend | Dense / Sparse / Banded, where supported | Matrix storage and factorization |
| Evaluation policy | Sequential / Parallel / Auto, where supported | Callback dispatch and chunking |
| Lifecycle | Fresh preparation / prepared reuse / continuation / restart | Which model and numerical state are retained |

These axes are independent concepts, but not every solver supports their full
Cartesian product. In particular, symbolic Sparse/Banded support does not imply
that the same solver's native callback API accepts sparse/banded Jacobians.
Consult its guide for the supported contract. Several native callback routes
accept an optional analytic Jacobian and use finite differences when it is absent.

Dense can be appropriate for small fully coupled systems; Sparse and Banded
exploit different structures. Atom, AOT, and parallelism can each reduce
cost for suitable workloads, but preparation overhead and linear solves matter.
Compare the same equations, tolerances, layout, and lifecycle.

## AOT and Parameter Continuation

Ahead-of-time compilation turns a prepared symbolic model into compiled
residual/Jacobian callbacks:

```text
equations -> symbolic derivatives -> codegen IR -> Rust/C/Zig source
          -> materialization -> compilation -> loading -> numerical evaluation
```

BVP discretization is an additional stage where the selected method needs it.
Both Lambdify and AOT prepare symbolic work before numerical evaluation; AOT
additionally requires a suitable toolchain to build new artifacts.

The generated-backend infrastructure includes artifact caching, provenance,
and explicit policies such as `BuildIfMissing`, `RequirePrebuilt`, and
`RebuildAlways`. Supported handoff routes let another process consume a
published artifact without recompilation. Compiler and loader requirements
depend on the selected route; see the solver's AOT guide.

Parameter continuation is useful when solving related models repeatedly.
Value-only parameter rebinding can reuse prepared callbacks and compiled
artifacts. Numerical factorization/history reuse depends on the solver and
what changed. A restart with a new initial state is distinct from continuing
an existing trajectory; structural changes may require rebuilding preparation.

For performance decisions, distinguish **cold preparation**, **warm residual and
Jacobian evaluation**, **full solve**, and **the complete continuation series**.
Faster callbacks alone do not guarantee a faster full solve. AOT setup pays off
only when its subsequent savings outweigh compilation/loading costs.

Examples: [LSODE2 AOT continuation](examples/lsode2_parameter_continuation_aot.rs),
[BE symbolic continuation](examples/be_symbolic_continuation_guide.rs),
[BDF AOT](examples/bdf_aot_guide.rs),
[BVP_sci AOT](examples/bvp_sci_aot_guide.rs), and
[nonlinear AOT lifecycle](examples/nonlinear_aot_lifecycle_guide.rs).

## Task Documents and CLI

Text tasks describe equations, conditions, solver options, and outputs without
a custom Rust program. The DSL includes recursive `where` / `substitute`
aliases, declared parameters, continuation plans, and validation with source
diagnostics. Stiff IVP tasks use their solver's native API; non-stiff tasks use
the universal ODE route.

A minimal parameterized IVP document:

```text
task
solver: IVP
method: LSODA

equations
arg: t
parameters: rate
parameter_values: 1.0
y: -rate*y

initial_conditions
t0: 0.0
t_end: 2.0
y0: 1.0

solver_options
rtol: 1e-6
atol: 1e-8
```

From the repository root, these commands work through Cargo without
platform-specific executable paths:

```sh
cargo run -- check examples/task_docs/reference/ivp_lsoda_continuation.txt
cargo run -- run examples/task_docs/reference/ivp_lsoda_continuation.txt
cargo run -- check examples/task_docs/reference/bvp_damped_lambdify.txt
cargo run -- template ivp
cargo run -- template bvp
```

Additional CLI commands include `convert`, `convert-check` (DOCX conversion
requires Pandoc), `check-ffi-dependencies`, and `showcase`. The library's
`run_task_batch` continues after individual task failures and provides a
structured summary.

See the [task-document guide](src/command_interpreter/TASK_DOCS_GUIDE_EN.md),
[commented reference tasks](examples/task_docs/reference/), and
[recursive symbolic aliases example](examples/task_document_symbolic_aliases_guide.rs)
for the complete syntax and per-solver options.

## Guides and Examples

| Family | English | Russian |
|:--|:--|:--|
| LSODE2 | [Guide]src/numerical/LSODE2/LSODE2_USER_GUIDE_EN.md | [Guide]src/numerical/LSODE2/LSODE2_USER_GUIDE_RU.md |
| Radau | [Guide]src/numerical/Radau/RADAU_USER_GUIDE_EN.md | [Guide]src/numerical/Radau/RADAU_USER_GUIDE_RU.md |
| BDF | [Guide]src/numerical/BDF/BDF_USER_GUIDE_EN.md | [Guide]src/numerical/BDF/BDF_USER_GUIDE_RU.md |
| BE | [Guide]src/numerical/BE/BE_USER_GUIDE_EN.md | [Guide]src/numerical/BE/BE_USER_GUIDE_RU.md |
| BVP_Damp | [Guide]src/numerical/BVP_Damp/BVP_DAMP_USER_GUIDE_EN.md | [Guide]src/numerical/BVP_Damp/BVP_DAMP_USER_GUIDE_RU.md |
| BVP_sci | [Guide]src/numerical/BVP_sci/BVP_SCI_USER_GUIDE_EN.md | [Guide]src/numerical/BVP_sci/BVP_SCI_USER_GUIDE_RU.md |
| Nonlinear systems / least squares | [Guide]src/numerical/Nonlinear_systems/NONLINEAR_SYSTEMS_USER_GUIDE_EN.md | [Guide]src/numerical/Nonlinear_systems/NONLINEAR_SYSTEMS_USER_GUIDE_RU.md |
| Shared IVP API | [Guide]src/numerical/IVP_USER_GUIDE_EN.md | [Guide]src/numerical/IVP_USER_GUIDE_RU.md |

The [examples](examples/) directory contains complete Rust example-guides;
[examples/rus](examples/rus/) contains Russian-language counterparts.
Fitting examples include [LM](examples/lm_fitting_guide.rs) and
[VarPro](examples/varpro_fitting_guide.rs). For internal design and validation
conventions, see the [architectural guideline](src/RST_ARCHITECTURAL_GUIDELINE.md).

## Diagnostics, Testing, and Benchmarks

The maintained solver APIs provide typed failures/statuses and opt-in telemetry.
Depending on the solver, counters and stage timings expose symbolic preparation,
callback evaluations, Newton iterations, Jacobian refreshes, factorization,
linear solves, and AOT build/load activity. Logging and detailed instrumentation
are configurable; keep their settings matched when comparing performance.

The test corpus includes exact-solution checks, backend/frontend parity,
independent-solver comparisons, continuation/restart contracts, failure paths,
and AOT lifecycle tests. Story tests and benchmarks produce compact Tabled
reports. The release runners preserve technical logs separately and continue
through individual failures while recording them in a final summary.

A focused debug check:

```sh
cargo test --lib --no-default-features numerical::BDF:: -- --test-threads=1
```

Use `cargo test --lib --no-default-features` for the ordinary library suite.
Ignored stories can require external compilers or substantial time; select the
relevant solver campaign instead of treating them as a quick smoke test.

Campaign runners are available for
[LSODE2](scripts/lsode2_release_matrix.ps1),
[Radau](scripts/radau_release_matrix.ps1),
[BDF](scripts/bdf_release_matrix.ps1),
[BE](scripts/be_release_matrix.ps1),
[BVP_Damp](scripts/bvp_damp_release_matrix.ps1),
[BVP_sci](scripts/bvp_sci_release_matrix.ps1), and
[nonlinear systems](scripts/nonlinear_systems_release_matrix.ps1).
They are PowerShell scripts with solver-specific parameters; inspect the script
before selecting workloads. For example, Radau can print its plan first:

```powershell
./scripts/radau_release_matrix.ps1 -PlanOnly
```

Timing tables are workload-specific evidence. Statistical regression decisions
require repeated, matched measurements; a single story run is not a universal
performance threshold. The [Radau statistical runner](scripts/radau_statistical_baseline.ps1)
supports that separate workflow. Raw run archives and generated artifacts are
not part of the published crate.

## Additional Tools and Dependencies

- [Interpolation and extrapolation]src/numerical/interpolation/ include
  polynomial and piecewise-polynomial utilities shared by numerical solvers.
- [Linear algebra]src/somelinalg/ includes banded LU
  (`LapackStyleBandedLuFaithful`), structured solvers, iterative methods, and
  preconditioners. Banded versus general sparse performance depends on bandwidth,
  conditioning, and workload.
- [Plotting utilities]src/Utils/ provide Plotters/Gnuplot output and terminal
  visualization. [Animation examples]examples/plotting/ use Bevy for 2D/3D
  trajectories.
- Default Cargo features are empty. Optional `arrayfire` and `cuda` features
  require external GPU dependencies; `cuda` also enables `arrayfire`.
  ArrayFire needs its native library, and the custom CUDA path needs its compiled
  native components.
- Optional `lapack` / `openblas-system` features select native linear-algebra
  integrations. Generated AOT toolchains, Gnuplot, and Pandoc are needed only
  for the corresponding workflows.

```sh
cargo build --features arrayfire
cargo build --features cuda
```

## Executable Mode

The crate can also be built as a command-line executable. This lets you provide
a human-readable task document instead of writing a Rust program for each
problem. Build the binary, then pass it a task file:

```sh
cargo build --release
target/release/RustedSciThe run model.txt
```

On Windows, run `target\release\RustedSciThe.exe run model.txt`. The task file
contains the equations, solver and options, plus optional `postprocessing`
settings. Those settings determine whether the run writes numerical data, a
solution report, a plot, or several outputs. See [Task Documents and CLI](#task-documents-and-cli)
for a runnable task example and the supported output formats.

For example, save this nonlinear IVP as `model.txt`:

```text
task
solver: IVP
method: LSODE2

equations
arg: t
y: -y*y

initial_conditions
t0: 0.0
t_end: 1.0
y0: 1.0

postprocessing
write_report: true
report_path: output/solution.md
plotters_png: true
plotters_dir: output/plots
```

Then run `target/release/RustedSciThe run model.txt` (or
`target\release\RustedSciThe.exe run model.txt` on Windows). The task runner
solves the model and writes the Markdown report and Plotters image requested
in `postprocessing`; omit or change those options to select different outputs.

## Contributing

Questions, reproducible bug reports, and contributions are welcome in the
[project repository](https://github.com/Gleb-Zaslavsky/RustedSciThe).
For numerical issues, include the model, initial/boundary conditions, tolerances,
frontend/execution/layout, and a minimal reproducer. Performance reports should
also identify the toolchain, hardware, lifecycle, and instrumentation settings.

RustedSciThe is distributed under the [MIT license](LICENSE.txt).