Conversation
Fields derived from other fields need units derived from theirs, and an area-weighted sum or a product cannot simply copy them. CFUnits parses a units string in the CF plain form (m s-1, kg m-3, 1), or the udunits caret and slash spellings still used by some field definitions, into unit symbols with integer exponents; supports the product, quotient and integer power; and formats the result in the plain form with merged exponents, positive exponents first. An empty string is the unknown units of a field with no units attribute, and unknown units propagate through every operation so a derived field never claims units its inputs did not have. A malformed string is a Fail error from parse(), and the string interfaces multiply(), divide() and power() abort on it, since a bad units string is a programming error in a field definition that should stop the run at initialization. Includes a CTest covering parsing, formatting, the algebra, unknown propagation and rejected strings, and a developer-guide page. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The analysis operators registered their output fields with empty units and standard name, so every global statistic Omega wrote arrived with no units (E3SM-Project#545). A mean, minimum, maximum, standard deviation or time mean has the units and standard name of the field it reduces, and CF describes the reduction itself with a cell_methods attribute rather than a different standard name. AnalysisOperator gains helpers for this: inheritMetadata() collects an input's units, standard_name and cell_methods, each empty if the input has none, and appends the cell method of the new reduction so the attribute lists reductions in the order applied; spatialCellMethod() gives "area: <method>" for a horizontal field and "area: depth: <method>" for a layered one; createOutputField() creates the output Field with them. The five operators use these, so a time mean of a spatial mean now carries "area: depth: mean time: mean". An operator whose result has different units derives them with CFUnits before creating its output. Only the CF attribute names are read and written, and a missing attribute is treated as empty, so this works the same whether or not Field::create stores empty attributes. The operator CTest checks the attributes every operator writes, a chained time mean of a spatial mean, and that a field without units yields outputs without units. The Analysis developer's and user's guides describe the output metadata and how a new operator derives it. Fixes E3SM-Project#545 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Error::createErrMsg resumed its scan for {} placeholders at the position
of the placeholder it had just replaced, so an argument that itself
contained braces (a units string such as m^{-2}) was scanned again and
its braces taken for further placeholders, logging "Not enough arguments
for placeholders in error msg". Resume the scan after the inserted
argument instead. ErrorTest now covers an argument with braces.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
TestingCTests on chrysalis with intel and openmpi: 50/50 pass, including the new Polaris The Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly. |
@brian-oneill, is that true? I would think we would always want an area-weighted horizontal mean, so if that isn't the current case, it sounds like a bug. |
|
Need a fix for #551 before this can go in. |
The analysis operators wrote every global statistic with empty units and standard name (#545), so the Polaris global-statistics plots had no axis labels. A spatial mean, minimum, maximum, standard deviation or time mean now carries the
unitsandstandard_nameof its input and a CFcell_methodsattribute naming the reduction, chained in the order applied (area: depth: mean time: meanfor a time mean of a spatial mean).For a reviewer to decide:
area: meandoes not say. A(comment: ...)clause could; I left it out.time: meanmakes cfchecks warn thattimehas no bounds. Time bounds are a separate change (Time-mean analysis output has no time bounds #549).Operators whose result has different units (an area-weighted sum, a product) derive them with the new
CFUnitsclass; nothing ondevelopneeds that yet, but #481 does. Only the CF attribute names are read and written, so this is independent of #546.Fixes #545
Checklist
Documentation:
Linting
Building
Testing
chrysalis, intel, openmpi
Provide relevant details in a comment to the PR titled
TestingNew tests:
Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly.
🤖 Generated with Claude Code