Skip to content

Latest commit

 

History

History
473 lines (369 loc) · 19 KB

setup_problems.md

File metadata and controls

473 lines (369 loc) · 19 KB

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.

Start with the standard simulation tutorial for the student YAML route: small quasi-static SENT, small dynamic SENT, then full layered DCB. Use phast.Problem for programmatic construction and a complete YAML for shared runs. New adapter checks remain a promotion gate.

Standard schema-2 setup

Use the order schema_version, name, reference, geometry, regions, materials, assignments, initial_conditions, boundary_conditions, analysis_steps, solver, outputs. The {download}configuration authoring rules <../../CONFIGURATION_STYLE.md> are mandatory for new YAML/README/tutorial contributions.

Edit Input location Dependency or interpretation
Rectangle dimensions geometry.parameters.length, height, origin Update coordinate-based boundaries, layer/disk regions, and crack selectors.
Structured mesh geometry.parameters.nx, ny Check non-empty selections and material-boundary resolution, not only h/l0.
Inclusion geometry regions Match circle and complementary selectors; assignments cover all elements without overlap.
Stiffness materials.<name>.parameters.E Changes elastic response and energy; it is not toughness.
Fracture resistance materials.<name>.parameters.Gc Vary separately from E for a controlled comparison.
Material placement assignments Refer to declared element regions, not support node sets.
Starter crack initial_conditions and its region Maintained prescribed damage on this route, not a prescribed future path.
Loading boundary_conditions, analysis_steps[].active_boundary_conditions Check selected nodes, directions, values, signs, and active names.
Quasi-static increments analysis_steps[].controls.number_of_steps Includes zero on the multi-material route; cutbacks can increase the accepted count.
Numerical acceptance solver Tolerances and iteration limits, not experimental validity.
Saved fields outputs.fields Use a trajectory request with format: h5; PNG/GIF alone is not reloadable field data.

The documented multi-material route is structured T3 rectangles, CPU float64, quasi-static Amor AT2, elementwise E/Gc, common nu/l0, shared constitutive settings, and Dirichlet conditions. It is not dynamic multi-material or an independent interface law. The other geometry recipes below belong to their own documented adapters, not automatically to this one.

Quasi-static analysis omits inertia. Dynamics includes density and physical time; explicit integration additionally needs a CFL-limited time step. Final time, maximum steps, iteration limits, and output cadence are different controls. Smaller steps or a particular h/l0 are not validation guarantees. A short setup exercise may not propagate a crack; seeded damage = 1 is not evidence of new growth.

Frozen course inputs and separate 3D research retain their own scope until adapters and evidence exist.

Fluent and legacy FEM workflow map

The YAML column below describes the compatibility layout used by existing schema-1 examples. Use the mapping above for new standard schema-2 inputs; do not mix singular and plural sections.

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 phast.Problem("name") problem:
Part geometry Part / geometry sequence .geometry(...) geometry:
Imported mesh Mesh file / imported mesh .mesh("mesh.msh") geometry.mesh_path
Named selections Sets / physical groups / boundaries .region(...) geometry groups and node sets
Material definition Material card .material(...) material:
Material assignment Section assignment / domain material .material(..., region="body") schema 1 is single-material; schema 2 uses assignments above
Initial crack/notch state Initial field / predefined field .initial_condition("damage", ...) initial_conditions:
Supports Dirichlet BC / fixed constraint .fix(...) or .boundary_condition("fix", ...) boundary_conditions:
Prescribed displacement Displacement BC .prescribe(...) or .boundary_condition("displacement", ...) boundary_conditions:
Loads/tractions Neumann load / boundary load .neumann(...) or .boundary_condition("traction", ...) boundary_conditions:
Step/study Static, transient, or dynamic step .analysis_step(...) loading: and solver:
Solver controls Time step, tolerances, backend .solver(...) solver:
Field/history output Output requests / probes .outputs(...) output:
Job submission Run study / submit job .run(...) or python -m phast run ... CLI command
Results ODB/MED/XDMF/result database phast.load_result(path) 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

Use a dimensionally consistent system for all values. Unit-string conversion is route-specific: the schema-2 teaching inputs use bare numbers, and geometry.units does not convert arbitrary material/loading values. Common coherent conventions are:

Quantity SI example mm-N-MPa style example
Length m mm
Force N N
Stress/modulus Pa MPa = N/mm^2
Fracture energy Gc 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.

The quasi-static density is illustrative because inertia is omitted. Do not reuse it as measured density in dynamics. State out-of-plane thickness and reaction conventions when comparing forces.

Setup Checklist

Step Question to answer PhAST surface
Geometry or mesh Is this a built-in geometry or an imported Gmsh mesh? .geometry(...) or .mesh(...)
Regions What parts of the mesh receive materials, loads, supports, or outputs? .region(...)
Materials Which material model and parameters apply to each region? .material(...)
Initial conditions Does the run start with seeded damage or another supported field? .initial_condition(...)
Boundary conditions Which supports and loads are active? .boundary_condition(...), .fix(...), .prescribe(...), .neumann(...)
Analysis step Is this explicit dynamics, quasi-static fracture, or solid mechanics? .analysis_step(...)
Solver Which backend, tolerance, and solver family should be used? .solver(...)
Outputs Which fields, histories, plots, and trajectory stores are needed? .outputs(...)
Preflight Are region names and requested outputs valid? .validate_setup(), --validate-only
Inspection How will the completed run be read? phast.load_result(path)

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:

  1. define the domain;
  2. name the parts of the domain that matter;
  3. assign physics to those parts;
  4. prescribe how the model is loaded;
  5. choose what to record;
  6. 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:

  1. Choose the closest example from examples/.
  2. Run python -m phast run <example>/config.yaml --validate-only.
  3. Read the example README.md and inspect its checked-in visuals.
  4. Copy config.yaml into a new working directory.
  5. Change geometry or mesh first, then validate again.
  6. Change material parameters, then validate again.
  7. Change boundary conditions or loading, then validate again.
  8. Run a short baseline verification solve before launching the full case.
  9. 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
rectangular_sent Single-edge-notched plates and branching benchmarks W, H, a, h_crack, h_coarse, branching
miehe_tension Square SENT benchmark L, a, h_crack, h_coarse
miehe_shear Square SENS benchmark L, a, h_crack, h_coarse
kalthoff_winkler Two-notch impact specimen W, H, theta, h_crack
three_point_bending TPB beam L, H, a, h_crack
l_shaped_panel L-panel re-entrant corner L, h_crack
perforated_sent SENT with one or more holes W, H, hole_config

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
E Young's modulus
nu Poisson ratio
Gc Critical fracture energy
l0 Phase-field length scale
pf_model Damage model, for example AT1 or AT2
energy_split Tensile/compressive split, for example spectral or amor
eta_residual 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
glass_borden Borden-style dynamic glass benchmarks
maraging_steel_kw Kalthoff-Winkler impact
pmma_bleyer PMMA branching and perforated SENT studies
miehe_tension Miehe quasi-static SENT
miehe_shear Miehe quasi-static shear
l_shaped_concrete Ambati-style L-panel concrete benchmark
alumina_kumar 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
solid_mechanics tip_force_y, load magnitude or displacement controls used by the promoted solid runner Small solid-mechanics examples and material-kernel demonstrations.
quasi_static protocol, num_steps, dt, active boundary conditions Staggered phase-field fracture loading.
explicit 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 have a consistent, inspectable structure:

  • one config.yaml declarative configuration,
  • one optional run_fluent.py companion 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.

If an input choice or documented command is unclear, open a GitHub issue with the configuration, command, OS, Python/PhAST version, and full error.