Ruby wrapper for Siesta DFT calculations, with an async REST API backed by PostgreSQL.
The API + database run on a cloud server; the Siesta worker runs on a separate compute server (HPC cluster or login node). See DEPLOY.md for production setup.
Prerequisite — PostgreSQL user & database
sudo -u postgres psql <<EOF
CREATE USER myuser WITH PASSWORD 'mypassword';
CREATE DATABASE ruby_siesta OWNER myuser;
GRANT ALL PRIVILEGES ON DATABASE ruby_siesta TO myuser;
EOF
export DATABASE_URL="postgres://myuser:mypassword@localhost:5432/ruby_siesta"# Install dependencies
cd /path/to/ruby_siesta
bundle install
# Configure pseudopotentials
export SIESTA_PP_PATH=/path/to/siesta_pseudo
# Start Redis (required by Sidekiq)
redis-server &
# Start the API server
bundle exec puma config.ru -p 4567 -b tcp://0.0.0.0 &
# Start the Sidekiq worker (in another terminal)
bundle exec sidekiq -C config/sidekiq.yml -r ./config/database.rbThen call it from anywhere:
# Check status
curl http://localhost:4567/api/v1/status
# Submit a calculation (returns immediately with a job ID)
curl -X POST http://localhost:4567/api/v1/calculate \
-H 'Content-Type: application/json' \
-d "$(jq -n --arg s "$(cat input.STRUCT_OUT)" \
'{structure: $s, format: "STRUCT_OUT", label: "silicon", xc: "PBE", kpoints: [9,9,9]}')"
# Poll for results (replace :id with the returned job_id)
curl http://localhost:4567/api/v1/jobs/1
# Monitor Sidekiq queue in browser
open http://localhost:4567/sidekiqOr use the included example script:
ruby examples/api_client.rb input.STRUCT_OUT| Method | Path | Description |
|---|---|---|
GET |
/api/v1/status |
Siesta version, MPI, environment |
POST |
/api/v1/calculate |
Submit a calculation → returns job_id (202) |
GET |
/api/v1/jobs/:id |
Poll calculation status and results |
POST |
/api/v1/input |
Dry-run: generate FDF without running |
POST |
/api/v1/structure |
Parse structure file → coordinates + cell |
GET |
/sidekiq |
Sidekiq Web UI (monitoring) |
Only structure (file content string) is required. Everything else is optional:
| Parameter | Example | Notes |
|---|---|---|
format |
"STRUCT_OUT", "vasp", "xyz" |
Auto-detected from filename |
label |
"my_run" |
Default: siesta_api |
xc |
"PBE", "PW92", "LDA", "BLYP" |
Default: PBE |
kpoints |
[9, 9, 9] |
Monkhorst-Pack mesh |
spin |
{"polarized": true} |
Also: soc, non_colinear, fix |
hubbard_u |
{"atom": "Fe", "orbital": "3d", "value": 4.0} |
DFT+U |
parameters |
{"meshcutoff": "400 Ry", "basis": "TZP"} |
Override any FDF parameter |
vdw |
true |
DFT-D2 correction |
electric_field |
{"x": 0.5} |
V/Ang |
require 'siesta'
siesta = Siesta.import_from_file('input.STRUCT_OUT')
siesta.label('silicon')
siesta.xc('PBE')
siesta.kpoint(kmesh: [9, 9, 9])
energy = siesta.energy- Ruby >= 2.6.8
- PostgreSQL >= 12
- Redis >= 6
- Siesta >= 4.1.5 (compute server only)