Containerization WIP

This commit is contained in:
jaseg 2024-02-08 18:21:15 +01:00
parent 0ee3a1844b
commit 57cb1e3dd7
4 changed files with 414 additions and 329 deletions

9
Containerfile Normal file
View file

@ -0,0 +1,9 @@
FROM ubuntu:22.04
RUN apt update && apt install -y software-properties-common
RUN add-apt-repository ppa:elmer-csc-ubuntu/elmer-csc-ppa && apt update && apt install -y elmerfem-csc
RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y python3-scipy python3-tqdm python3-click python3-tabulate python3-gmsh python3-matplotlib python3-subprocess-tee python3-pip python3-numpy python3-pandas
#RUN pip install --break-system-packages pyelmer
RUN pip install pyelmer
COPY *.py *.yml /nice-coils/
WORKDIR /nice-coils
VOLUME /mesh

4
build_container_tarball.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
podman build -f Containerfile --label nice-coils-make --tag nice-coils-runner --iidfile nice-coils-runner.cid --cache-ttl 1h
podman save --format oci-archive -o nice-coils-runner.tar.gz $(cat nice-coils-runner.cid)

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,14 @@
#!/usr/bin/env python3
import threading
import datetime
import queue
import itertools
import pathlib
import tempfile
import secrets
import sys
import uuid
import sqlite3
import time
import math
@ -17,9 +20,10 @@ import click
from tabulate import tabulate
def mesh_args(db, coil_id, mesh_type, mesh_file, outfile):
def mesh_args(db, coil_id, mesh_type, mesh_file, outfile, **kwargs):
mesh_type = {'split': '--mesh-split-out', 'normal': '--mesh-out', 'mutual': '--mesh-mutual-out'}[mesh_type]
rows = db.execute('SELECT key, value FROM results WHERE coil_id=?', (coil_id,)).fetchall()
rows = dict(db.execute('SELECT key, value FROM results WHERE coil_id=?', (coil_id,)).fetchall())
rows.update(kwargs)
args = ['python', '-m', 'twisted_coil_gen_twolayer', mesh_type, mesh_file, '--pcb']
for k, v in rows:
prefix, _, k = k.partition('.')
@ -169,7 +173,8 @@ def run(ctx, run_id, log_dir, mesh_dir):
if run_id is None:
run_id, = ctx.obj['db_connect']().execute('SELECT run_id FROM runs ORDER BY timestamp DESC LIMIT 1').fetchone()
ctx.obj['run_id'] = run_id
ctx.obj['log_dir'] = pathlib.Path(log_dir)
log_dir = ctx.obj['log_dir'] = pathlib.Path(log_dir)
log_dir.mkdir(exist_ok=True)
ctx.obj['mesh_dir'] = pathlib.Path(mesh_dir)
@ -260,6 +265,73 @@ def self_inductance(ctx, num_jobs):
threads.append(t)
q.join()
@run.command()
@click.option('target_hosts', type=click.Path(exists=True, dir_okay=False, path_type=pathlib.Path), help='File with one SSH target host name per line')
@click.option('job_file', type=click.Path(exists=True, dir_okay=False, path_type=pathlib.Path), help='JSON job description file')
@click.pass_context
def run_mutual_inductance(ctx, target_hosts, job_file):
db = ctx.obj['db_connect']()
target_hosts = [l.strip() for l in target_hosts.read_text().splitlines()]
log_dir.mkdir(exist_ok=True)
jobs = json.loads(job_file.read_text())
q = queue.Queue()
def queue_worker(host):
try:
while True:
case_name, case_id, kwargs = q.get_nowait()
workdir = pathlib.Path('/mesh') / f'{case_name}-{case_id}' # container path
mesh_file = wordir / 'mesh.msh' # container path
host_log = lambda log_name: ctx.obj['log_dir'] / f'{case_name}-{log_name}-{case_id}.log'
mesh_log = host_log('mesh') # host path
sim_log = host_log('sim') # host path
try:
args = mesh_args(db, coil_id, 'mutual', mesh_file, str(workdir / 'tmp_pcb.kicad_pcb'), **kwargs)
res = subprocess.run(['ssh', host, 'podman', 'run', '-v', './mesh:/mesh:rw', 'nice-coils-runner', *args], check=True, capture_output=True, text=True)
mesh_log.write_text(res.stdout + res.stderr)
try:
tqdm.tqdm.write(f'Processing {mesh_file} on {host}')
res = subprocess.run(['ssh', host, 'podman', 'run', '-v', './mesh:/mesh:rw', 'nice-coils-runner', 'python', '-m', 'coil_parasitics', 'mutual-inductance', '--sim-dir', workdir, mesh_file], check=True, capture_output=True, text=True)
sim_log.write_text(res.stdout + res.stderr)
try:
for fn in ['ElmerGrid_stdout.log',
'ElmerGrid_stderr.log',
'ElmerSolver_stdout.log',
'ElmerSolver_stderr.log']:
subprocess.run(['scp', f'{host}:mesh/{workdir.name}/{fn}', str(host_log(Path(fn).stem))], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
print(f'Error copying simulation logs, rc={e.returncode}', file=sys.stderr)
sim_log.write_text(e.stdout + e.stderr)
except subprocess.CalledProcessError as e:
print(f'Error running simulation, rc={e.returncode}', file=sys.stderr)
sim_log.write_text(e.stdout + e.stderr)
except subprocess.CalledProcessError as e:
print('Mesh generation failed with exit code {e.returncode}', file=sys.stderr)
mesh_log.write_text(e.stdout + e.stderr)
tq.update(1)
q.task_done()
except queue.Empty:
pass
run_id = f'{datetime.datetime.now():%Y%m%d-%H%M%S}-{secrets.token_urlsafe(6)}'
for i, (job_name, kwargs) in jobs.items():
case_id = f'{run_id}-{i}'
q.put((job_name, case_id, kwargs))
tq = tqdm.tqdm(total=num_meshes-num_completed)
threads = []
for host in target_hosts:
t = threading.Thread(target=lambda: queue_worker(host), daemon=True)
t.start()
threads.append(t)
q.join()
@run.command()
@click.pass_context
def self_capacitance(ctx):