Workflow: NC Optimization
This workflow describes how to generate optimized NC files from a physics-based simulation. The optimizer adjusts feed rates to keep physical quantities (spindle power, torque, thermal stress, cutting force) within specified safety limits while maximizing machining efficiency.
flowchart TD
Prereq["Prerequisites<br>(simulation with physics,<br>cutting parameters)"]
Config["Configure optimization options"]
Simulate["Run simulation"]
Output["Generate optimized NC files"]
Verify["Verify optimization results"]
Prereq --> Config --> Simulate --> Output --> Verify
1. Prerequisites
NC optimization requires a simulation environment with physics enabled and valid cutting parameters:
EnablePhysics = true;
LoadCuttingParaByFile("Material.mp");
| Prerequisite | Description |
|---|---|
| Physics enabled | EnablePhysics must be true |
| Cutting parameters | Workpiece must have loaded milling coefficients (see Workflow: Milling Force Parameter Training) |
| Valid tool definitions | Tool geometry, flute count, and material properties configured |
Note
Optimization is based on an ideal geometric model. If the workpiece is a casting or has installation errors, configure a conservatively larger workpiece geometry to prevent misidentification of cutting vs. non-cutting regions.
2. Configure Optimization Options
Feed Rate Control
| Property | Description | Default |
|---|---|---|
| OptEnableFeedrate | Enable sequential feed rate optimization | true |
| OptEnableInterpolation | Re-interpolation for smoother acceleration/deceleration | — |
| OptRapidFeed_mmdmin | Feed rate for non-cutting regions (mm/min) | — |
| OptMinFeedrate_mmdmin | Minimum cutting-region feed rate (mm/min) | — |
| OptMaxFeedrate_mmdmin | Maximum cutting-region feed rate (mm/min) | — |
| OptMaxAcceleration_mmds2 | Acceleration/deceleration limit (mm/s²) | — |
| OptFeedrateAssignmentRatio | Re-interpolation trigger threshold | — |
Extended Distance
| Property | Description |
|---|---|
| OptExtendedPreDistance_mm | Pre-distance for equivalent calculation of cutting regions (mm) |
| OptExtendedPostDistance_mm | Post-distance for equivalent calculation of cutting regions (mm) |
Safety Factors (Physics-Based Constraints)
| Property | Description |
|---|---|
| OptSpindlePowerSafetyFactor | Spindle power safety factor (0 = ignore) |
| OptSpindleTorqueSafetyFactor | Spindle torque safety factor (0 = ignore) |
| OptThermalYieldSafetyFactor | Thermal yield safety factor (0 = ignore) |
| OptPreferedForce_N | Target cutting force (N) |
Note
Target value = 100% / Safety factor. For example, a safety factor of 1.5 means the physical quantity targets ~67% of the limit.
Constraint Priority
In cutting regions, constraints are applied in this order:
- Direct feed rate constraints (min/max feed rate, min/max feed per tooth from tool settings)
- Acceleration/deceleration constraints (
OptMaxAcceleration_mmds2) - Physics-based constraints (spindle power, torque, thermal yield, preferred force)
When constraints at the same priority conflict, the lowest feed rate is used.
A floor above the ceiling neither fails nor lowers the feed: where the composed minimum feed per tooth exceeds the composed maximum — a minimum feed rate, a minimum feed per tooth or the cutter's minimum uncut chip thickness sitting above the maximum — the boundary collapses onto the minimum, and the step is solved there.
Script Command Example
OptEnableFeedrate = true;
OptEnableInterpolation = true;
OptRapidFeed_mmdmin = 4000;
OptMinFeedrate_mmdmin = 100;
OptMaxFeedrate_mmdmin = 4000;
OptMaxAcceleration_mmds2 = 10;
OptExtendedPreDistance_mm = 3;
OptExtendedPostDistance_mm = 2;
OptSpindlePowerSafetyFactor = 1.5;
OptSpindleTorqueSafetyFactor = 1.5;
OptThermalYieldSafetyFactor = 0;
OptPreferedForce_N = double.PositiveInfinity;
XML Configuration (NC Code Inline)
Optimization settings can be embedded in NC code comments:
N0110 X-3.064 Y6.378 (;@OptMaxAcceleration_mmds2=10;)
N0150 G01 X-3.068 Y40.776 (;@OptMaxAcceleration_mmds2=100; OptMaxFeedrate_mmdmin=12000;)
3. Run Simulation
Configuration can be interleaved between NC files. Settings apply to the files that follow:
OptRapidFeed_mmdmin = 4000;
PlayNcFile("NC/file1.nc");
OptRapidFeed_mmdmin = 8000;
PlayNcFile("NC/file2.nc");
Excluding Lines from Optimization
To preserve specific NC lines unchanged:
N0140 G03 X-2.66 Y38.193 I-103.796 J7.172 (;@Preserve();)
To exclude a range:
N0140 G03 X-2.66 Y38.193 (;@BeginPreserve();)
N0150 G01 X-3.068 Y40.776
N0160 X-3.555 Y43.338 (;@EndPreserve();)
Warning
Do not combine UpdateNcOptOption inside the SessionStepBuilt event with NC-embedded optimization commands. This may cause undefined behavior due to parallel computation.
4. Generate Optimized NC Files
OptimizeToFiles writes the optimized NC programs:
OptimizeToFiles("Cache/Opt-[NcName]");
The [NcName] template is replaced with each input NC file name.
What the Run Reports
An optimization reports itself to the Shell tab of the Session Messages panel, as a fixed sequence of rows:
| Row | Stage |
|---|---|
Start NC optimization. |
the pass opens |
Computing Optimized Feed by indivisual step.. |
the per-step feed solve |
Optimization Feedrate built. |
the feed solve closed |
Constrain feedrate By expaneded segment.. |
the extended-distance constraint |
Constrain Feedrate By Acceleration.. |
the acceleration constraint |
Build Compensation.. |
the compensation build |
Regenerate NC commands.. |
the NC text is rewritten |
File optimized: <path> |
one row per written file |
Total N files optimized. |
the pass is over |
optimization cache cleared. |
the step cache is released |
Two of those stages tick while they work, and they are the only instrument for telling a slow
optimization from a stopped one. The feed solve adds Computing Optimized Feed by indivisual step.. FileNo:<n>, LineNo:<m> every thousand steps solved — StepIndex:<i> instead, for a step that
carries no source line — and the writer adds Now optimizing to: FileNo.<n>, LineNo.<m> every
thousand lines written. Each names the source file and line the run has reached, so a ladder whose
last row keeps advancing is a run still moving through the program, and one that has gone quiet
without reaching Total N files optimized. is not. A stage with fewer than a thousand steps or
lines to get through announces its start and then says nothing until it ends, so a short program
crosses the whole ladder in near-silence.
Stop reaches inside an optimization. The transport's Stop is tested between every pair of
stages, inside the per-step feed solve, and once per destination piece while files are written, so a
stopped optimization halts at the next step or piece boundary rather than running to the end. The
Shell ladder says so twice: the feed solve closes with Optimization Feed Process canceled. in
place of Optimization Feedrate built., and an optimization canceled. row is added before the
pass ends.
Important
A stopped optimization still ends on the green Total N files optimized. row a completed one ends
on. That row is not a statement that the optimization finished — read the row above it. N counts
the files the run had begun writing, so a Stop during the feed solve ends on
Total 0 files optimized., and a Stop during writing counts the file it was in the middle of,
which is left short.
5. Verify Optimization Results
Optimization Logs
The per-step log is written by default. Every optimization drops one .IndependentStepAdjustment.log
beside each optimized NC file that had steps to solve, named after that optimized file, and it
records which constraint limited each step.
EnableIndividualStepAdjustmentLog is the switch that stops it
being written:
EnableIndividualStepAdjustmentLog = false;
A stopped or failed optimization leaves that file short. Its buffered tail is written out only when
the feed solve runs to completion; when the pass is cut off, the lines still in the buffer are
dropped, and so is any step line held back in the ordering window waiting for a lower step index
that never arrived. Batches reach the file at most once a second, so the missing tail can cover the
last second of solving as well as the steps that were never reached. Read the log as a complete
record only for a run whose feed solve closed with Optimization Feedrate built.
Each row of the .IndependentStepAdjustment.log file opens with the source NC file and line, the step index and the cutter location, then lists the feed per tooth every active criterion allowed:
| Field | Criterion |
|---|---|
FrtByPreferedForce_mm |
target cutting force |
FrtByYieldingStressRatio_mm |
yielding stress |
FrtBySpindleTorqueRatio_mm |
spindle torque |
FrtBySpindlePowerRatio_mm |
spindle power |
FrtByThermalYieldingRatio_mm |
thermal yield |
FrtByCustom_mm(n) |
the n-th custom criterion the script registered |
FrtByReliefAngle_mm |
relief-face contact — see Relief Face Avoidance |
The step's feed per tooth is the lowest of the first six; the relief-angle pass then runs on that value, so its row is the last word rather than one vote among the others.
Every row carries the solver's status for that criterion in brackets: Solved when the binary solve converged, Singular / OverIteration / Iterating when it did not, and — on the relief-angle row only — Acceptable, which means the relief face was clear at the feed already chosen, so that row states the feed instead of a limit on it. A criterion with no row at all was switched off (its safety factor is 0) or was not evaluable for that tool.
Three rows replace that list rather than joining it:
| Field | Meaning |
|---|---|
FrtByUnTouched: inf |
the step cuts nothing, so no physical criterion applies |
FeedrateByNoData_mmdmin: <feed> |
no tool or no milling coefficients on the step; it keeps its feed |
StepFailed: <exception> |
the solve threw; the step keeps its simulated feed and is reported as an error — see When a Step Cannot Be Solved |
Embedded Log Comments
Control embedded log verbosity with EmbeddedLogMode:
| Mode | Description |
|---|---|
None |
No log comments |
SimpleLog |
StepIndex on re-interpolated lines; LineNo on last interpolated line per original line |
FullLog |
StepIndex and LineNo on all lines |
Important
The mode is read by the legacy optimization path. While
EnableSoftNcRunner is on and the session holds played
NC — the default — the optimizer writes the SimpleLog shape whatever the mode says: every
re-interpolated fragment carries its StepIndex, the last fragment of each source line adds that
line's LineNo, and a line the optimizer did not split carries no note.
The note is written in the controller's comment grammar, so the optimized file stays legal for the control that reads it. On the Fanuc family it is parenthesized:
G01 X10.0 Y20.0 F500 (src(LineNo: 140, StepIndex: 256))
On Heidenhain it is a ; comment, because a TNC reads parentheses as code:
120 L X+35 Y-11.7 R0 F500 ;src(LineNo: 140, StepIndex: 256)
On a Heidenhain project a feed word the optimizer has to insert is also placed in the element order
a TNC enforces — after the coordinate words, after the rotation direction DR+ / DR-, and after
the radius compensation RL / RR / R0. A block that read L X+10 Y+20 RL comes back as
L X+10 Y+20 RL F500.
Tracking Individual Step Constraints
To isolate which physical quantity limits each step, disable smoothing:
OptMaxAcceleration_mmds2 = double.PositiveInfinity;
OptFeedrateAssignmentRatio = 0;
OptExtendedPreDistance_mm = 0;
OptExtendedPostDistance_mm = 0;
The four smoothing settings are what this block changes. The per-step log is already on, and
EmbeddedLogMode does not reach the pipeline that runs by default — see above.
Post-Optimization Simulation Differences
Optimized feed rates produce different interpolation points, causing:
- Different simulation mesh errors
- Surface morphology changes at the surface roughness level (more pronounced at corners)
Simulated physical quantities after optimization may be slightly above target values due to these differences.
Tip
For abnormally low optimized feed rates at corners, refer to Corner Feed Rate Optimization.
Tool Breakage Solutions
If the simulation shows yielding stress ratio, max spindle torque ratio, or max spindle power ratio above 100%, consider:
- Modify the toolpath to reduce cutting width/depth
- Use HiNC optimization to adjust feed rates, bringing these ratios below 100%
For thermal edge chipping, reduce the spindle speed to allow heat dissipation.
Complete Script Example
EnablePhysics = true;
LoadCuttingParaByFile("Material.mp");
OptEnableFeedrate = true;
OptEnableInterpolation = true;
OptRapidFeed_mmdmin = 4000;
OptMinFeedrate_mmdmin = 100;
OptMaxFeedrate_mmdmin = 4000;
OptMaxAcceleration_mmds2 = 10;
OptExtendedPreDistance_mm = 3;
OptExtendedPostDistance_mm = 2;
OptSpindlePowerSafetyFactor = 1.5;
OptSpindleTorqueSafetyFactor = 1.5;
OptThermalYieldSafetyFactor = 0;
OptPreferedForce_N = double.PositiveInfinity;
PlayNcFile("NC/file1.nc");
OptimizeToFiles("Cache/Opt-[NcName]");
WriteStepFiles("Output/[NcName].step.csv");
See Also
- NC Optimization (Concepts) — theory and objectives
- Corner Feed Rate Optimization
- Workflow: Milling Force Parameter Training — prerequisite: training cutting parameters
- Workflow: Basic Machining Simulation — basic simulation setup
- SessionShell — SessionShell quick-reference