Appearance
Automation & Remote Execution
This exercise has you automate a small parametric study: generate five solver scripts that vary Young’s modulus, run them in a batch with a bash script, save the outputs, and finally visualize one of the results in ParaView.
Time: 25–40 minutes Deliverables: 6–8 screenshots (listed under “What to submit”)
Step 1 — Prepare a clean study folder
Create a working directory with this structure:
automation_study/
base_solver_template.py
generate_cases.py
run_all.sh
outputs/ # will be filled automaticallyKeep file/folder names lowercase and alphanumeric for portability.
Step 2 — Write the base solver template (with placeholders)
Create base_solver_template.py with placeholders {E_YOUNG} and {OUTDIR}. This minimal linear elasticity model (FEniCS) solves a cantilever-like cube with a tip traction; it writes XDMF results.
python
# base_solver_template.py
from fenics import *
import os
E = {E_YOUNG} # Pa (placeholder)
nu = 0.30 # Poisson's ratio
mu = E/(2.0*(1.0+nu))
lmbda = E*nu/((1.0+nu)*(1.0-2.0*nu))
nx, ny, nz = 20, 6, 6
mesh = BoxMesh(Point(0,0,0), Point(1,0.1,0.1), nx, ny, nz)
V = VectorFunctionSpace(mesh, "Lagrange", 1)
u = TrialFunction(V)
v = TestFunction(V)
def eps(u): return sym(grad(u))
def sigma(u): return 2.0*mu*eps(u) + lmbda*tr(eps(u))*Identity(3)
# Fixed end at x=0
class FixedEnd(SubDomain):
def inside(self, x, on_boundary): return near(x[0], 0.0) and on_boundary
fixed = FixedEnd()
bcs = [DirichletBC(V, Constant((0.0,0.0,0.0)), fixed)]
# Traction (Neumann) at free end x=1
class FreeEnd(SubDomain):
def inside(self, x, on_boundary): return near(x[0], 1.0) and on_boundary
boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
FreeEnd().mark(boundaries, 1)
ds_ = Measure("ds", domain=mesh, subdomain_data=boundaries)
t = Constant((0.0, -1e5, 0.0)) # downward traction
a = inner(sigma(u), eps(v))*dx
L = dot(t, v)*ds_(1)
u_sol = Function(V)
solve(a == L, u_sol, bcs)
# Post-processing
Vmag = FunctionSpace(mesh, "P", 1)
u_mag = project(sqrt(dot(u_sol, u_sol)), Vmag)
outdir = "{OUTDIR}"
os.makedirs(outdir, exist_ok=True)
with XDMFFile(os.path.join(outdir, "u.xdmf")) as xf:
xf.write(u_sol)
with XDMFFile(os.path.join(outdir, "u_mag.xdmf")) as xf:
xf.write(u_mag)
print("Done. E =", E, "Results in:", outdir)Step 3 — Generate 5 solver scripts with different E values (Python)
Create generate_cases.py to produce five case scripts plus per-case output folders:
python
# generate_cases.py
import os, shutil
E_list = [5e8, 1e9, 2e9, 5e9, 1e10] # Pa: 0.5 GPa → 10 GPa
template = open("base_solver_template.py", "r").read()
os.makedirs("outputs", exist_ok=True)
os.makedirs("cases", exist_ok=True)
for i, E in enumerate(E_list, start=1):
case_name = f"case_{i}_E_{int(E):d}"
outdir = os.path.join("outputs", case_name)
code = template.replace("{E_YOUNG}", str(E)).replace("{OUTDIR}", outdir)
case_path = os.path.join("cases", f"{case_name}.py")
with open(case_path, "w") as f:
f.write(code)
print("Generated", len(E_list), "cases in ./cases and outdirs under ./outputs")Run it:
bash
python3 generate_cases.pyYou should now have cases/case_*.py and empty outputs/case_* folders ready. Automation like this prevents manual errors and speeds up studies.
Screenshot A: automation_study/ showing cases/ and outputs/ populated.
Step 4 — Batch-run all cases (bash)
Create run_all.sh to execute all generated Python cases and capture logs. Make it executable and run
Screenshot B: Terminal showing run_all.sh progress and output.
Screenshot C: outputs/ tree with five case folders, each containing u.xdmf and u_mag.xdmf.
Step 5 — Visualize any one output in ParaView
Open ParaView and load any of the generated output files.
Screenshot E: ParaView view of the scalar field for one case, scalar bar visible.
What to submit
- A: File tree or editor view showing
cases/andoutputs/after runninggenerate_cases.py. - B: Terminal capture of
./run_all.shrunning all five cases (with logs). - C:
outputs/directory showing five case folders, each with result files. - D (optional): Remote/headless run proof (tmux/nohup).
- E: ParaView screenshot visualizing (or
uvia Warp/Color By) for any one case.
Acceptance checklist (pass/fail)
- Five solver scripts generated programmatically with distinct Young’s modulus values.
- Bash script runs all cases in sequence and saves logs/results cleanly.
- Each case has its own output folder with XDMF results.
- At least one case visualized in ParaView with a clear scalar field view (and scalar bar).
- Folder structure and filenames are clean, consistent, and reproducible.
This pattern—Python to generate inputs, shell to orchestrate runs, and ParaView to review outputs—is the standard loop for robust parametric studies and makes it trivial to scale up or push to remote resources later.