[FEATURE] Clamp delta_time and format logs#216
Merged
Conversation
The default delta_time estimate sizes the wake ring vortices to match the bound trailing edge ring vortices, but that criterion alone does not guarantee that the motion itself is adequately sampled: a coarse chordwise discretization or a slow motion can produce a delta_time spanning a large fraction of a motion cycle. Clamp the estimate for non static Movements so that there are at least 30 time steps per LCM period. Explicit numeric delta_time values are never clamped, and while the iterative "optimize" option is seeded with the clamped estimate, its search remains deliberately unconstrained by the clamp. Move the period property computation above the delta_time resolution in Movement's initialization method, since the clamp reads the LCM period. Add unit tests covering the clamped and unclamped paths.
Replace ad-hoc round() and str() calls throughout the logging, trim, convergence, and output paths with G-format specifiers so that displayed numbers carry a consistent number of significant figures rather than a fixed decimal count. This keeps very small and very large magnitudes readable instead of collapsing to zero or sprawling across many digits. Attach explicit unit labels (s, m/s, deg, N) to the state and result messages so the logged values are unambiguous, and add spaces around the equals signs for legibility. Update the Reynolds number test regex to match the new three-significant-figure uppercase scientific notation produced by the alternate-form G specifier.
The convergence analysis logs report elapsed times in raw seconds, which reads poorly once a study runs long: a multi-hour unsteady sweep logs as tens of thousands of seconds. Add a format_duration helper to _functions.py that renders a duration as hours, minutes, and three-significant-figure seconds, dropping the leading units when they are zero, collapsing to an hours-only form at 1000 hours, carrying a seconds remainder that rounds to 60 into the minutes place, and placing the sign of a negative duration on the largest unit. Route the eight timing lines in convergence.py through the helper. They use its unpadded default; an opt-in left_pad flag can instead right-align the values of repeated log lines into a common column, with the field width sized for the widest possible form, including a three-digit float exponent in the seconds place.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR standardizes numeric formatting in logs/error messages, adds a format_duration helper for human-readable timing output, and introduces a clamp on the default delta_time estimate to ensure a minimum temporal resolution for non-static unsteady motions.
Changes:
- Added
format_duration(with optional fixed-width padding) and updated convergence timing logs to use it. - Added a minimum-resolution clamp to the analytically-estimated
delta_timeinMovement.__init__, plus unit tests covering clamped/non-clamped cases. - Converted multiple log/error-message numeric formats to a consistent
#.significant-figure style and regenerated expected example outputs.
Reviewed changes
Copilot reviewed 13 out of 65 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_movement.py | Adds unit tests for the delta_time clamp behavior (non-static vs static) and adjusts an existing mocked-value test. |
| tests/unit/test_functions.py | Adds unit tests for format_duration, including rollover and left-padding behavior. |
| tests/integration/test_output.py | Updates Reynolds-number log formatting assertion to match the new formatting convention. |
| pterasoftware/trim.py | Standardizes trim-state logging numeric formatting and adds explicit units in the log message. |
| pterasoftware/problems.py | Updates free-flight sub-iteration residual logging to consistent significant-figure formatting. |
| pterasoftware/output.py | Standardizes numeric formatting in logged results and scalar-plot labels/colorbar formatting. |
| pterasoftware/movements/movement.py | Introduces minimum time-steps-per-LCM-period clamp for analytical delta_time estimates and updates optimization logging formatting. |
| pterasoftware/geometry/airfoil.py | Updates an airfoil normalization error message to the new formatting convention. |
| pterasoftware/convergence.py | Routes convergence timing lines through format_duration and standardizes convergence metric formatting. |
| pterasoftware/_oscillation.py | Standardizes validation error message formatting for custom spacing functions. |
| pterasoftware/_functions.py | Adds format_duration and _DURATION_PAD_WIDTH to centralize duration formatting for logs. |
| pterasoftware/_convergence_meshing.py | Standardizes delta_time cache/optimization log formatting. |
| pterasoftware/_aerodynamics_functions.py | Adds targeted mypy ignores for prange false positives with an explanatory comment. |
| docs/examples_expected_output/unsteady_static_convergence/example_convergence.log | Regenerates expected log output to reflect new numeric and duration formatting. |
| docs/examples_expected_output/unsteady_ring_vortex_lattice_method_solver_static/example_solver.log | Regenerates expected log output to reflect new numeric formatting. |
| docs/examples_expected_output/unsteady_ring_vortex_lattice_method_solver_static_ground_effect/example_solver.log | Regenerates expected log output to reflect new numeric formatting. |
| docs/examples_expected_output/steady_ring_vortex_lattice_method_solver/example_solver.log | Regenerates expected log output to reflect new numeric formatting (including Reynolds number). |
| docs/examples_expected_output/steady_ring_vortex_lattice_method_solver_non_trapezoidal/example_solver.log | Regenerates expected log output to reflect new numeric formatting (including Reynolds number). |
| docs/examples_expected_output/steady_horseshoe_vortex_lattice_method_solver/example_solver.log | Regenerates expected log output to reflect new numeric formatting (including Reynolds number). |
| docs/examples_expected_output/steady_convergence/example_convergence.log | Regenerates expected convergence log output to reflect new duration/metric formatting. |
| docs/examples_expected_output/free_flight_unsteady_ring_vortex_lattice_method_solver_glider/example_solver.log | Regenerates expected free-flight log output to reflect new numeric/time formatting. |
| docs/examples_expected_output/free_flight_unsteady_ring_vortex_lattice_method_solver_flapping/example_solver.log | Regenerates expected free-flight log output to reflect new numeric/time formatting. |
| docs/examples_expected_output/analyze_unsteady_trim/example_trim.log | Regenerates expected trim log output to reflect new numeric formatting and units in state logs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #216 +/- ##
==========================================
+ Coverage 93.69% 93.72% +0.02%
==========================================
Files 44 44
Lines 8473 8504 +31
==========================================
+ Hits 7939 7970 +31
Misses 534 534 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR standardizes numeric formatting across the log output and error messages, adds a
format_durationhelper for human-readable timing lines, and clamps the defaultdelta_timeestimate so that unsteady motions are always resolved with a minimum temporal fidelity. The formatting changes are cosmetic and do not affect any computed result. Thedelta_timeclamp only lowers an estimate that was too coarse, so existing simulations that already met the resolution floor, or that pass an explicitdelta_time, are unaffected.Motivation
The solver, convergence, and trim logs mixed several ad hoc rounding styles (
round(x, 2),np.round(x, 3),%g,%.2e), which produced inconsistent precision and hard-to-scan columns. A single three-significant-figure convention (with four significant figures reserved for the convergence metric percentages) makes the output uniform and easier to read. Separately, the analyticaldelta_timeestimate matches wake and bound ring vortex chord lengths, which does not by itself guarantee the motion is sampled finely enough in time: a coarse chordwise discretization or a slow motion can leave the estimate too large to resolve the flapping cycle. Clamping to at least 30 time steps per LCM period guards against that failure mode without changing well-resolved cases.Relevant Issues
None.
Changes
format_durationand its_DURATION_PAD_WIDTHconstant to_functions.py, formatting a duration as hours, minutes, and seconds with three significant figures, optional left-padding for aligned log columns, and carry handling for a seconds remainder that rounds up to 60.delta_timeestimate inMovement.__init__to at most_lcm_period / _MIN_TIME_STEPS_PER_LCM_PERIOD(30 steps per LCM period) for non-static movements, moving the local period computation ahead of thedelta_timeresolution block and updating thedelta_time_typedocstring.#.3Gspecifier (and#.4Gfor the convergence metric percentages) acrossconvergence.py,trim.py,output.py,_oscillation.py,_convergence_meshing.py,movements/movement.py, andgeometry/airfoil.py, and switched the free flight sub-iteration log strings inproblems.pyto%#.3G; convergence timing lines now route throughformat_duration.# type: ignore[attr-defined]with an explanatory comment to the twoprangeloops in_aerodynamics_functions.pyto suppress mypy false positives arising from Numba's unannotatedprange.__new__.format_durationintests/unit/test_functions.pyand thedelta_timeclamp intests/unit/test_movement.py, adjusted a scalar-rounding assertion intests/integration/test_output.py, and regenerated the affected example logs, plots, and animations underdocs/examples_expected_output/.Dependency Updates
None.
Change Magnitude
Minor: Small change such as a bug fix, small enhancement, or documentation update.
Checklist (check each item when completed or not applicable)
mainand is up to date with the upstreammainbranch.--in-place --black). See the style guide for type hints and docstrings for more details.pterasoftwarepackage use type hints. See the style guide for type hints and docstrings for more details.testspackage.testspackage.ascii-only,black,codespell,docformatter,isort, andpre-commit-hooksGitHub actions.mypyGitHub action.testsGitHub actions.