Setting Up New Problems¶
This page explains the pieces of a PhAST forward model: geometry or mesh, regions, materials, initial conditions, boundary conditions, analysis steps, solver controls, outputs, validation, and result inspection.
Use the fluent phast.Problem API while designing a new setup. Use YAML configurations
for reproducible public examples, shared runs, CI, and HPC submission.
FEM Workflow Map¶
If you are coming from Abaqus, COMSOL, FEniCS, deal.II, or another FEM code, the PhAST workflow is the same sequence with different names:
FEM concept |
Abaqus/COMSOL-style term |
PhAST fluent API |
YAML configuration location |
|---|---|---|---|
Model or study |
Model database / component / study |
|
|
Part geometry |
Part / geometry sequence |
|
|
Imported mesh |
Mesh file / imported mesh |
|
|
Named selections |
Sets / physical groups / boundaries |
|
geometry groups and node sets |
Material definition |
Material card |
|
|
Material assignment |
Section assignment / domain material |
|
material plus region/node-set references |
Initial crack/notch state |
Initial field / predefined field |
|
|
Supports |
Dirichlet BC / fixed constraint |
|
|
Prescribed displacement |
Displacement BC |
|
|
Loads/tractions |
Neumann load / boundary load |
|
|
Step/study |
Static, transient, or dynamic step |
|
|
Solver controls |
Time step, tolerances, backend |
|
|
Field/history output |
Output requests / probes |
|
|
Job submission |
Run study / submit job |
|
CLI command |
Results |
ODB/MED/XDMF/result database |
|
result directory |
PhAST is intentionally narrower than a general-purpose commercial FEM GUI: the public API routes to supported phase-field fracture and solid-mechanics workflows. It does not compile arbitrary weak forms from user text.
Units¶
PhAST is unit-agnostic, like Abaqus. It does not convert units for you. Choose one consistent unit system and use it everywhere:
Quantity |
SI example |
mm-N-MPa style example |
|---|---|---|
Length |
m |
mm |
Force |
N |
N |
Stress/modulus |
Pa |
MPa = N/mm^2 |
Fracture energy |
J/m^2 |
N/mm |
Density |
kg/m^3 |
tonne/mm^3 when using mm-N-s |
Time |
s |
s |
Before running a new case, check that geometry dimensions, material properties, loads, density, fracture energy, and time-step controls are all expressed in the same system. The result manifests record the inputs; they do not infer or repair inconsistent units.
Setup Checklist¶
Step |
Question to answer |
PhAST surface |
|---|---|---|
Geometry or mesh |
Is this a built-in geometry or an imported Gmsh mesh? |
|
Regions |
What parts of the mesh receive materials, loads, supports, or outputs? |
|
Materials |
Which material model and parameters apply to each region? |
|
Initial conditions |
Does the run start with seeded damage or another supported field? |
|
Boundary conditions |
Which supports and loads are active? |
|
Analysis step |
Is this explicit dynamics, quasi-static fracture, or solid mechanics? |
|
Solver |
Which backend, tolerance, and solver family should be used? |
|
Outputs |
Which fields, histories, plots, and trajectory stores are needed? |
|
Preflight |
Are region names and requested outputs valid? |
|
Inspection |
How will the completed run be read? |
|
Why this sequence matters¶
The ordering above is deliberate. Geometry and regions define the available boundaries, materials attach physics to those boundaries, initial conditions seed the state, boundary conditions and analysis steps define the loading history, and outputs decide what information is preserved after the solve. Validation is most useful when it runs before the expensive solve, because many configuration errors are purely geometric or semantic and do not require a full simulation to detect.
If you are new to PhAST, think of the workflow as:
define the domain;
name the parts of the domain that matter;
assign physics to those parts;
prescribe how the model is loaded;
choose what to record;
validate the deck before the first solve.
Minimal Fluent Setup¶
import phast
problem = (
phast.Problem("linear plate")
.geometry("structured_grid", nx=40, ny=12, length=1.0, height=0.2)
.region("body", kind="domain")
.material("steel", model="solid_mechanics", region="body", E=2.1e11, nu=0.3)
.analysis_step("load", kind="solid_mechanics", controls={"tip_force_y": -1.0e3})
.solver("solid_mechanics", example="solid_mechanics.linear_plate")
.outputs(fields=["displacement", "von_mises"], histories=["response"], plots=True)
)
problem.validate_setup()
result = problem.run(output_dir="runs/linear_plate", return_result=True)
For the same workflow as a durable declarative configuration:
python -m phast run examples/solid_mechanics_beta/linear_plate/config.yaml \
--output_dir runs/linear_plate
Start From a Solved Example¶
The fastest way to build a trustworthy model is to clone a solved public example, then change one part at a time:
Choose the closest example from
examples/.Run
python -m phast run <example>/config.yaml --validate-only.Read the example
README.mdand inspect its checked-in visuals.Copy
config.yamlinto a new working directory.Change geometry or mesh first, then validate again.
Change material parameters, then validate again.
Change boundary conditions or loading, then validate again.
Run a short baseline verification solve before launching the full case.
Inspect the result with
phast.load_result(...).
Examples are YAML-first because they are reproducible. When available,
run_fluent.py shows the same model in the Python authoring style.
Geometry and Meshes¶
Use built-in geometry names for common benchmark shapes:
problem.geometry("rectangular_sent", W=100, H=40, a=50, h_crack=0.5, h_coarse=4.0)
Common built-in geometry recipes include:
Geometry name |
Use |
Typical parameters |
|---|---|---|
|
Single-edge-notched plates and branching benchmarks |
|
|
Square SENT benchmark |
|
|
Square SENS benchmark |
|
|
Two-notch impact specimen |
|
|
TPB beam |
|
|
L-panel re-entrant corner |
|
|
SENT with one or more holes |
|
The easiest way to discover geometry arguments is to start from a solved YAML example and inspect it:
python -m phast explain-config examples/dynamic/B2_kalthoff_winkler/config.yaml
python -m phast explain-config examples/quasistatic/notched_holed_plate/config.yaml
The example config.yaml files are the supported reference for each public
geometry recipe.
Use an imported Gmsh mesh when the geometry comes from CAD, Gmsh, or another meshing workflow:
summary = phast.inspect_mesh("meshes/notched_plate.msh")
print(summary["named_groups"])
problem = (
phast.Problem("imported plate")
.mesh("meshes/notched_plate.msh")
.region("body", from_mesh="Domain")
.region("left", from_mesh="Left")
.region("right", from_mesh="Right")
)
External meshes should preserve named physical groups for all boundaries used
by materials, boundary conditions, initial conditions, and history outputs.
In Gmsh, those names usually come from Physical Surface and Physical Curve
declarations:
Physical Surface("Domain") = {1};
Physical Curve("Left") = {2};
Physical Curve("Right") = {3};
Bind them to PhAST regions by name:
problem = (
phast.Problem("imported plate")
.mesh("meshes/notched_plate.msh")
.region("body", from_mesh="Domain")
.region("left", from_mesh="Left")
.region("right", from_mesh="Right")
)
Abaqus NSET/ELSET, COMSOL selections, and FEniCS boundary markers should be
exported or converted into equivalent Gmsh physical groups before use in PhAST.
Regions¶
Regions give stable names to domains and boundaries:
problem.region("body", kind="domain")
problem.region("left", from_mesh="Left")
problem.region("right", from_mesh="Right")
problem.region("notch", from_mesh="Notch")
Use short domain names in your model (left, right, notch) even if the
mesh group names are verbose. That keeps materials, loads, and histories easy
to read.
Materials¶
Assign materials to regions:
problem.material("glass", region="body", E=210000.0, nu=0.3, Gc=2.7, l0=0.25)
For phase-field fracture, common parameters are:
Parameter |
Meaning |
|---|---|
|
Young’s modulus |
|
Poisson ratio |
|
Critical fracture energy |
|
Phase-field length scale |
|
Damage model, for example |
|
Tensile/compressive split, for example |
|
Residual stiffness used after high damage |
For public benchmark reproduction, start from the checked-in config.yaml.
For a real engineering study, choose material parameters from the relevant
material data source and document the unit system with the run.
Common material presets include:
Preset |
Typical use |
|---|---|
|
Borden-style dynamic glass benchmarks |
|
Kalthoff-Winkler impact |
|
PMMA branching and perforated SENT studies |
|
Miehe quasi-static SENT |
|
Miehe quasi-static shear |
|
Ambati-style L-panel concrete benchmark |
|
Star-convex nucleation studies |
Initial Conditions¶
Seed an initial notch or damaged region when the workflow supports damage initialization:
problem.initial_condition("damage", region="notch", value=1.0)
The public fracture examples use this path to mark a pre-existing notch before the load step begins.
Boundary Conditions¶
Use explicit named boundary conditions for clarity:
problem.boundary_condition("fix", region="left", dof="xy", name="clamp")
problem.boundary_condition("displacement", region="right", dof="x", value=0.01, name="pull")
problem.boundary_condition("traction", region="top", dof="y", value=1.0, name="top_load")
Use shorthand helpers in compact examples:
problem.fix("left", dof="xy")
problem.prescribe("right", dof="x", value=0.01)
problem.neumann("top", dof="y", value=1.0)
Always specify a degree of freedom for displacement-style conditions:
dof="x", dof="y", or dof="xy".
Analysis Steps and Solver Settings¶
The analysis step describes the physical solve:
problem.analysis_step(
"load",
kind="quasi_static",
controls={"protocol": "simple", "num_steps": 10},
active_boundary_conditions=["clamp", "pull"],
)
Current public fluent workflows use one primary analysis step. For staged
loading, use the loading protocol supported by that workflow, or encode the
staged run in the example YAML configuration for that example. Do not assume chained
.analysis_step(...) calls create a full Abaqus-style step sequence unless the
specific workflow documents that behavior.
Common controls:
Workflow kind |
Typical controls |
Meaning |
|---|---|---|
|
|
Small solid-mechanics examples and material-kernel demonstrations. |
|
|
Staggered phase-field fracture loading. |
|
final time, time-step safety, output cadence, damage update cadence |
Dynamic fracture examples; public YAML configurations expose the full control set. |
The solver settings select numerical controls:
problem.solver("quasi_static", backend="auto", preconditioner="jacobi", max_stagger=500)
For explicit dynamics, the YAML examples expose the full time-step and output cadence controls and are the recommended starting point for reproducible runs.
Outputs¶
Request fields, histories, plots, and trajectory stores:
problem.outputs(
fields=["damage", "displacement"],
histories=[{"name": "reaction_force", "region": "right", "dof": "y"}],
plots=True,
trajectory=True,
)
A promoted example result directory should include the declarative configuration, lockfile, metadata, history CSVs, standard figures, and a visual manifest. See Example result contract for output conventions.
Validate, Run, Inspect¶
Validate a Python-authored setup:
problem.validate_setup()
problem.preview(output="runs/my_case/setup.png")
Validate a YAML configuration:
python -m phast run examples/quasistatic/notched_holed_plate/config.yaml --validate-only
python -m phast explain-config examples/quasistatic/notched_holed_plate/config.yaml
Run a YAML configuration:
python -m phast run examples/quasistatic/notched_holed_plate/config.yaml \
--output_dir runs/notched_holed_plate
Inspect the result:
import phast
result = phast.load_result("runs/notched_holed_plate")
print(result.metadata())
print(result.history_names())
print(result.visuals())
Acceptance Targets¶
For benchmark or researcher-validation runs, include an acceptance: block in
the YAML once the setup is more than a local scratch case. The block records
what the run is expected to reproduce; it does not change the solve.
acceptance:
status: beta
reference_result: "Borden et al. (2012), Fig. 10"
required_outputs: [run_lockfile.json, config.yaml, damage_final.png]
metrics:
crack_path:
target: "straight crack to right boundary"
tolerance: visual
peak_force:
target: null
tolerance: null
units: N
notes: "Fill numerical targets once the reference extraction is audited."
Keep this block honest: use scaffold or beta until the benchmark has a
documented reference extraction, a known reaction/load convention, and a stored
comparison artifact.
What Makes a Good Public Example?¶
Each public example should be boringly predictable:
one
config.yamldeclarative configuration,one optional
run_fluent.pycompanion when the fluent path is promoted,setup visual,
final field plots,
response or energy histories,
animation when the response is meaningful,
run_manifest.json,run_metadata.json, and lockfile,clear README with the command, runtime expectation, and expected outputs.
Examples that still need large raw trajectories, unpublished HPC provenance, or custom one-off scripts should stay out of the public examples tree until they are promoted.