PyParticles3 0.4.0rc1__tar.gz → 0.4.0rc2__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.
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/CHANGELOG.md +22 -1
- {pyparticles3-0.4.0rc1/PyParticles3.egg-info → pyparticles3-0.4.0rc2}/PKG-INFO +63 -5
- pyparticles3-0.4.0rc2/PUBLISHING.md +179 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2/PyParticles3.egg-info}/PKG-INFO +63 -5
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/PyParticles3.egg-info/SOURCES.txt +1 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/README.md +62 -4
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/opencl_context.py +58 -19
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/utils/pypart_global.py +37 -2
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyproject.toml +1 -1
- pyparticles3-0.4.0rc2/tests/test_opencl_device_selection.py +82 -0
- pyparticles3-0.4.0rc1/PUBLISHING.md +0 -100
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/LICENSE-gpl-3.0.txt +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/MANIFEST.in +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/PyParticles3.egg-info/dependency_links.txt +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/PyParticles3.egg-info/entry_points.txt +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/PyParticles3.egg-info/requires.txt +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/PyParticles3.egg-info/top_level.txt +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/README.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Config File.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Logo/pyparticles_logo.svg +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Makefile +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Packages Descriptions.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Programming Example II.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Programming Example.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/Testing.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/conf.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/img/dam_an.jpg +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/img/dhar.png +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/img/fall.png +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/img/fall_an.jpg +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/img/har.png +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/img/har_an.jpg +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/index.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/intro.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/logo.png +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/logo_pyp.png +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/make.bat +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/modules.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.animation.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.demo.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.forces.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.geometry.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.main.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.measures.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.ode.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.ogl.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.pset.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/doc/pyparticles.utils.rst +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/example/cluster_demo.cfg +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/example/solar_sys.csv +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/example/solar_system.csv +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/man/install.sh +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/man/pyparticles.1 +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/__main__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/animated_cli.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/animated_ogl.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/animated_ogl_compat.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/animated_scatter.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/animation.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/animation/test_animation.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/bubble.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/electromagnetic_demo.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/electrostatic_demo.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/fountain.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/gas_lennard_jones.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/gravity_clusters.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/solar_system.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/springs.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/springs_constr.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/demo/test.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/const_force.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/damping.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/drag.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/electromagnetic.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/electromagnetic_field.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/electrostatic.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/force.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/force_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/fused_const_drag.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/gravity.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/lennard_jones.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/linear_spring.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/linear_spring_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/multiple_force.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/pseudo_bubble.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/van_der_waals_force.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/forces/vector_field_force.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/geometry/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/geometry/dist.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/geometry/intersection.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/geometry/transformations.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/main/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/main/main.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/elastic_potential_energy.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/gravitational_potential_energy.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/kinetic_energy.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/mass.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/measure.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/momentum.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/measures/total_energy.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/euler_solver.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/euler_solver_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/leapfrog_solver.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/leapfrog_solver_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/midpoint_solver.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/midpoint_solver_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/ode_solver.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/ode_solver_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/runge_kutta_solver.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/runge_kutta_solver_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/sim_time.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/stormer_verlet_solver.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ode/stormer_verlet_solver_constrained.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/axis_ogl.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/draw_particles_ogl.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/draw_particles_ogl_compat.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/draw_vector_field.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/opencl_gl_vbo.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/trackball.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/ogl/translate_scene.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/boundary.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/cluster.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/constrained_force_interactions.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/constrained_x.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/constraint.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/default_boundary.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/file_cluster.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/logger.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/octree.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/particles_set.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/periodic_boundary.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/rand_cluster.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/pset/rebound_boundary.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/utils/__init__.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/utils/parse_args.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/utils/problem_config.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/pyparticles/utils/time_formatter.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/setup.cfg +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/setup.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/tests/test_demo_compat.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/tests/test_opencl_compute_only.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/tests/test_opencl_regression.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/tests/test_opencl_residency.py +0 -0
- {pyparticles3-0.4.0rc1 → pyparticles3-0.4.0rc2}/tests/test_particles_set_compat.py +0 -0
|
@@ -2,9 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the modernized distribution are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.4.0rc2 - release candidate
|
|
6
|
+
|
|
7
|
+
Follow-up release candidate based on installation and multi-ICD validation of `0.4.0rc1`.
|
|
8
|
+
|
|
9
|
+
### OpenCL/OpenGL interoperability
|
|
10
|
+
|
|
11
|
+
- document that `PyParticles3[opencl]` guarantees OpenCL compute support but does not guarantee a PyOpenCL build with OpenGL interoperability;
|
|
12
|
+
- add an explicit runtime warning when `pyopencl.have_gl()` is `False`;
|
|
13
|
+
- document rebuilding PyOpenCL from source with `PYOPENCL_ENABLE_GL=ON` and verifying `pyopencl.have_gl() is True`;
|
|
14
|
+
- preserve an explicit `PYOPENCL_CTX` device selection when creating a CL/GL sharing context;
|
|
15
|
+
- do not silently migrate an explicitly selected Intel CPU OpenCL workload to an NVIDIA GPU merely to obtain `cl_khr_gl_sharing`;
|
|
16
|
+
- improve CL/GL failure messages so host-synchronized fallback identifies why sharing is unavailable.
|
|
17
|
+
|
|
18
|
+
### Validation
|
|
19
|
+
|
|
20
|
+
- validated OpenCL gravity kernels on NVIDIA GTX 1060 and Intel Xeon E5-2697 v2 OpenCL implementations;
|
|
21
|
+
- validated CPU/OpenCL numerical agreement over complete Euler integration runs;
|
|
22
|
+
- validated persistent X/V device residency and transfer accounting;
|
|
23
|
+
- validated clean PyPI installation and all published CLI entry points;
|
|
24
|
+
- validated the high-performance fountain CL/GL path with a GL-enabled PyOpenCL build.
|
|
25
|
+
|
|
5
26
|
## 0.4.0rc1 - release candidate
|
|
6
27
|
|
|
7
|
-
First release candidate
|
|
28
|
+
First release candidate under the **PyParticles3** distribution name.
|
|
8
29
|
|
|
9
30
|
### Packaging
|
|
10
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyParticles3
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.0rc2
|
|
4
4
|
Summary: Modern educational particle simulation toolbox with OpenCL/OpenGL acceleration
|
|
5
5
|
Author: Simone Riva
|
|
6
6
|
Maintainer: jamaj69
|
|
@@ -64,15 +64,13 @@ The goal is to preserve the original project's unusually clear, educational arch
|
|
|
64
64
|
|
|
65
65
|
## Installation
|
|
66
66
|
|
|
67
|
-
The
|
|
68
|
-
|
|
69
|
-
Once published:
|
|
67
|
+
The current release candidate is `PyParticles3 0.4.0rc2`.
|
|
70
68
|
|
|
71
69
|
```bash
|
|
72
70
|
python -m pip install PyParticles3
|
|
73
71
|
```
|
|
74
72
|
|
|
75
|
-
For OpenCL support:
|
|
73
|
+
For OpenCL compute support:
|
|
76
74
|
|
|
77
75
|
```bash
|
|
78
76
|
python -m pip install 'PyParticles3[opencl]'
|
|
@@ -80,6 +78,66 @@ python -m pip install 'PyParticles3[opencl]'
|
|
|
80
78
|
|
|
81
79
|
The OpenCL runtime/ICD and an OpenGL/FreeGLUT implementation are system-level dependencies and are not installed by pip.
|
|
82
80
|
|
|
81
|
+
### OpenCL/OpenGL interoperability requires a GL-enabled PyOpenCL build
|
|
82
|
+
|
|
83
|
+
`PyParticles3[opencl]` installs PyOpenCL and is sufficient for OpenCL **compute**. It does **not** guarantee that the installed PyOpenCL binary was compiled with OpenGL interoperability enabled.
|
|
84
|
+
|
|
85
|
+
Check the installed build with:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python - <<'PY'
|
|
89
|
+
import pyopencl as cl
|
|
90
|
+
print("PyOpenCL:", cl.VERSION_TEXT)
|
|
91
|
+
print("have_gl :", cl.have_gl())
|
|
92
|
+
PY
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For the fast OpenCL/OpenGL shared-buffer path used by the `fountain` demo, the required result is:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
have_gl : True
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
If a PyPI wheel reports `have_gl : False`, OpenCL compute still works, but PyParticles3 cannot create `GLBuffer` objects and high-particle-count rendering must fall back to host synchronization. That fallback can be dramatically slower.
|
|
102
|
+
|
|
103
|
+
PyOpenCL's source-build documentation requires `PYOPENCL_ENABLE_GL=ON` to enable GL interoperability. A typical pip rebuild is:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
python -m pip uninstall -y pyopencl
|
|
107
|
+
|
|
108
|
+
PYOPENCL_ENABLE_GL=ON \
|
|
109
|
+
python -m pip install \
|
|
110
|
+
--no-binary=pyopencl \
|
|
111
|
+
--no-cache-dir \
|
|
112
|
+
-v \
|
|
113
|
+
'pyopencl>=2026.1'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Then verify again:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python - <<'PY'
|
|
120
|
+
import pyopencl as cl
|
|
121
|
+
assert cl.have_gl(), "PyOpenCL was built without OpenGL interoperability"
|
|
122
|
+
print("PyOpenCL GL interoperability: enabled")
|
|
123
|
+
PY
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Building PyOpenCL from source also requires a C++17 compiler, Python/build dependencies, OpenCL headers and loader libraries, and OpenGL development headers appropriate to the operating system.
|
|
127
|
+
|
|
128
|
+
## Selecting an OpenCL device
|
|
129
|
+
|
|
130
|
+
PyParticles3 follows PyOpenCL's `PYOPENCL_CTX` selection for compute contexts. For example, on a system where platform 0 is an NVIDIA GPU and platform 1 is an Intel CPU:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
PYOPENCL_CTX=0:0 pyparticles3 --demo fountain
|
|
134
|
+
PYOPENCL_CTX=1:0 pyparticles3 --demo fountain
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
As of `0.4.0rc2`, an explicit `PYOPENCL_CTX` selection is also honored when PyParticles3 attempts to create a CL/GL sharing context. PyParticles3 will not silently move the simulation to another OpenCL device just because that other device supports `cl_khr_gl_sharing`.
|
|
138
|
+
|
|
139
|
+
This matters on mixed systems. An Intel Xeon CPU OpenCL device can execute the simulation kernels but may not advertise or support `cl_khr_gl_sharing` with the active NVIDIA OpenGL context. In that case PyParticles3 keeps the selected Intel compute device and falls back to host-synchronized rendering instead of silently switching compute to the NVIDIA GPU.
|
|
140
|
+
|
|
83
141
|
## Current import namespace
|
|
84
142
|
|
|
85
143
|
The initial PyParticles3 packaging release intentionally keeps the historical Python import namespace:
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Publishing PyParticles3 to PyPI
|
|
2
|
+
|
|
3
|
+
This repository is prepared to publish the `PyParticles3` distribution through PyPI Trusted Publishing.
|
|
4
|
+
|
|
5
|
+
## Why Trusted Publishing
|
|
6
|
+
|
|
7
|
+
The release workflow uses GitHub Actions OIDC instead of storing a long-lived PyPI API token in the repository. PyPI issues a short-lived credential to the trusted workflow at publication time.
|
|
8
|
+
|
|
9
|
+
## PyPI publisher configuration
|
|
10
|
+
|
|
11
|
+
The PyPI project is published from this GitHub repository with these values:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
PyPI project name : PyParticles3
|
|
15
|
+
GitHub owner : jamaj69
|
|
16
|
+
Repository : pyparticles
|
|
17
|
+
Workflow : release.yml
|
|
18
|
+
Environment : pypi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## GitHub environment
|
|
22
|
+
|
|
23
|
+
The release workflow uses the GitHub Actions environment:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
pypi
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For a public release project, required reviewers on this environment are recommended so a tag cannot publish without an explicit approval step.
|
|
30
|
+
|
|
31
|
+
## Release candidates
|
|
32
|
+
|
|
33
|
+
The first published candidate was:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
PyParticles3 0.4.0rc1
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The current candidate is:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
PyParticles3 0.4.0rc2
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`0.4.0rc2` adds explicit diagnostics for PyOpenCL builds without GL interoperability and ensures that an explicit `PYOPENCL_CTX` selection is not silently replaced by another device when CL/GL sharing is attempted.
|
|
46
|
+
|
|
47
|
+
After CI is green, publish the candidate with:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git tag -a v0.4.0rc2 -m "PyParticles3 0.4.0rc2"
|
|
51
|
+
git push origin v0.4.0rc2
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`.github/workflows/release.yml` will:
|
|
55
|
+
|
|
56
|
+
1. build the wheel and source distribution;
|
|
57
|
+
2. run `twine check`;
|
|
58
|
+
3. pass the artifacts to a separate publish job;
|
|
59
|
+
4. request an OIDC publishing credential;
|
|
60
|
+
5. upload the release to PyPI.
|
|
61
|
+
|
|
62
|
+
## Repository references shown by PyPI
|
|
63
|
+
|
|
64
|
+
`pyproject.toml` declares:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
Homepage https://github.com/jamaj69/pyparticles
|
|
68
|
+
Source https://github.com/jamaj69/pyparticles
|
|
69
|
+
Documentation https://github.com/jamaj69/pyparticles#readme
|
|
70
|
+
Issues https://github.com/jamaj69/pyparticles/issues
|
|
71
|
+
Original https://github.com/simon-r/PyParticles
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Because releases are uploaded through GitHub Trusted Publishing from `jamaj69/pyparticles`, PyPI can verify links belonging to that GitHub repository.
|
|
75
|
+
|
|
76
|
+
## Release discipline
|
|
77
|
+
|
|
78
|
+
Do not reuse a version already uploaded to PyPI. If a release artifact must change, increment the version first.
|
|
79
|
+
|
|
80
|
+
Recommended sequence:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
0.4.0rc1
|
|
84
|
+
0.4.0rc2
|
|
85
|
+
0.4.0rc3 (only if another release candidate is needed)
|
|
86
|
+
0.4.0
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Local verification before tagging
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python -m pip install -U build twine
|
|
93
|
+
rm -rf build dist *.egg-info
|
|
94
|
+
python -m build
|
|
95
|
+
python -m twine check dist/*
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then test the wheel in a clean environment, outside the source tree:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python -m venv /tmp/pyparticles3-release-test
|
|
102
|
+
source /tmp/pyparticles3-release-test/bin/activate
|
|
103
|
+
cd /tmp
|
|
104
|
+
unset PYTHONPATH
|
|
105
|
+
python -m pip install '/path/to/dist/PyParticles3-0.4.0rc2-py3-none-any.whl[opencl]'
|
|
106
|
+
python -m pip check
|
|
107
|
+
pyparticles3 --version
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## OpenCL compute validation
|
|
111
|
+
|
|
112
|
+
List available platforms/devices and test each desired ICD explicitly. For example:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python - <<'PY'
|
|
116
|
+
import pyopencl as cl
|
|
117
|
+
for pi, platform in enumerate(cl.get_platforms()):
|
|
118
|
+
for di, device in enumerate(platform.get_devices()):
|
|
119
|
+
print(f"{pi}:{di} {platform.name} {device.name}")
|
|
120
|
+
PY
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Then select devices with `PYOPENCL_CTX`, for example:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
PYOPENCL_CTX=0:0 pyparticles3 --demo fountain
|
|
127
|
+
PYOPENCL_CTX=1:0 pyparticles3 --demo fountain
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The selected device must remain the selected compute device. `0.4.0rc2` must not silently migrate an explicit Intel CPU selection to an NVIDIA GPU merely to obtain CL/GL sharing.
|
|
131
|
+
|
|
132
|
+
## CL/GL release validation
|
|
133
|
+
|
|
134
|
+
The optional `opencl` extra guarantees PyOpenCL compute support only. A PyOpenCL wheel may report:
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
have_gl : False
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
For CL/GL validation, verify:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
python - <<'PY'
|
|
144
|
+
import pyopencl as cl
|
|
145
|
+
print("PyOpenCL:", cl.VERSION_TEXT)
|
|
146
|
+
print("have_gl :", cl.have_gl())
|
|
147
|
+
PY
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The shared-buffer fountain path requires:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
have_gl : True
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
If necessary, rebuild PyOpenCL from source with GL support:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
python -m pip uninstall -y pyopencl
|
|
160
|
+
|
|
161
|
+
PYOPENCL_ENABLE_GL=ON \
|
|
162
|
+
python -m pip install \
|
|
163
|
+
--no-binary=pyopencl \
|
|
164
|
+
--no-cache-dir \
|
|
165
|
+
-v \
|
|
166
|
+
'pyopencl>=2026.1'
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Then require the result programmatically:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
python - <<'PY'
|
|
173
|
+
import pyopencl as cl
|
|
174
|
+
assert cl.have_gl(), "PyOpenCL was built without OpenGL interoperability"
|
|
175
|
+
print("PyOpenCL GL interoperability: enabled")
|
|
176
|
+
PY
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
A selected OpenCL device that cannot share the active OpenGL context is allowed to fall back to host-synchronized rendering, but the fallback must be explicit and the compute device must not silently change.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyParticles3
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.0rc2
|
|
4
4
|
Summary: Modern educational particle simulation toolbox with OpenCL/OpenGL acceleration
|
|
5
5
|
Author: Simone Riva
|
|
6
6
|
Maintainer: jamaj69
|
|
@@ -64,15 +64,13 @@ The goal is to preserve the original project's unusually clear, educational arch
|
|
|
64
64
|
|
|
65
65
|
## Installation
|
|
66
66
|
|
|
67
|
-
The
|
|
68
|
-
|
|
69
|
-
Once published:
|
|
67
|
+
The current release candidate is `PyParticles3 0.4.0rc2`.
|
|
70
68
|
|
|
71
69
|
```bash
|
|
72
70
|
python -m pip install PyParticles3
|
|
73
71
|
```
|
|
74
72
|
|
|
75
|
-
For OpenCL support:
|
|
73
|
+
For OpenCL compute support:
|
|
76
74
|
|
|
77
75
|
```bash
|
|
78
76
|
python -m pip install 'PyParticles3[opencl]'
|
|
@@ -80,6 +78,66 @@ python -m pip install 'PyParticles3[opencl]'
|
|
|
80
78
|
|
|
81
79
|
The OpenCL runtime/ICD and an OpenGL/FreeGLUT implementation are system-level dependencies and are not installed by pip.
|
|
82
80
|
|
|
81
|
+
### OpenCL/OpenGL interoperability requires a GL-enabled PyOpenCL build
|
|
82
|
+
|
|
83
|
+
`PyParticles3[opencl]` installs PyOpenCL and is sufficient for OpenCL **compute**. It does **not** guarantee that the installed PyOpenCL binary was compiled with OpenGL interoperability enabled.
|
|
84
|
+
|
|
85
|
+
Check the installed build with:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python - <<'PY'
|
|
89
|
+
import pyopencl as cl
|
|
90
|
+
print("PyOpenCL:", cl.VERSION_TEXT)
|
|
91
|
+
print("have_gl :", cl.have_gl())
|
|
92
|
+
PY
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For the fast OpenCL/OpenGL shared-buffer path used by the `fountain` demo, the required result is:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
have_gl : True
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
If a PyPI wheel reports `have_gl : False`, OpenCL compute still works, but PyParticles3 cannot create `GLBuffer` objects and high-particle-count rendering must fall back to host synchronization. That fallback can be dramatically slower.
|
|
102
|
+
|
|
103
|
+
PyOpenCL's source-build documentation requires `PYOPENCL_ENABLE_GL=ON` to enable GL interoperability. A typical pip rebuild is:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
python -m pip uninstall -y pyopencl
|
|
107
|
+
|
|
108
|
+
PYOPENCL_ENABLE_GL=ON \
|
|
109
|
+
python -m pip install \
|
|
110
|
+
--no-binary=pyopencl \
|
|
111
|
+
--no-cache-dir \
|
|
112
|
+
-v \
|
|
113
|
+
'pyopencl>=2026.1'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Then verify again:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python - <<'PY'
|
|
120
|
+
import pyopencl as cl
|
|
121
|
+
assert cl.have_gl(), "PyOpenCL was built without OpenGL interoperability"
|
|
122
|
+
print("PyOpenCL GL interoperability: enabled")
|
|
123
|
+
PY
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Building PyOpenCL from source also requires a C++17 compiler, Python/build dependencies, OpenCL headers and loader libraries, and OpenGL development headers appropriate to the operating system.
|
|
127
|
+
|
|
128
|
+
## Selecting an OpenCL device
|
|
129
|
+
|
|
130
|
+
PyParticles3 follows PyOpenCL's `PYOPENCL_CTX` selection for compute contexts. For example, on a system where platform 0 is an NVIDIA GPU and platform 1 is an Intel CPU:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
PYOPENCL_CTX=0:0 pyparticles3 --demo fountain
|
|
134
|
+
PYOPENCL_CTX=1:0 pyparticles3 --demo fountain
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
As of `0.4.0rc2`, an explicit `PYOPENCL_CTX` selection is also honored when PyParticles3 attempts to create a CL/GL sharing context. PyParticles3 will not silently move the simulation to another OpenCL device just because that other device supports `cl_khr_gl_sharing`.
|
|
138
|
+
|
|
139
|
+
This matters on mixed systems. An Intel Xeon CPU OpenCL device can execute the simulation kernels but may not advertise or support `cl_khr_gl_sharing` with the active NVIDIA OpenGL context. In that case PyParticles3 keeps the selected Intel compute device and falls back to host-synchronized rendering instead of silently switching compute to the NVIDIA GPU.
|
|
140
|
+
|
|
83
141
|
## Current import namespace
|
|
84
142
|
|
|
85
143
|
The initial PyParticles3 packaging release intentionally keeps the historical Python import namespace:
|
|
@@ -144,6 +144,7 @@ pyparticles/utils/pypart_global.py
|
|
|
144
144
|
pyparticles/utils/time_formatter.py
|
|
145
145
|
tests/test_demo_compat.py
|
|
146
146
|
tests/test_opencl_compute_only.py
|
|
147
|
+
tests/test_opencl_device_selection.py
|
|
147
148
|
tests/test_opencl_regression.py
|
|
148
149
|
tests/test_opencl_residency.py
|
|
149
150
|
tests/test_particles_set_compat.py
|
|
@@ -23,15 +23,13 @@ The goal is to preserve the original project's unusually clear, educational arch
|
|
|
23
23
|
|
|
24
24
|
## Installation
|
|
25
25
|
|
|
26
|
-
The
|
|
27
|
-
|
|
28
|
-
Once published:
|
|
26
|
+
The current release candidate is `PyParticles3 0.4.0rc2`.
|
|
29
27
|
|
|
30
28
|
```bash
|
|
31
29
|
python -m pip install PyParticles3
|
|
32
30
|
```
|
|
33
31
|
|
|
34
|
-
For OpenCL support:
|
|
32
|
+
For OpenCL compute support:
|
|
35
33
|
|
|
36
34
|
```bash
|
|
37
35
|
python -m pip install 'PyParticles3[opencl]'
|
|
@@ -39,6 +37,66 @@ python -m pip install 'PyParticles3[opencl]'
|
|
|
39
37
|
|
|
40
38
|
The OpenCL runtime/ICD and an OpenGL/FreeGLUT implementation are system-level dependencies and are not installed by pip.
|
|
41
39
|
|
|
40
|
+
### OpenCL/OpenGL interoperability requires a GL-enabled PyOpenCL build
|
|
41
|
+
|
|
42
|
+
`PyParticles3[opencl]` installs PyOpenCL and is sufficient for OpenCL **compute**. It does **not** guarantee that the installed PyOpenCL binary was compiled with OpenGL interoperability enabled.
|
|
43
|
+
|
|
44
|
+
Check the installed build with:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python - <<'PY'
|
|
48
|
+
import pyopencl as cl
|
|
49
|
+
print("PyOpenCL:", cl.VERSION_TEXT)
|
|
50
|
+
print("have_gl :", cl.have_gl())
|
|
51
|
+
PY
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For the fast OpenCL/OpenGL shared-buffer path used by the `fountain` demo, the required result is:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
have_gl : True
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If a PyPI wheel reports `have_gl : False`, OpenCL compute still works, but PyParticles3 cannot create `GLBuffer` objects and high-particle-count rendering must fall back to host synchronization. That fallback can be dramatically slower.
|
|
61
|
+
|
|
62
|
+
PyOpenCL's source-build documentation requires `PYOPENCL_ENABLE_GL=ON` to enable GL interoperability. A typical pip rebuild is:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
python -m pip uninstall -y pyopencl
|
|
66
|
+
|
|
67
|
+
PYOPENCL_ENABLE_GL=ON \
|
|
68
|
+
python -m pip install \
|
|
69
|
+
--no-binary=pyopencl \
|
|
70
|
+
--no-cache-dir \
|
|
71
|
+
-v \
|
|
72
|
+
'pyopencl>=2026.1'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then verify again:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
python - <<'PY'
|
|
79
|
+
import pyopencl as cl
|
|
80
|
+
assert cl.have_gl(), "PyOpenCL was built without OpenGL interoperability"
|
|
81
|
+
print("PyOpenCL GL interoperability: enabled")
|
|
82
|
+
PY
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Building PyOpenCL from source also requires a C++17 compiler, Python/build dependencies, OpenCL headers and loader libraries, and OpenGL development headers appropriate to the operating system.
|
|
86
|
+
|
|
87
|
+
## Selecting an OpenCL device
|
|
88
|
+
|
|
89
|
+
PyParticles3 follows PyOpenCL's `PYOPENCL_CTX` selection for compute contexts. For example, on a system where platform 0 is an NVIDIA GPU and platform 1 is an Intel CPU:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
PYOPENCL_CTX=0:0 pyparticles3 --demo fountain
|
|
93
|
+
PYOPENCL_CTX=1:0 pyparticles3 --demo fountain
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
As of `0.4.0rc2`, an explicit `PYOPENCL_CTX` selection is also honored when PyParticles3 attempts to create a CL/GL sharing context. PyParticles3 will not silently move the simulation to another OpenCL device just because that other device supports `cl_khr_gl_sharing`.
|
|
97
|
+
|
|
98
|
+
This matters on mixed systems. An Intel Xeon CPU OpenCL device can execute the simulation kernels but may not advertise or support `cl_khr_gl_sharing` with the active NVIDIA OpenGL context. In that case PyParticles3 keeps the selected Intel compute device and falls back to host-synchronized rendering instead of silently switching compute to the NVIDIA GPU.
|
|
99
|
+
|
|
42
100
|
## Current import namespace
|
|
43
101
|
|
|
44
102
|
The initial PyParticles3 packaging release intentionally keeps the historical Python import namespace:
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
# the Free Software Foundation, either version 3 of the License, or
|
|
7
7
|
# (at your option) any later version.
|
|
8
8
|
|
|
9
|
+
import os
|
|
10
|
+
|
|
9
11
|
import numpy as np
|
|
10
12
|
|
|
11
13
|
|
|
@@ -50,6 +52,11 @@ class OpenCLcontext(object):
|
|
|
50
52
|
context. In GL-sharing mode normal particle arrays remain ordinary OpenCL
|
|
51
53
|
buffers; a renderer may create :class:`pyopencl.GLBuffer` objects in the
|
|
52
54
|
same context and copy positions VRAM-to-VRAM without crossing PCIe.
|
|
55
|
+
|
|
56
|
+
When ``PYOPENCL_CTX`` explicitly selects a device, GL-sharing context
|
|
57
|
+
creation honors that same selection. PyParticles3 will not silently move
|
|
58
|
+
the simulation to a different OpenCL device merely because another device
|
|
59
|
+
supports ``cl_khr_gl_sharing``.
|
|
53
60
|
"""
|
|
54
61
|
|
|
55
62
|
_VALID_NAMES = ("X", "V", "A", "M")
|
|
@@ -88,7 +95,8 @@ class OpenCLcontext(object):
|
|
|
88
95
|
except Exception as exc:
|
|
89
96
|
if self.__gl_sharing:
|
|
90
97
|
raise RuntimeError(
|
|
91
|
-
"No OpenCL context could share the active OpenGL context"
|
|
98
|
+
"No OpenCL context could share the active OpenGL context: %s"
|
|
99
|
+
% exc
|
|
92
100
|
) from exc
|
|
93
101
|
raise RuntimeError("No usable OpenCL context could be created") from exc
|
|
94
102
|
|
|
@@ -110,30 +118,61 @@ class OpenCLcontext(object):
|
|
|
110
118
|
}
|
|
111
119
|
self.reset_transfer_stats()
|
|
112
120
|
|
|
121
|
+
def _gl_sharing_candidate_devices(self):
|
|
122
|
+
"""Return candidate devices without overriding an explicit selection."""
|
|
123
|
+
selector = os.environ.get("PYOPENCL_CTX", "").strip()
|
|
124
|
+
if selector:
|
|
125
|
+
selected_context = cl.create_some_context(interactive=False)
|
|
126
|
+
devices = list(selected_context.devices)
|
|
127
|
+
if not devices:
|
|
128
|
+
raise RuntimeError(
|
|
129
|
+
"PYOPENCL_CTX=%r did not select an OpenCL device" % selector
|
|
130
|
+
)
|
|
131
|
+
return devices, selector
|
|
132
|
+
|
|
133
|
+
devices = []
|
|
134
|
+
for platform in cl.get_platforms():
|
|
135
|
+
devices.extend(platform.get_devices())
|
|
136
|
+
return devices, None
|
|
137
|
+
|
|
113
138
|
def _create_gl_sharing_context(self):
|
|
114
139
|
if not hasattr(cl, "have_gl") or not cl.have_gl():
|
|
115
140
|
raise RuntimeError("PyOpenCL was built without OpenGL interoperability")
|
|
116
141
|
|
|
117
142
|
sharing = get_gl_sharing_context_properties()
|
|
143
|
+
candidates, selector = self._gl_sharing_candidate_devices()
|
|
118
144
|
last_error = None
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
|
|
146
|
+
for device in candidates:
|
|
147
|
+
platform = device.platform
|
|
148
|
+
if "cl_khr_gl_sharing" not in device.extensions.split():
|
|
149
|
+
if selector is not None:
|
|
150
|
+
raise RuntimeError(
|
|
151
|
+
"PYOPENCL_CTX=%s selected %s, which does not advertise "
|
|
152
|
+
"cl_khr_gl_sharing"
|
|
153
|
+
% (selector, device.name.strip())
|
|
154
|
+
)
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
properties = [
|
|
158
|
+
(cl.context_properties.PLATFORM, platform),
|
|
159
|
+
*sharing,
|
|
160
|
+
]
|
|
161
|
+
try:
|
|
162
|
+
context = cl.Context(devices=[device], properties=properties)
|
|
163
|
+
except Exception as exc:
|
|
164
|
+
last_error = exc
|
|
165
|
+
if selector is not None:
|
|
166
|
+
raise RuntimeError(
|
|
167
|
+
"PYOPENCL_CTX=%s selected %s, but that device could not "
|
|
168
|
+
"share the active OpenGL context: %s"
|
|
169
|
+
% (selector, device.name.strip(), exc)
|
|
170
|
+
) from exc
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
self.__platform = platform
|
|
174
|
+
self.__device = device
|
|
175
|
+
return context
|
|
137
176
|
|
|
138
177
|
if last_error is not None:
|
|
139
178
|
raise RuntimeError("No CL/GL sharing device accepted the active GL context") from last_error
|
|
@@ -22,7 +22,9 @@ import zlib
|
|
|
22
22
|
v_major = 0
|
|
23
23
|
v_minor = 4
|
|
24
24
|
v_revision = 0
|
|
25
|
-
v_prerelease = "
|
|
25
|
+
v_prerelease = "rc2"
|
|
26
|
+
|
|
27
|
+
_GL_INTEROP_WARNING_EMITTED = False
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
def py_particle_version(r="s"):
|
|
@@ -37,6 +39,35 @@ def py_particle_version(r="s"):
|
|
|
37
39
|
return (v_major, v_minor, v_revision)
|
|
38
40
|
|
|
39
41
|
|
|
42
|
+
def _warn_if_pyopencl_lacks_gl(cl):
|
|
43
|
+
"""Emit a one-time explanation when only compute OpenCL is available."""
|
|
44
|
+
global _GL_INTEROP_WARNING_EMITTED
|
|
45
|
+
|
|
46
|
+
if _GL_INTEROP_WARNING_EMITTED:
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
have_gl = getattr(cl, "have_gl", None)
|
|
50
|
+
if have_gl is None:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
gl_enabled = bool(have_gl())
|
|
55
|
+
except Exception:
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
if gl_enabled:
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
_GL_INTEROP_WARNING_EMITTED = True
|
|
62
|
+
print("")
|
|
63
|
+
print("WARNING: PyOpenCL was built without OpenGL interoperability (have_gl=False).")
|
|
64
|
+
print("OpenCL compute remains available, but CL/GL rendering will use host")
|
|
65
|
+
print("synchronization and can be much slower for large particle counts.")
|
|
66
|
+
print("For CL/GL interoperability, rebuild PyOpenCL from source with")
|
|
67
|
+
print("PYOPENCL_ENABLE_GL=ON and verify that pyopencl.have_gl() is True.")
|
|
68
|
+
print("")
|
|
69
|
+
|
|
70
|
+
|
|
40
71
|
def test_pyopencl():
|
|
41
72
|
"""Return True only when PyOpenCL has at least one usable device."""
|
|
42
73
|
try:
|
|
@@ -45,12 +76,16 @@ def test_pyopencl():
|
|
|
45
76
|
return False
|
|
46
77
|
|
|
47
78
|
try:
|
|
48
|
-
|
|
79
|
+
usable = any(platform.get_devices() for platform in cl.get_platforms())
|
|
49
80
|
except Exception:
|
|
50
81
|
# Broken/missing ICDs may allow importing pyopencl while still making
|
|
51
82
|
# every OpenCL operation unusable.
|
|
52
83
|
return False
|
|
53
84
|
|
|
85
|
+
if usable:
|
|
86
|
+
_warn_if_pyopencl_lacks_gl(cl)
|
|
87
|
+
return usable
|
|
88
|
+
|
|
54
89
|
|
|
55
90
|
def about():
|
|
56
91
|
mail = zlib.decompress(
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "PyParticles3"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.0rc2"
|
|
8
8
|
description = "Modern educational particle simulation toolbox with OpenCL/OpenGL acceleration"
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.11"
|