# r25 engineering workers The same engineering backend is used by standalone jobs and the hosted research workflow. Only the packaged Modelica Dahlquist FMU and the two packaged MATLAB clock functions are accepted. Uploading a native FMU, MATLAB function, Simulink model, executable path, or license configuration in a study is not supported. ## Hosted native FMU Build `Dockerfile.research` and use it as the approved research/FMU worker image. The model remains `Dahlquist_v0_0_41.fmu`, SHA-256 `cecf1fb0f04cbb9de102c783dd7d905a17aec0c6e8ce4641f54a0b26673c2c7f`. The adapter verifies this checksum before extraction or native-library loading. FMPy now extracts the approved model into a unique private temporary directory inside the job output directory and deletes that directory after execution. This avoids FMPy's implicit use of `/tmp`, which is deliberately mounted `noexec` by the isolated Docker worker. The hosted `/work` volume must support loading native shared libraries. An administrator may override the extraction parent with `PF_FMU_TEMP_DIR`, an absolute existing writable directory on an executable-capable filesystem; the application does not accept this setting from submitted configurations. Do not make a global shared writable execution directory. The default job-local location needs no override. The actual native model runs twice using CVode relative tolerances `1e-10` and `1e-12`. Both trajectories are checked against `x(t) = x0 exp(-k t)` and each other. The output interval is a sampling request, not CVode's adaptive time step. Both errors and the tolerance-refinement discrepancy are included in the CSV and report. Missing platform binaries or native loading/extraction failure produce an unavailable result, with no passing numerical checks. This validates FMI interoperability and this specific decay equation. It does not validate a spacecraft, oscillator, instrument, or experimental dataset. The upstream reference license remains in `pf_integrations/models/reference_fmus`. ## Licensed MATLAB/Simulink worker The implemented deployment route is **MATLAB Engine in a dedicated licensed worker**. It is not a MATLAB Runtime or compiled-component deployment. The free MATLAB Runtime cannot execute these Engine calls. Prepare a private Linux base image with: - An installed MATLAB release and the operating-system dependencies required by that release, plus Simulink for the Simulink preset. - 64-bit Python 3.12 with `venv`, `pip`, and the standard Linux account-management commands. MathWorks lists Python 3.12 support for R2024b, R2025a, R2025b and R2026a; confirm the selected release in the linked compatibility table. - A deployment-appropriate license configuration. The PF package neither supplies proprietary products nor determines whether a license covers a particular hosted service. Build the PF layer from the release directory, substituting the administrator's actual private base image and MATLAB location: ```sh docker build -f Dockerfile.matlab-worker \ --build-arg MATLAB_BASE_IMAGE=registry.example/pf-matlab-base:approved \ --build-arg PF_MATLAB_ROOT=/opt/matlab/R2025b \ --build-arg PF_WORKER_PYTHON=/usr/bin/python3 \ -t pf-matlab-worker:local . ``` The recipe installs MATLAB Engine from that installation's `extern/engines/python` directory into `/opt/pf-worker`. It deliberately avoids installing an unpinned latest `matlabengine` package that might target another MATLAB release. The resulting worker uses UID/GID 10001. Its fixed command is: ```sh python -u -m pf_saas.workload --execute /work/execution.json ``` Set the operator-only `matlab` entry in `PF_SAAS_RESEARCH_PROFILES_FILE` to that image, with an explicit profile revision. Configure the permitted license server environment privately in the profile or deployment secret configuration. Do not put license credentials in a Docker build argument or study JSON. See the r25 hosted deployment guide for the complete profile schema and AWS option. The Docker profile must use the service's isolated Docker execution backend. `PF_MATLAB_ROOT` is an optional administrator setting. It must name an absolute installation directory with a `bin/matlab` executable (`matlab.exe` on Windows). The adapter adds this directory to the worker's executable search path, verifies that `matlabroot` reported by the actual Engine matches it, then restores the Python process's search path afterward. The matching Engine package remains necessary; changing PATH is not a substitute for installing it. MATLAB is started headlessly, then the fixed model functions execute in a private writable job directory; only the packaged function directory is added to MATLAB's path. This avoids generating Simulink output in the read-only application tree. The worker uses `/work/tmp` for temporary files. An operator must confirm the selected licensed base can start under UID 10001 with a read-only root, writable job storage, its required preferences/cache locations, and the permitted license-server network. This image/OS-specific acceptance check requires the licensed installation and has not been executed here. The adapter reports an unavailable result if Engine import/startup, installation matching, or license checkout fails. Error classification does not copy license server names, credentials, or Engine output into the result. Numerical/model errors still fail the job; they are not converted into successful execution or hidden as missing licenses. The Engine is closed after both success and failure. ## Deployment acceptance and evidence On a licensed worker, execute both shipped presets and retain their reports: ```sh python run_research_integrations.py --config config_r24_matlab_clock.json --output validation_local_matlab_clock python run_research_integrations.py --config config_r24_matlab_simulink.json --output validation_local_matlab_simulink ``` Run the same two presets through the hosted workbench. Require actual Engine version metadata, finite clock trajectories, passing analytic comparisons, valid evidence manifests, and matching standalone/hosted values within the reported tolerances before claiming validated MATLAB/Simulink execution. An unavailable result or configured profile alone is not evidence of execution. For the native FMU, run `config_r24_fmu_dahlquist.json` through both routes and compare the actual decay output and both tolerance-run checks. `test_r25_engineering.py` exercises actual native FMPy execution and private extraction. Its MATLAB test doubles cover deployment failures, installation selection, cleanup, and secret suppression only. They are **not MATLAB physics validation**. Actual MATLAB, Simulink, licensed-image build, and cloud execution remain dependent on the operator's products and infrastructure. Official references checked 2026-09-20: - [MATLAB Engine installation and release matching](https://www.mathworks.com/help/matlab/matlab_external/install-the-matlab-engine-for-python.html) - [MathWorks Python compatibility by release](https://www.mathworks.com/support/requirements/python-compatibility.html) - [MATLAB Linux startup options](https://www.mathworks.com/help/matlab/ref/matlablinux.html) - [MATLAB settings directories](https://www.mathworks.com/help/matlab/matlab_env/where-matlab-stores-settings.html) - [FMPy native simulation tutorial](https://fmpy.readthedocs.io/en/latest/tutorial/)