From 8fff7ce640ccaf807827d8ffc6f32dd2ff57ea1b Mon Sep 17 00:00:00 2001 From: Sfonxu <89732829+Sfonxu@users.noreply.github.com> Date: Thu, 24 Oct 2024 22:03:24 +0200 Subject: [PATCH] add Rust code snippets to the tutorial (incl. CI execution) (#450) Co-authored-by: Sylwester Arabas --- .github/workflows/readme_rust.yml | 43 ++++++++++++++ docs/markdown/pympdata_landing.md | 93 ++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/readme_rust.yml diff --git a/.github/workflows/readme_rust.yml b/.github/workflows/readme_rust.yml new file mode 100644 index 00000000..45c39f14 --- /dev/null +++ b/.github/workflows/readme_rust.yml @@ -0,0 +1,43 @@ +name: readme_rust + +defaults: + run: + shell: bash + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: '0 13 * * 4' + +jobs: + rust: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@stable + with: + components: rust-src + - uses: actions/setup-python@v5 + with: + python-version: 3.9 + - run: pip install -e . + - run: pip install pytest-codeblocks pytest + + - run: | + cat >Cargo.toml < Python code (click to expand) +
+Rust code (click to expand) +```Rust +use pyo3::prelude::*; +use pyo3::types::{IntoPyDict, PyDict, PyTuple}; + +fn main() -> PyResult<()> { + Python::with_gil(|py| { + let options_args = [("n_iters", 2)].into_py_dict_bound(py); + let options = py.import_bound("PyMPDATA")?.getattr("Options")?.call((), Some(&options_args))?; +``` +
+ ```Python from PyMPDATA import Options options = Options(n_iters=2) @@ -236,6 +249,45 @@ advector = VectorField(pyargs(... )); ``` + +
+Rust code (click to expand) +```Rust + let vector_field = py.import_bound("PyMPDATA")?.getattr("VectorField")?; + let scalar_field = py.import_bound("PyMPDATA")?.getattr("ScalarField")?; + let periodic = py.import_bound("PyMPDATA.boundary_conditions")?.getattr("Periodic")?; + + let nx_ny = [24, 24]; + let cx_cy = [-0.5, -0.25]; + let boundary_con = PyTuple::new_bound(py, [periodic.call0()?, periodic.call0()?]).into_any(); + let halo = options.getattr("n_halo")?; + + let indices = PyDict::new_bound(py); + Python::run_bound(py, &format!(r#" +import numpy as np +nx, ny = {}, {} +xi, yi = np.indices((nx, ny), dtype=float) +data=np.exp( + -(xi+.5-nx/2)**2 / (2*(ny/10)**2) + -(yi+.5-nx/2)**2 / (2*(ny/10)**2) +) + "#, nx_ny[0], nx_ny[1]), None, Some(&indices)).unwrap(); + + let advectee_arg = vec![("data", indices.get_item("data")?), ("halo", Some(halo.clone())), ("boundary_conditions", Some(boundary_con))].into_py_dict_bound(py); + let advectee = scalar_field.call((), Some(&advectee_arg))?; + let full = PyDict::new_bound(py); + Python::run_bound(py, &format!(r#" +import numpy as np +nx, ny = {}, {} +Cx, Cy = {}, {} +data = (np.full((nx + 1, ny), Cx), np.full((nx, ny + 1), Cy)) + "#, nx_ny[0], nx_ny[1], cx_cy[0], cx_cy[1]), None, Some(&full)).unwrap(); + let boundary_con = PyTuple::new_bound(py, [periodic.call0()?, periodic.call0()?]).into_any(); + let advector_arg = vec![("data", full.get_item("data")?), ("halo", Some(halo.clone())), ("boundary_conditions", Some(boundary_con))].into_py_dict_bound(py); + let advector = vector_field.call((), Some(&advector_arg))?; +``` +
+
Python code (click to expand) @@ -306,6 +358,18 @@ stepper = Stepper(pyargs(... ```
+ +
+Rust code (click to expand) + +```Rust +let n_dims: i32 = 2; +let stepper_arg = PyDict::new_bound(py); +let _ = PyDictMethods::set_item(&stepper_arg, "options", &options); +let _ = PyDictMethods::set_item(&stepper_arg, "n_dims", &n_dims); +``` +
+ Python code (click to expand) ```Python @@ -332,6 +396,17 @@ stepper = Stepper(pyargs(... )); ```
+ +
+Rust code (click to expand) + +```Rust + let _stepper_arg_alternative = vec![("options", &options), ("grid", &PyTuple::new_bound(py, nx_ny).into_any())].into_py_dict_bound(py); + let stepper_ = py.import_bound("PyMPDATA")?.getattr("Stepper")?; + let stepper = stepper_.call((), Some(&stepper_arg))?; //or use stepper args alternative +``` +
+
Python code (click to expand) @@ -406,6 +481,22 @@ solver.advance(pyargs('n_steps', 75)); state = solver.advectee.get(); ```
+ +
+Rust code (click to expand) + +```Rust + let solver_ = py.import_bound("PyMPDATA")?.getattr("Solver")?; + let solver = solver_.call((), Some(&vec![("stepper", stepper), ("advectee", advectee), ("advector", advector)].into_py_dict_bound(py)))?; + let _state_0 = solver.getattr("advectee")?.getattr("get")?.call0()?.getattr("copy")?.call0()?; + solver.getattr("advance")?.call((), Some(&vec![("n_steps", 75)].into_py_dict_bound(py)))?; + let _state = solver.getattr("advectee")?.getattr("get")?.call0()?; + Ok(()) + }) +} +``` +
+
Python code (click to expand)