Linux Execution of HEC-RAS with ras-commander¶
This notebook demonstrates how to execute HEC-RAS simulations on Linux servers
using RasCmdr.compute_plan_linux(). This enables scalable, headless execution
on cloud VMs, Proxmox containers, Docker, or any Linux host with the HEC-RAS
Linux binaries installed.
Two-Phase Workflow¶
Linux HEC-RAS execution is a two-phase process:
| Phase | Platform | What Happens |
|---|---|---|
| Phase 1: Preprocessing | Windows | Run RasPreprocess.preprocess_plan() to generate .tmp.hdf, .b##, .x## files |
| Phase 2: Execution | Linux | Run RasUnsteady binary with preprocessed files |
Why two phases? The Linux HEC-RAS binaries (RasUnsteady, RasSteady,
RasGeomPreprocess) are Fortran executables that run the compute engine only.
They cannot do the full preprocessing or GUI operations needed to produce
.tmp.hdf and .b## files. The Windows HEC-RAS application must preprocess
the model first. Use RasPreprocess.preprocess_plan() to automate this step.
What You'll Learn¶
- Setting up HEC-RAS Linux binaries on a server
- Preprocessing a model on Windows using
RasPreprocess.preprocess_plan() - Transferring files and running on Linux via SSH
- macOS development workflow (for ras-agent users)
- Verifying results match Windows execution
Prerequisites¶
1. Linux Server with SSH Access¶
You need a Linux machine accessible via SSH. Supported platforms: - Ubuntu 20.04+ / Debian 11+ - RHEL 8+ / Rocky Linux 8+ / AlmaLinux 8+ - Proxmox LXC containers - Docker containers - AWS EC2 / Azure VM / GCP instances
Minimum requirements: 4 GB RAM, 2 CPU cores, 10 GB disk space.
2. SSH Key-Based Authentication (Recommended)¶
Set up passwordless SSH for automation:
# On your local machine (Windows PowerShell or macOS Terminal)
ssh-keygen -t ed25519 -C "ras-commander" # Accept defaults
ssh-copy-id user@your-linux-server # Copy public key
# Verify passwordless login
ssh user@your-linux-server "echo Connected"
3. HEC-RAS Linux Binaries¶
HEC-RAS Linux binaries are bundled with HEC-RAS 6.5+ Windows installers. They can also be downloaded from the USACE HEC-RAS website.
4. Python Environment¶
Step 1: Install HEC-RAS Linux Binaries on the Server¶
Option A: Copy from Windows Installation (Recommended)¶
HEC-RAS 6.5+ includes Linux binaries in the Windows installation directory:
C:\Program Files (x86)\HEC\HEC-RAS\6.6\Linux\
RasGeomPreprocess # Geometry preprocessor
RasSteady # Steady flow solver
RasUnsteady # Unsteady flow solver
run_helper.sh # Official run script
libs/ # Shared libraries
libifcore.so.5
libimf.so
libiomp5.so
...
mkl/ # Math Kernel Library
rhel_8/ # RHEL 8 specific libs
Copy to the Linux server:
# From Windows (Git Bash or PowerShell with OpenSSH)
scp -r "C:/Program Files (x86)/HEC/HEC-RAS/6.6/Linux/"* \
user@server:/opt/hecras/6.6/
# On the server: set executable permissions
ssh user@server "chmod +x /opt/hecras/6.6/RasUnsteady \
/opt/hecras/6.6/RasSteady /opt/hecras/6.6/RasGeomPreprocess"
Option B: Extract from HEC-RAS Installer¶
For versions that bundle Linux binaries in the .exe installer but don't
have a separate Linux/ folder, install HEC-RAS on a Windows machine first,
then copy the Linux/ directory.
Directory Layout on Server¶
Recommended layout supporting multiple versions:
/opt/hecras/
6.5/
RasUnsteady
RasSteady
RasGeomPreprocess
run_helper.sh
libs/
mkl/
6.6/
RasUnsteady
...
libs/
mkl/
rhel_8/
6.7-beta5/
...
Verify Installation¶
ssh user@server "export LD_LIBRARY_PATH=/opt/hecras/6.6/libs:/opt/hecras/6.6/libs/mkl:/opt/hecras/6.6/libs/rhel_8 && /opt/hecras/6.6/RasUnsteady --version 2>&1 || echo 'Binary runs (no --version flag, expected)'"
If the binary runs without "not found" errors, the libraries are correctly configured. The solver will fail with a usage error since no input was given — that's expected.
Step 2: Preprocess the Model on Windows (Phase 1)¶
The Linux solver needs preprocessed files that only the Windows HEC-RAS application can generate. There are two approaches:
Approach A: RasPreprocess (Recommended)¶
The RasPreprocess.preprocess_plan() method automates preprocessing by:
- Enabling detailed logging (
Write Detailed= 1) in the plan file - Starting HEC-RAS and monitoring the
.bcolog file - Detecting "Starting Unsteady Flow Computations" signal
- Killing HEC-RAS at that exact moment (preprocessing complete)
- Verifying
.tmp.hdf,.b##,.x##files were generated
from ras_commander import RasPreprocess, init_ras_project
init_ras_project("C:/Projects/MyModel", "6.6")
result = RasPreprocess.preprocess_plan("01")
if result:
print(f"Preprocessing complete in {result.elapsed_seconds:.1f}s")
print(f" tmp.hdf: {result.tmp_hdf_path}")
print(f" .b file: {result.b_file_path}")
print(f" .x file: {result.x_file_path}")
else:
print(f"Preprocessing failed: {result.error}")
You can also check if preprocessing has already been done:
if RasPreprocess.verify_preprocessing("01"):
print("Ready for Linux execution")
else:
RasPreprocess.preprocess_plan("01")
Approach B: Manual Preprocessing¶
- Open the project in HEC-RAS GUI on Windows
- Run the plan (let it start computing)
- Once you see "Starting Unsteady Flow Computations" in the compute window, close HEC-RAS
- The
.tmp.hdffile in the project folder contains all preprocessed data
Required Output Files¶
After preprocessing, your project folder should contain:
| File | Description | Generated By |
|---|---|---|
Project.p01.tmp.hdf |
Preprocessed plan HDF (geometry + setup) | HEC-RAS preprocessing |
Project.b01 |
Boundary conditions (Fortran format) | HEC-RAS preprocessing |
Project.x01 |
Cross-section preprocessor data | HEC-RAS preprocessing |
Project.g01.hdf |
Geometry HDF | Existing (from project) |
Project.p01 |
Plan file | Existing (from project) |
Step 3: Transfer Files to Linux Server¶
import platform
import sys
from pathlib import Path
import subprocess
# IS_LINUX: flag used by all subsequent cells to guard Linux-only operations.
# When False every cell prints a skip message and exits cleanly.
IS_LINUX = sys.platform.startswith("linux")
if IS_LINUX:
print("Running on Linux — notebook is active.")
else:
print(
"NOTE: This notebook targets Linux/WSL. "
"All execution cells will be skipped on this platform "
f"({sys.platform}). The code is shown for reference only."
)
# Imports that are safe on any platform
try:
from ras_commander import init_ras_project, RasCmdr, RasUtils, RasPreprocess
except ImportError:
sys.path.append(str(Path(".").resolve().parent))
from ras_commander import init_ras_project, RasCmdr, RasUtils, RasPreprocess
import os
# ── Configuration ────────────────────────────────────────────
# Edit these values for your environment
if IS_LINUX:
# Linux server connection
LINUX_HOST = "192.168.3.2" # Your Linux server IP or hostname
LINUX_USER = "root" # SSH username
LINUX_RAS_DIR = "/opt/hecras/6.7-beta5" # HEC-RAS binary directory on server
# Local Windows project (already preprocessed with Phase 1)
LOCAL_RESULTS_DIR = os.environ.get("RAS_LINUX_RESULTS_DIR", "")
LOCAL_PROJECT = Path(LOCAL_RESULTS_DIR) if LOCAL_RESULTS_DIR else Path("/tmp/MyModel") # Your project folder
PLAN_NUMBER = "01" # Plan to execute
# Remote working directory
REMOTE_PROJECT_DIR = "/tmp/ras_linux_run"
else:
print("(skipped — not on Linux; config values not set)")
# ── Verify prerequisite files exist locally ─────────────────────────────────────
if IS_LINUX:
project_name = list(LOCAL_PROJECT.glob("*.prj"))[0].stem
plan_num = PLAN_NUMBER.zfill(2)
# Read geometry number from plan file
import re
plan_file = LOCAL_PROJECT / f"{project_name}.p{plan_num}"
geom_num = "01"
for line in plan_file.read_text(errors='replace').splitlines():
if line.startswith("Geom File="):
m = re.search(r'(\d+)', line.split('=', 1)[1])
if m:
geom_num = m.group(1)
break
required_files = {
'tmp_hdf': LOCAL_PROJECT / f"{project_name}.p{plan_num}.tmp.hdf",
'boundary': LOCAL_PROJECT / f"{project_name}.b{plan_num}",
'xsec': LOCAL_PROJECT / f"{project_name}.x{geom_num}",
'plan': plan_file,
'geom_hdf': LOCAL_PROJECT / f"{project_name}.g{geom_num}.hdf",
}
print(f"Project: {project_name}")
print(f"Plan: p{plan_num}, Geometry: g{geom_num}")
print()
all_ok = True
for name, path in required_files.items():
exists = path.exists()
size = f"{path.stat().st_size / 1e6:.1f} MB" if exists else "MISSING"
status = "OK" if exists else "MISSING"
print(f" [{status}] {path.name} ({size})")
if not exists:
all_ok = False
if not all_ok:
print("\nRun Phase 1 preprocessing on Windows first!")
else:
print("\nAll prerequisite files present. Ready for Linux transfer.")
else:
print("(skipped — not on Linux)")
# ── Transfer project to Linux server ───────────────────────────────────────────────
# Uses scp for simplicity. For large projects, consider rsync.
if IS_LINUX:
def run_ssh(cmd, check=True):
"""Run a command on the Linux server via SSH."""
result = subprocess.run(
["ssh", f"{LINUX_USER}@{LINUX_HOST}", cmd],
capture_output=True, text=True, timeout=60
)
if check and result.returncode != 0:
print(f"SSH error: {result.stderr}")
return result
# Create remote directory
run_ssh(f"mkdir -p {REMOTE_PROJECT_DIR}")
# Copy project files
print(f"Transferring project to {LINUX_USER}@{LINUX_HOST}:{REMOTE_PROJECT_DIR}")
scp_result = subprocess.run(
["scp", "-r", str(LOCAL_PROJECT) + "/.",
f"{LINUX_USER}@{LINUX_HOST}:{REMOTE_PROJECT_DIR}/"],
capture_output=True, text=True, timeout=600
)
if scp_result.returncode == 0:
print("Transfer complete.")
# Verify files arrived
result = run_ssh(f"ls -la {REMOTE_PROJECT_DIR}/*.tmp.hdf {REMOTE_PROJECT_DIR}/*.b* {REMOTE_PROJECT_DIR}/*.x*")
print(result.stdout)
else:
print(f"Transfer failed: {scp_result.stderr}")
else:
print("(skipped — not on Linux)")
Step 4: Execute on Linux (Phase 2)¶
# ── Execute RasUnsteady on the Linux server ─────────────────────────────────────────
# This runs the official run_helper.sh or invokes RasUnsteady directly.
if IS_LINUX:
# Option A: Using run_helper.sh (simplest)
cmd = (
f"cd {REMOTE_PROJECT_DIR} && "
f"{LINUX_RAS_DIR}/run_helper.sh RasUnsteady "
f"{project_name}.p{plan_num}.tmp.hdf x{geom_num}"
)
print(f"Running: {cmd}")
print("This may take several minutes...")
print()
result = subprocess.run(
["ssh", f"{LINUX_USER}@{LINUX_HOST}", cmd],
capture_output=True, text=True,
timeout=14400 # 4-hour timeout
)
# Print output
if result.stdout:
# Filter out FONT= lines (Fortran console formatting)
for line in result.stdout.splitlines():
if not line.startswith("FONT="):
print(line)
if result.returncode == 0:
print("\nExecution completed successfully.")
else:
print(f"\nExecution failed (exit code {result.returncode})")
if result.stderr:
print(result.stderr[-500:])
else:
print("(skipped — not on Linux)")
# ── Option B: Using compute_plan_linux() (programmatic, with ras-commander on Linux)
# This requires ras-commander installed on the Linux server.
#
# ssh user@server "pip install ras-commander"
#
# Then from a Python script on the server:
#
# from ras_commander import init_ras_project, RasCmdr
# init_ras_project("/tmp/ras_linux_run")
# result = RasCmdr.compute_plan_linux(
# "01",
# ras_exe_dir="/opt/hecras/6.6",
# timeout_sec=7200
# )
# print(f"Success: {result.success}")
Step 5: Retrieve Results¶
# ── Copy results back from Linux server ────────────────────────────────────────────
if IS_LINUX:
local_results = LOCAL_PROJECT / "linux_results"
local_results.mkdir(exist_ok=True)
# Copy the results HDF back
scp_result = subprocess.run(
["scp",
f"{LINUX_USER}@{LINUX_HOST}:{REMOTE_PROJECT_DIR}/{project_name}.p{plan_num}.tmp.hdf",
str(local_results / f"{project_name}.p{plan_num}.hdf")],
capture_output=True, text=True, timeout=600
)
if scp_result.returncode == 0:
hdf_path = local_results / f"{project_name}.p{plan_num}.hdf"
print(f"Results downloaded: {hdf_path}")
print(f"Size: {hdf_path.stat().st_size / 1e6:.1f} MB")
else:
print(f"Download failed: {scp_result.stderr}")
else:
print("(skipped — not on Linux)")
# ── Extract and verify results ─────────────────────────────────────────────────
if IS_LINUX:
from ras_commander.hdf import HdfResultsMesh
import h5py
hdf_path = local_results / f"{project_name}.p{plan_num}.hdf"
# Check HDF structure
with h5py.File(hdf_path, 'r') as hf:
has_results = 'Results' in hf
print(f"Has Results group: {has_results}")
if has_results:
print(f"Top-level groups: {list(hf.keys())}")
results = hf['Results']
print(f"Results subgroups: {list(results.keys())}")
else:
print("(skipped — not on Linux)")
macOS Development Workflow¶
For macOS users (e.g., developing with ras-agent), the workflow is the same conceptually but with macOS-specific SSH tooling:
SSH Setup on macOS¶
# Generate SSH key (if not done)
ssh-keygen -t ed25519 -C "ras-commander"
# Copy to Linux server
ssh-copy-id user@linux-server
# Verify
ssh user@linux-server "uname -a"
File Transfer from macOS¶
# scp works identically on macOS
scp -r ./my_project/ user@server:/tmp/ras_run/
# rsync for large projects (faster for incremental updates)
rsync -avz --progress ./my_project/ user@server:/tmp/ras_run/
macOS Limitations¶
- No Windows preprocessing on macOS: Phase 1 requires Windows HEC-RAS. Options:
- Use a Windows VM (Parallels, UTM, VMware Fusion)
- Use a remote Windows machine via RDP
- Pre-generate
.tmp.hdffiles on a Windows build server - Use Docker with Wine (experimental)
- ras-commander works on macOS for all non-execution operations: project initialization, HDF reading, geometry parsing, results extraction.
- ras-agent pipeline runs entirely on macOS in mock mode for development; real execution requires the Linux server.
Typical macOS + Linux Workflow¶
macOS (development) Windows VM Linux Server
| | |
|-- Edit model files ------->| |
| |-- Preprocess (Phase 1) |
| |-- .tmp.hdf, .b, .x --->|
| | |-- RasUnsteady (Phase 2)
|<-- Results (.hdf) ---------|<-- Results (.hdf) -----|
|-- Analyze with RC | |
HEC-RAS Linux Version Compatibility¶
| Version | Linux Binaries | Library Layout | Notes |
|---|---|---|---|
| 6.3.1 | Separate download | libs/, libs/mkl/ |
Oldest supported |
| 6.4.1 | Separate download | libs/, libs/mkl/ |
|
| 6.5 | Bundled in installer | libs/, libs/mkl/ |
First version bundled with Windows |
| 6.6 | Bundled in installer | libs/, libs/mkl/, libs/rhel_8/ |
Added RHEL 8 libs |
| 6.7 Beta | Bundled in installer | libs/, libs/mkl/, libs/rhel_8/ |
Latest |
compute_plan_linux() auto-detects the library layout by scanning all
subdirectories under libs/ and adding them to LD_LIBRARY_PATH.
Version-Specific Considerations¶
- 6.3.1-6.4.1: May require
centos_7libs instead ofrhel_8on older distributions. - 6.5-6.6: Most widely tested. Recommended for production.
- 6.7 Beta: Newer Fortran I/O conventions. Requires geometry files
preprocessed with the same version — a model preprocessed with
6.5 may not run on 6.7 due to HDF schema changes (e.g.,
IBCTYPdataset).
Rule of thumb: Always preprocess and execute with the same HEC-RAS version.
Fortran I/O Naming Convention¶
The Linux RasUnsteady binary is a Fortran executable that uses hardcoded
unit numbers for file I/O. When invoked with a project-named file
(e.g., Muncie.p04.tmp.hdf), it looks for supporting files with a base
name of io — for example, io.b, io.X, io.g.
compute_plan_linux() handles this automatically by creating temporary
symlinks:
io.b → Muncie.b04 (boundary conditions)
io.X → Muncie.x04 (cross-section preprocessor)
io.x → Muncie.x04 (lowercase variant)
io.g → Muncie.g04 (geometry)
io.p → Muncie.p04 (plan)
io.u → Muncie.u01 (unsteady flow)
...
These symlinks are created before execution and cleaned up afterwards.
If you're running manually (without compute_plan_linux()), you'll need
to create these symlinks yourself or use the official run_helper.sh script.
Troubleshooting¶
"file not found: io.b"¶
The solver can't find the boundary conditions file. Ensure:
- .b## file exists in the project directory
- io.b symlink points to it (or use compute_plan_linux() which creates it)
"IBCTYP doesn't exist" / "TRY SAVING THE GEOMETRY AND RE-RUNNING THE PREPROCESSOR"¶
Version mismatch between preprocessing and execution. The .g##.hdf was
preprocessed with a different HEC-RAS version than the Linux binary.
Solution: Re-preprocess on Windows using the same version as the Linux binary.
"The output must not already exist"¶
The .tmp.hdf file already has a /Results group. Delete it or let
compute_plan_linux() handle it.
"unable to open file" / HDF5 errors¶
Possible causes:
- File permissions (run chmod 644 *.hdf)
- File corruption during transfer (re-copy with scp or rsync -c)
- Wrong HDF5 library version on server
Timeout after 4 hours¶
Large models may need more time. Increase timeout_sec:
CRLF line ending errors¶
If the .b## or .g## files have Windows line endings (CRLF), the Fortran
parser may fail. compute_plan_linux() runs dos2unix automatically.
For manual execution:
Key Takeaways¶
- Two-phase workflow: Preprocess on Windows (Phase 1), execute on Linux (Phase 2)
- Version matching: Always use the same HEC-RAS version for both phases
- Prerequisite files:
.tmp.hdf,.b##,.x##must exist before Linux execution - Fortran I/O: The solver needs
io.*symlinks —compute_plan_linux()handles this - macOS users: Use a Windows VM for Phase 1, SSH to Linux for Phase 2
- Multiple versions: Install each version in
/opt/hecras/{version}/