English · Українська · Русский · 简体中文
Identification of density-dependent Drucker–Prager Cap models and generation of LS-DYNA material cards.
You give it what you measured on a powder — Brazilian discs, axial compression,
closed-die pressing, hydrostatic points — and it gives you back three LS-DYNA
material cards built from one identification: our density-dependent user material
(umat41), and the two stock cards, *MAT_CSCM (MAT_159) and
*MAT_GEOLOGIC_CAP_MODEL (MAT_025).
The output is a plain .k file containing material cards only — no geometry, no
mesh, no loads. You attach it to whatever model you like and point your parts at the
MID you want. That is deliberate: the material data is the part that cannot be
obtained anywhere else; the geometry is yours.
Version 1.0 · Ya. Dvirnyk, Zaporizhzhia Polytechnic National University ORCID 0000-0001-5439-5413
- Installation
- The five-minute version
- The window
- Tab A — Experiment: entering your data
- The material and the pore-free density
- Tab B — Identification: fitting the laws
- Tab C — Model parameters: the three densities
- Tab D — Final model
- Tab E — LS-DYNA card
- Exporting: what you get
- Using the card in LS-DYNA
- The 3D and 2D views
- Projects, language, settings
- Messages the program may show you
- What the program does NOT do
- Building from source
- Citing
There is nothing to install. Download PowderCap.exe and double-click it.
Windows 10/11, 64-bit. No Python, no LS-DYNA, no licence needed to run it.
Two things worth knowing:
- The first start takes 10–30 seconds. The executable is one 227 MB file that unpacks itself into a temporary folder before the window appears. Later starts are faster because Windows caches it. Nothing is written to your registry.
- Keep the .exe in a folder you can write to (your Documents, a project folder —
not
C:\Program Files). The program writes its material database,materials_db.json, next to the executable. If that folder is read-only, the built-in materials still work, but you cannot save your own.
To move the program to another machine, copy PowderCap.exe. To take your materials
along, copy materials_db.json next to it.
If you just want to see it work:
- Start
PowderCap.exe. - Tab A — Experiment → Import CSV → pick
raw_tests_distaloy_AE.csv(shipped with the paper's data). 35 rows appear. - Tab B — ρ-law identification → press Identify all forms from experiment points. Six laws appear, each with its R².
- In the toolbar at the top, choose the material Distaloy AE (Fe). The pore-free density fills in.
- Tab C — Model parameters → set ρ₀ start to
0.50. - Tab E — LS-DYNA card → Export cards… → tick all four → Save.
You now have a .k file with four material cards. That is the whole workflow; the
rest of this document explains each step and why it is there.
┌──────────────────────────────────────────────────────────────────────────┐
│ File Settings Help │ ← menu
├──────────────────────────────────────────────────────────────────────────┤
│ Material: [ Distaloy AE (Fe) ▾ ] = 7.48e-09 t/mm³ [Save to database] │ ← material
│ [Delete] Developed by Ya. Dvirnyk│ toolbar
├────────────────────────────────────────┬─────────────────────────────────┤
│ A — Experiment │ │
│ B — ρ-law identification │ 3D / 2D view │
│ C — Model parameters │ │
│ D — Final model │ ☑ UMAT ☑ MAT_025 ☑ MAT_159 │
│ E — LS-DYNA card │ ρ slider ─────●─────── │
│ │ │
├────────────────────────────────────────┤ │
│ Calculation log (plain text) │ │
└────────────────────────────────────────┴─────────────────────────────────┘
The tabs run in workflow order, A → E: enter data, fit laws, check parameters, review the assembled model, write the card. You normally go through them once, top to bottom.
The calculation log under the tabs shows every step with its formula and numbers —
what was substituted, what came out. It is plain text: select it, copy it, or save it
with File → Export log. It is the same text the .txt export writes.
This is where your measurements go. One row = one specimen.
| Column | Meaning |
|---|---|
| Test type | which experiment this row is (drop-down, see below) |
| value 1 … value 4 | the measured numbers — what they mean depends on the test type |
| ρ (relative density) | the relative density of that specimen, 0…1 |
The column captions and units change when you pick a test type, and cells that the chosen test does not use are greyed out and say "not used for this test". You cannot put a number in the wrong place by accident.
| Type | What you enter | What it gives |
|---|---|---|
| Brazilian radial (disc, diametral fracture) | F [N] fracture force, D [mm] diameter, t [mm] thickness |
a point on the shear branch at low pressure |
| Axial disc compression | F_a [N] force, D [mm] diameter |
a point on the shear branch |
| Tension (per standard) | σ_u [MPa] tensile strength |
the tensile point |
| Closed die (instrumented): loading + unloading | σ_ax [MPa] axial, σ_rad [MPa] radial, E [MPa] from unload slope, ν from unload ratio |
a point and the elastic pair E, ν |
| Hydrostatic / elastostatic | p_b [MPa] hydrostatic limit |
the cap intercept on the pressure axis |
The reduction formula for the selected type is shown under the table, so you can see exactly what is done with your numbers, for example:
radial: p = 4F/(3·π·D·t), q = √52·F/(π·D·t)
die: p = (σ_ax + 2·σ_rad)/3, q = σ_ax − σ_rad
unload → E (slope) and ν = K0/(1+K0), K0 = σ_r/σ_ax
At least three different densities. With two, every two-parameter law fits perfectly (R² = 1) and the program cannot tell which shape is right — it will warn you about this. Seven densities is what the published data sets use.
At each density you want, at minimum, one die row (it carries E and ν as well) and one hydro row (it fixes the cap). The Brazilian, axial and tension rows populate the shear branch.
- Add row / Delete — edit the table by hand.
- Import CSV — load a table. This is the usual way in.
- Export CSV — save the table back out.
- Recalculate — refresh the log and the views.
Six columns, a header line, comma-separated, dot or comma as decimal separator:
test_type,v1,v2,v3,v4,rho
radial,1.413281,10.0,5.0,,0.5
axial,29.783703,10.0,,,0.5
die,8.440520,3.180440,10700.0,0.0385,0.5
hydro,6.304020,,,,0.5test_type is one of radial, axial, tension, die, hydro. Leave a cell empty
if that test does not use it. Rows may be in any order; the program groups them by
density itself.
This step is easy to skip and it will block your export if you do.
The toolbar at the top carries the material. Pick one from the drop-down — the list ships with 48 materials: titanium alloys (VT1-0, VT6, VT3-1, Ti-1023, γ-TiAl), nickel superalloys (Inconel 718/625/738LC, Rene 41, Waspaloy, ZhS6U, ZhS32, EI698, EP741NP), iron powders (Distaloy AE/AB, Astaloy Mo, ASC100.29), steels, hard metals, ceramics, light alloys.
Picking a material sets the pore-free density ρ_theo — the density of the solid, zero-porosity material. Everything density-related is built on it:
card RO = ρ₀ × ρ_theo (the mass density LS-DYNA integrates)
and the relative densities in your table are converted to absolute ones through it.
If your powder is not in the list, type the density into the ρ pore-free field on tab C (in kg/m³ — the unit it is published in; the program converts to t/mm³ for the card). Then Save to database if you want it back next time.
Why this matters. A wrong pore-free density is silently wrong: the yield surface is still right, but the mass is not, which changes the explicit time step and the inertial terms. The program therefore refuses to export a card whose RO does not equal ρ₀ × ρ_theo — see §14.
Press Identify all forms from experiment points. This is the heart of the program.
For each of six parameters it takes your points, fits seven candidate shapes, and picks the best:
| Parameter | What it is |
|---|---|
d(ρ) |
cohesion |
tanβ(ρ) |
friction (the slope of the shear line) |
R(ρ) |
cap aspect ratio |
p_b(ρ) |
cap position on the pressure axis (hardening) |
E(ρ) |
Young's modulus |
ν(ρ) |
Poisson's ratio |
The seven shapes:
const f = a
power f = a·ρ^b
exp f = a·exp(b·ρ)
linear f = a + b·ρ
poly2 f = a + b·ρ + c·ρ²
expoffset f = a + b·e^(c·ρ)
poweroffset f = a + b·ρ^c
| Column | Meaning |
|---|---|
| form | which shape is used — a drop-down; you can override the automatic choice |
| coefficients | a, b, c |
| R² | ordinary coefficient of determination |
| R² adj. | adjusted R² — this is what the automatic choice uses |
| max dev. % | the worst relative deviation over your points |
Why adjusted R² and not R². A three-coefficient shape always fits at least as well
as a two-coefficient one, simply by having more freedom. Adjusted R² charges for that
freedom, so a poly2 does not win over a power unless it earns it.
Read "max dev. %", not just R². R² = 0.997 can hide a 36 % error at the low-density end, where the values are small. The worst deviation is the number that tells you whether a law is usable across your whole range.
You can force a different shape per parameter with the drop-down — the choice applies immediately to the model, the views and the card.
Three densities appear in this program and they do different jobs. Getting them straight is most of understanding the tool.
The state your simulation starts from. Everything is anchored to it:
umat cm(1) = ρ₀ the user material's anchor
RO = ρ₀ × ρ_theo the mass density
X0 = 3·p_b(ρ₀) where the stock cards' cap starts
W = ln(1/ρ₀) how much compaction is left from there
d, β, R at ρ₀ the constants the stock cards freeze
There is deliberately no separate "reference density" field. Our user material has no reference density at all — it evaluates the laws at the current ρ every step. A second field could only make the stock cards start from a different state than the user material, which would make the comparison meaningless.
Typical value: the lowest density you actually tested (0.50 for the iron data, 0.35 for WC-Co).
The apparent (tap) density of the loose powder. p_b crosses zero there and is
negative below it, so the model is undefined under this density.
The field fills itself from the fitted p_b law (its zero — 0.4144 for Distaloy AE)
and stays editable. If you type a measured value it is used as-is and never
overwritten, and the card says which of the two it used.
Covered in §5. In kg/m³; the t/mm³ value that goes into the card is shown underneath.
The groups are labelled by which material they feed:
- DPC constants @ ρ₀ → stock MAT_159 and MAT_025 — d, β, R, W, D. Both stock cards use exactly these; they differ only in cap shape.
- Elasticity @ ρ₀ → stock MAT_159 and MAT_025 — E and ν read off the fitted laws at ρ₀.
- UMAT (our material) — laws evaluated every step — a read-only read-out of d(ρ), tanβ(ρ), R(ρ), p_b(ρ), p_a(ρ), E(ρ), ν(ρ) at the density of the ρ slider. These are not inputs: the user material has no frozen constants.
Fields showing a fitted value are read-only (they are a slice of the model, not a free input) and say so in their tooltip.
The assembled model, in formulas, with one numbered section per material so you can see what separates them:
Density laws — the six laws, the shared source of all three cards.
1. UMAT (our material) — angular DPC ellipse. No frozen constants; α = 0, so the corner between cone and cap is kept.
2. Stock MAT_025 — the same segmented ellipse, constants frozen at ρ₀, cap advancing through X0, W, D1. Against the UMAT, this isolates the cost of freezing the constants.
3. Stock MAT_159 — continuous cap (CSCM). Frozen the same way, but the cap is a smooth product F_f·F_c with no corner. Above the junction it lies outside the segmented one. Against MAT_025, this isolates the effect of the cap shape.
Then the coefficients shared by both stock cards (α, θ, R_card, G, K, X, X₀, D₁), listed once, and the three fields only MAT_025 has (TOFF, γ, C/N).
Two export buttons live here as well as on tab E — they do the same thing.
The cards exactly as LS-PrePost shows them: field name on top, value underneath, grouped by card. Computed fields are highlighted; fields left at a default are grey.
Four blocks: *MAT_CSCM, *MAT_GEOLOGIC_CAP_MODEL twice (FTYPE = 2 and FTYPE = 1),
and *MAT_USER_DEFINED_MATERIAL_MODELS, each with its own Copy keyword button if
you want just that one on the clipboard.
Below the UMAT card is the P1…P30 legend: what every constant in the user material's array means.
Material density RO sits at the top. With a material selected it is read-only and
derived (ρ₀ × ρ_theo); with no material it stays editable.
Export cards… (tab D or tab E) opens one dialog with four tick boxes:
☑ *MAT_CSCM (MAT_159, stock)
☑ *MAT_025, FTYPE=2 (no cap contraction)
☑ *MAT_025, FTYPE=1 (cap may contract)
☑ *MAT_USER (umat41, density-dependent)
Tick any combination — all four for the comparison the paper makes, or a single card
when you already have a deck. Save writes one .k file.
Why both FTYPEs of MAT_025. FTYPE = 1 lets the cap contract, FTYPE = 2 does not. For a powder that is not cosmetic: cap contraction is how this model family limits dilatancy on the cone, and it is also what lets the material give back compaction it already gained. Both are worth running.
$ Generated by PowderCap
$
$ Material cards only -- attach to a model with *INCLUDE and point the
$ parts at the MID you want. No geometry, sections or loads here.
$ Every card is anchored at the SAME start density rho0 = 0.5000:
$ X0, W, RO and umat cm(1) all describe that one state.
$
$ MID 1 = *MAT_CSCM (MAT_159, stock, frozen @ rho_ref)
$ MID 2 = *MAT_GEOLOGIC_CAP_MODEL (MAT_025, FTYPE=2, no cap contraction)
$ MID 3 = *MAT_GEOLOGIC_CAP_MODEL (MAT_025, FTYPE=1, cap may contract)
$ MID 4 = *MAT_USER_DEFINED_MATERIAL_MODELS (umat41, density-dependent)
$
$ MAT_159 (CSCM) frozen at rho0 = 0.5000
$ anchor rho0 = 0.5: X0 = 3*p_b(rho0) = 18.9121 MPa, W = 0.693147 (ONE state)
$ strain convention: log measure eps=ln(rho/rho0), limit W=ln(1/rho0)
$ cap can densify to rho0*exp(W) = 1.0000
$ D1 = 0.00330677 1/MPa fitted on [0.500, 1.00] by minimax of the RELATIVE
$ DENSITY error: worst 6.83%
$ two-parameter cap vs the fitted p_b law: R2 = 0.8115, worst 22.1% at rho = ...
$ fill density rho_fill = 0.414438 -- lower bound of the model (zero of the p_b law)
$ RO = rho_rel * rho_pore-free = 0.5000 * 7.450 g/cm3 (Distaloy AE (Fe)) = 3.7250e-09
*MAT_CSCM
$# MID RO NPLOT INCRE IRATE ERODE RECOV ITRETRC
1 3.725e-09 1 0 0 0 0 0
...
*END
Every card carries its own comment block stating the anchor state, the strain convention, the density the cap can reach, the fit interval and the error it leaves. This is deliberate: those numbers tell you whether to trust the card, and reading them off the file beats discovering them by comparing runs.
The comments are always in English, whatever language the interface is set to — the deck is read by whoever runs the solver, not necessarily by whoever generated it.
- Export identified model (text for a paper) — the laws written out as text, for copying into a manuscript.
- *Export MAT_159 / UMAT constants — the older single-file export, kept for compatibility.
The exported .k holds materials and nothing else. In your own deck:
*INCLUDE
powdercap_materials.k
then point a part at the MID you want:
*PART
$# title
powder
$# pid secid mid
1 1 4 $ <- MID 4 = the density-dependent UMAT
MIDs are numbered 1…n in the order the cards were written, and the header lists
them, because a deck cannot hold four materials all claiming MID 1. If those numbers
collide with your own, renumber them in the .k — it is a plain text file.
*MAT_USER_DEFINED_MATERIAL_MODELS calls a Fortran routine that must be compiled
into your LS-DYNA executable. The reference source, umat41.f, is in the paper's
Zenodo record. Without it, use the stock cards — they need no compilation.
The card is written for MT = 41, LMC = 30, NHV = 2, IBULK = 25, IG = 26, which must
match the routine's header.
Damage, erosion, rate effects and kinematic hardening are all switched off
(IRATE = 0, damage parameters left at their suppressing values, C = N = 0). The
cards describe the yield surface and its hardening — nothing else. If you need
softening or rate dependence, add it deliberately.
The panel on the right draws the yield surface. Switch between 3D surface and 2D section (meridian) with the drop-down.
| Colour | Line | Cap shape | |
|---|---|---|---|
| UMAT (density-dependent) | red | solid | angular DPC ellipse, corner kept |
| MAT_025 (frozen) | green | dash-dot | the same segmented ellipse |
| MAT_159 (frozen) | blue | dashed, shaded | continuous (smooth) cap |
Each has its own tick box, coloured to match. Any subset draws. The styling follows Figure 11 of the paper, so a screenshot is publication-ready.
The cap shape belongs to the model, not to a switch — that is the whole point of having all three: red against green shows the cost of freezing the constants, green against blue shows the cost of the cap shape.
- ρ slider — the current density. Moves the cap of all curves and the whole density-dependent UMAT surface.
- model points — filled markers, computed from the laws.
- raw data (hollow) — your measured points at their own densities, to check the fit by eye.
- equations (callouts) and markers d, β, pₐ, p_b — annotate the 2D section.
- side-by-side — one viewport per visible model (3D only).
- Surface settings (collapsible) — opacity, circles, meridians, angular sector, per model.
- Axis settings (collapsible) — proportions, font, tick counts. The p:q axis proportion starts at 3:1, the ratio that makes the body read as a solid rather than a spike; the spinboxes are multipliers on top of that.
- Save PNG — a screenshot of the current view.
Projects (File → Save / Open) are written as .pcpj — a plain JSON file holding
the experiment table, the fitted laws, the densities, the material and the view
settings. Files from before the program was renamed (.cse) still open and re-save
under their own name.
Language (Settings → Language): English, Українська, Русский, 简体中文. Switching
retranslates the whole interface, including the calculation log. Two things stay Latin
in every language: the 3D axis labels and titles (VTK's fonts carry no Cyrillic or
CJK), and the comments in the exported deck (see §10).
Text size and Formula size are separate settings, both under Settings.
Help → About carries the version, the author and the identifiers.
The card's mass density does not equal ρ₀ × ρ_theo. The dialog gives both numbers. Usual causes: you changed ρ₀ or the material after the card was built, or the project predates the material you selected.
Fix: confirm the material in the toolbar and the ρ₀ on tab C. RO recomputes on its own; the message goes away.
This is a hard block — the card would carry the wrong mass otherwise.
Something in the model is not physical over the working range, for example:
rho0_start = 0.4 is below the fill density 0.4144, where p_b crosses zero —
the model is undefined below it. Enter rho0_start ≥ 0.4144.
The dialog lists every problem and asks whether to export anyway. Usually you should not — fix the input instead. The most common case is exactly the one above: a start density below the powder's fill density.
You have fewer than three densities, so the form cannot be chosen reliably. Add data.
The project carries a material this machine's database does not have. It still works — the passport travels inside the project. Press Save to database to add it.
Stated plainly, so you know where its job ends:
- No geometry and no meshing. It writes materials; you bring the model. Earlier versions built specimens and dies; that was removed deliberately so that any analyst can attach any geometry.
- No process simulation. It does not press anything — LS-DYNA does.
- No damage or fracture. The cards carry the yield surface and its hardening; softening is switched off.
- It does not compile
umat41.finto your solver. That is your build step. - It does not check your data for you. Garbage points fit a law just as happily as good ones — read the max dev. % column and look at the raw points against the curves.
Requires Python 3.11+ with PySide6, pyvista, pyvistaqt, matplotlib, numpy,
scipy, pillow.
python cap_gui.py # run from source
python make_icon.py # re-render the icon (powdercap.ico)
pyinstaller --noconfirm PowderCap.spec # build dist/PowderCap.exeThe spec file, not a command line, because VTK/PyVista resolve renderer plugins by name at run time, matplotlib needs its font data, and UPX compression must stay off (it breaks VTK DLLs and trips antivirus heuristics).
Source layout:
| File | What it is |
|---|---|
cap_gui.py |
the interface and the card writers |
cap_model.py |
the physics: laws, fitting, the cap calibration |
materials_db.py |
the material database |
make_icon.py |
renders the icon from the program's own surface |
PowderCap.spec |
PyInstaller build recipe |
If this program contributed to your work, please cite the paper and the software:
Y. Dvirnyk, PowderCap: identification of density-dependent Drucker–Prager Cap models and generation of LS-DYNA material cards, 2026. doi:10.5281/zenodo.21893514, software (Windows executable). Version 1.0.
The Zenodo record also contains the reference umat41.f source and the experimental
data sets used in the paper.
Contact: dvirnyk@gmail.com · ORCID 0000-0001-5439-5413 · Scopus Author ID 57212582169