diff --git a/CHANGELOG.md b/CHANGELOG.md index 854a7df..832b385 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht images and JupyterHub profiles can omit it (default off); instructors enable cluster testing with `QUANTUI_ENABLE_SLURM=1` without any extra student command. +- **CPU teaching SIF defaults** — `quantui.def` sets `QUANTUI_FREQ_PARALLEL=1` + so NCShare classroom sessions parallelize IR-intensity displacements on + multi-core nodes. The Settings checkbox reflects the deployment value and is + locked while the variable is set; use `QUANTUI_FREQ_PARALLEL=0` to force off + site-wide. ### Fixed diff --git a/apptainer/README.md b/apptainer/README.md index 276941b..1a98809 100644 --- a/apptainer/README.md +++ b/apptainer/README.md @@ -35,6 +35,13 @@ every layer (CUDA base image, all-pip install, a pinned PyPI release rather than the working tree). Merging them would ship a multi-GB CUDA stack to students who will never have a GPU. See [GPU image](#gpu-image) below. +**CPU image environment defaults** (set in `quantui.def` `%environment`): + +| Variable | CPU `quantui.sif` | GPU `quantui-gpu.sif` | +| --- | --- | --- | +| `QUANTUI_FREQ_PARALLEL` | `1` — parallel CPU workers for IR-intensity displacements on frequency calcs (≥4 cores, ≥2 atoms). Overrides the Settings checkbox while set. | unset (off unless you set it) | +| `QUANTUI_ENABLE_SLURM` | unset (class stays in-kernel) | unset | + The compiled `.sif` image is **not** committed to git — it is too large (~4–5 GB). Build it locally (see below) or download the latest release asset from the [GitHub Releases page](https://github.com/The-Schultz-Lab/QuantUI/releases). diff --git a/apptainer/quantui.def b/apptainer/quantui.def index cffa3be..17f7339 100644 --- a/apptainer/quantui.def +++ b/apptainer/quantui.def @@ -49,6 +49,12 @@ FROM: condaforge/miniforge3:26.1.1-3 # across kernel restarts. The home dir is bind-mounted by Apptainer. export QUANTUI_RESULTS_DIR="${HOME}/.quantui/results" + # Parallel CPU workers for IR-intensity finite-difference SCFs (6N displacements) + # on multi-core hosts. Reference SCF + Hessian stay in-kernel. Students can still + # see the preference in Settings; when this variable is set it overrides the + # saved checkbox (set QUANTUI_FREQ_PARALLEL=0 to force off site-wide). + export QUANTUI_FREQ_PARALLEL=1 + %files # Source paths are relative to where you run `apptainer build` (repo root). # Run the build command from the repo root, not from apptainer/. diff --git a/quantui/app.py b/quantui/app.py index 0c03e0f..008f56c 100644 --- a/quantui/app.py +++ b/quantui/app.py @@ -574,6 +574,10 @@ SUPPORTED_BASIS_SETS, SUPPORTED_METHODS, ) +from quantui.freq_ir_workers import ( + freq_parallel_env_configured, + freq_parallel_opt_in, +) from quantui.help_content import HELP_TOPICS from quantui.molecule import Molecule, parse_xyz_input from quantui.progress import StepProgress @@ -1964,7 +1968,12 @@ def _build_status_panel(self) -> None: vib_framerate_fps=self._user_settings.viz.vib_framerate_fps, gpu_enabled=self._user_settings.compute.gpu_enabled, density_fit_enabled=self._user_settings.compute.density_fit, - freq_parallel_enabled=self._user_settings.compute.freq_parallel, + freq_parallel_enabled=( + freq_parallel_opt_in() + if freq_parallel_env_configured() + else self._user_settings.compute.freq_parallel + ), + freq_parallel_env_locked=freq_parallel_env_configured(), execution_backend=self._user_settings.compute.execution_backend, slurm_available=is_slurm_available(), ) @@ -3748,10 +3757,12 @@ def _on_density_fit_enabled_changed(self, change) -> None: def _on_freq_parallel_enabled_changed(self, change) -> None: """Persist the parallel IR finite-difference preference. - The freq_calc driver reads this via :func:`freq_ir_workers._freq_parallel_opt_in` + The freq_calc driver reads this via :func:`freq_ir_workers.freq_parallel_opt_in` on each run (unless ``QUANTUI_FREQ_PARALLEL`` overrides in the environment). Refresh the time estimate because parallel divides the IR term in the model. """ + if freq_parallel_env_configured(): + return new_val = bool(change["new"]) if new_val == self._user_settings.compute.freq_parallel: return diff --git a/quantui/app_builders.py b/quantui/app_builders.py index f66fdb5..31876f1 100644 --- a/quantui/app_builders.py +++ b/quantui/app_builders.py @@ -123,6 +123,7 @@ def build_status_panel( gpu_enabled: bool = True, density_fit_enabled: bool = False, freq_parallel_enabled: bool = False, + freq_parallel_env_locked: bool = False, execution_backend: str = "local", slurm_available: bool = False, ) -> None: @@ -327,8 +328,17 @@ def _render_status(gpu_state: Any) -> str: value=freq_parallel_enabled, description="Parallelize IR intensity displacements (CPU)", indent=False, + disabled=freq_parallel_env_locked, layout=layout_fn(width="320px", margin="2px 0 0 0"), ) + if freq_parallel_env_locked: + fp_env_note = widgets.HTML( + f'
QUANTUI_FREQ_PARALLEL in the "
+ "container or session environment).