From cb6eebd0a9fd044d9dd9e43978719f8ba5e2d0fd Mon Sep 17 00:00:00 2001 From: Shunichiro Nomura Date: Sun, 16 Aug 2026 01:52:57 +0900 Subject: [PATCH 1/3] Add source-backed engineering projects --- corpus.toml | 118 ++++++++++++++++++ .../README.md | 5 + .../graphcal.toml | 2 + .../reference/calculation.md | 84 +++++++++++++ .../main.gcl | 36 ++++++ projects/nasa-lift-sweep/README.md | 5 + projects/nasa-lift-sweep/graphcal.toml | 2 + .../nasa-lift-sweep/reference/calculation.md | 58 +++++++++ .../src/nasa_lift_sweep/main.gcl | 24 ++++ projects/pvwatts-hourly-dc-energy/README.md | 5 + .../pvwatts-hourly-dc-energy/graphcal.toml | 2 + .../reference/calculation.md | 57 +++++++++ .../src/pvwatts_hourly_dc_energy/main.gcl | 37 ++++++ 13 files changed, 435 insertions(+) create mode 100644 projects/fao56-reference-evapotranspiration/README.md create mode 100644 projects/fao56-reference-evapotranspiration/graphcal.toml create mode 100644 projects/fao56-reference-evapotranspiration/reference/calculation.md create mode 100644 projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl create mode 100644 projects/nasa-lift-sweep/README.md create mode 100644 projects/nasa-lift-sweep/graphcal.toml create mode 100644 projects/nasa-lift-sweep/reference/calculation.md create mode 100644 projects/nasa-lift-sweep/src/nasa_lift_sweep/main.gcl create mode 100644 projects/pvwatts-hourly-dc-energy/README.md create mode 100644 projects/pvwatts-hourly-dc-energy/graphcal.toml create mode 100644 projects/pvwatts-hourly-dc-energy/reference/calculation.md create mode 100644 projects/pvwatts-hourly-dc-energy/src/pvwatts_hourly_dc_energy/main.gcl diff --git a/corpus.toml b/corpus.toml index 4dd83ac..eb13c06 100644 --- a/corpus.toml +++ b/corpus.toml @@ -55,3 +55,121 @@ evidence = "reference/calculation.md" pointer = "/node/mass_ratio/si_value" expected = 10.0 absolute_tolerance = 1.0 +[[projects]] +id = "nasa-lift-sweep" +path = "projects/nasa-lift-sweep" +status = "active" +domain = "aerodynamics" +origin = "source-backed" +purpose = "Verify dynamic pressure, lift, and inverse speed against NASA's lift equation." + +[[projects.cases]] +id = "three-flight-points" +entry = "src/nasa_lift_sweep/main.gcl" + +[projects.cases.expectation] +kind = "reference-backed" +evidence = "reference/calculation.md" + +[[projects.cases.expectation.assertions]] +pointer = "/node/cruise_dynamic_pressure/si_value" +expected = 980.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/cruise_lift/si_value" +expected = 12700.8 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/maximum_lift/si_value" +expected = 19845.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/level_flight_speed/si_value" +expected = 38.88078956798696 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/maximum_lift/unit" +expected = "kN" + +[[projects]] +id = "pvwatts-hourly-dc-energy" +path = "projects/pvwatts-hourly-dc-energy" +status = "active" +domain = "solar-energy" +origin = "source-backed" +purpose = "Verify an hourly DC-energy calculation against the PVWatts Version 5 module model." + +[[projects.cases]] +id = "four-hour-profile" +entry = "src/pvwatts_hourly_dc_energy/main.gcl" + +[projects.cases.expectation] +kind = "reference-backed" +evidence = "reference/calculation.md" + +[[projects.cases.expectation.assertions]] +pointer = "/node/low_sun_dc_power/si_value" +expected = 1040.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/peak_dc_power/si_value" +expected = 4600.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/total_dc_energy/si_value" +expected = 38016000.0 +absolute_tolerance = 1e-6 + +[[projects.cases.expectation.assertions]] +pointer = "/node/peak_dc_power/unit" +expected = "kW" + +[[projects.cases.expectation.assertions]] +pointer = "/node/total_dc_energy/unit" +expected = "kWh" + +[[projects]] +id = "fao56-reference-evapotranspiration" +path = "projects/fao56-reference-evapotranspiration" +status = "active" +domain = "agricultural-water-management" +origin = "source-backed" +purpose = "Reproduce the FAO-56 Example 18 daily reference evapotranspiration result." + +[[projects.cases]] +id = "example-18" +entry = "src/fao56_reference_evapotranspiration/main.gcl" + +[projects.cases.expectation] +kind = "reference-backed" +evidence = "reference/calculation.md" + +[[projects.cases.expectation.assertions]] +pointer = "/node/radiation_component/si_value" +expected = 3.2466022318476985e-8 +absolute_tolerance = 1e-18 + +[[projects.cases.expectation.assertions]] +pointer = "/node/aerodynamic_component/si_value" +expected = 1.2429119836677152e-8 +absolute_tolerance = 1e-18 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reference_evapotranspiration/si_value" +expected = 4.489514215515413e-8 +absolute_tolerance = 1e-18 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_reference_evapotranspiration/si_value" +expected = 4.5138888888888884e-8 +absolute_tolerance = 1e-18 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_reference_evapotranspiration/unit" +expected = "mm_per_day" diff --git a/projects/fao56-reference-evapotranspiration/README.md b/projects/fao56-reference-evapotranspiration/README.md new file mode 100644 index 0000000..7e4d575 --- /dev/null +++ b/projects/fao56-reference-evapotranspiration/README.md @@ -0,0 +1,5 @@ +# FAO-56 daily reference evapotranspiration + +This source-backed reproduction asks: **Does the FAO Penman–Monteith equation reproduce the daily reference evapotranspiration reported in FAO-56 Example 18?** + +It evaluates Equation 6 from the rounded intermediate meteorological values published for the example and reports the result to 0.1 mm/day. Celsius is handled explicitly as a normalized numeric value while physical temperatures remain kelvin quantities. The source comparison, assumptions, unit adaptation, and independent calculation are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/fao56-reference-evapotranspiration/graphcal.toml b/projects/fao56-reference-evapotranspiration/graphcal.toml new file mode 100644 index 0000000..78f39c5 --- /dev/null +++ b/projects/fao56-reference-evapotranspiration/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "fao56_reference_evapotranspiration" diff --git a/projects/fao56-reference-evapotranspiration/reference/calculation.md b/projects/fao56-reference-evapotranspiration/reference/calculation.md new file mode 100644 index 0000000..574d486 --- /dev/null +++ b/projects/fao56-reference-evapotranspiration/reference/calculation.md @@ -0,0 +1,84 @@ +# Independent FAO-56 reference-evapotranspiration calculation + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction. The agent selected the cited public worked example, wrote an original Graphcal reproduction from its formula and rounded intermediate values, and performed the separate calculation below. It does not derive from a private project. Human source, privacy, calculation, and promotion review remain pull-request responsibilities. + +## Source + +R. G. Allen, L. S. Pereira, D. Raes, and M. Smith, *Crop Evapotranspiration: Guidelines for Computing Crop Water Requirements*, FAO Irrigation and Drainage Paper 56, Food and Agriculture Organization of the United Nations, Rome, 1998, Chapter 4, Equation 6 and Example 18, https://www.fao.org/4/x0490e/x0490e08.htm, accessed 2026-08-15. + +For a daily time step, the FAO Penman–Monteith equation is + +\[ +ET_0 = +\frac{ +0.408\,\Delta(R_n-G) ++ \gamma\frac{900}{T+273}u_2(e_s-e_a) +}{ +\Delta+\gamma(1+0.34u_2) +}. +\] + +Under the equation's stated conventional units, the result is millimetres per day. Example 18 reports 3.88 mm/day before presenting the result as 3.9 mm/day. + +## Reproduced inputs and adaptations + +This project begins from the rounded intermediate values printed in Example 18: + +- mean air temperature \(T=16.9\ ^\circ\mathrm{C}\); +- wind speed at 2 m \(u_2=2.078\ \mathrm{m/s}\); +- slope of the vapour-pressure curve \(\Delta=0.122\ \mathrm{kPa/K}\); +- psychrometric constant \(\gamma=0.0666\ \mathrm{kPa/K}\); +- vapour-pressure deficit \(e_s-e_a=0.589\ \mathrm{kPa}\); +- net radiation \(R_n=13.28\ \mathrm{MJ/(m^2\,day)}\); +- daily soil heat flux \(G=0\ \mathrm{MJ/(m^2\,day)}\). + +The example's intermediate values are already rounded, so this is a reproduction of its final Equation 6 calculation, not a recomputation from the raw weather observations. + +Graphcal intentionally has no affine Celsius unit. The model stores 16.9 °C as 290.05 K and explicitly computes the Celsius numeric value as \((T_K-273.15\,K)/(1\,K)\) before using the empirical \(T+273\) term. Temperature differences in \(\Delta\) and \(\gamma\) use kelvin because one kelvin and one degree Celsius have the same interval size. + +The empirical equation combines values expressed in prescribed conventional units. The Graphcal model makes each normalization explicit, computes the conventional numerical terms dimensionlessly, and attaches the physical output unit mm/day. + +## Independent calculation + +Using the published rounded values with ordinary binary64 arithmetic, independently of Graphcal: + +\[ +D = 0.122 + 0.0666(1+0.34(2.078)) + = 0.23565423200000002. +\] + +Radiation component: + +\[ +ET_{rad} = \frac{0.408(13.28)(0.122)}{D} + = 2.805064328316411\ \mathrm{mm/day}. +\] + +Aerodynamic component: + +\[ +ET_{aero} = +\frac{0.0666\,[900/(16.9+273)](2.078)(0.589)}{D} +=1.073875953888906\ \mathrm{mm/day}. +\] + +Therefore: + +\[ +ET_0=3.878940282205317\ \mathrm{mm/day}, +\] + +which rounds to 3.9 mm/day and agrees with the reported Example 18 result. Using \(1\ \mathrm{mm/day}=10^{-3}/86400\ \mathrm{m/s}\), the corresponding SI values are: + +- radiation component: 3.2466022318476985 × 10⁻⁸ m/s; +- aerodynamic component: 1.2429119836677152 × 10⁻⁸ m/s; +- unrounded total: 4.489514215515413 × 10⁻⁸ m/s; +- reported 3.9 mm/day: 4.5138888888888884 × 10⁻⁸ m/s. + +The manifest checks these SI values with narrowly scoped tolerances and checks the displayed mm/day unit exactly. + +## Licensing and adaptation + +Only the equation and the small set of numerical facts needed to reproduce the cited worked example are used. No FAO prose, figures, calculation-sheet layout, software, or data files are copied. The Graphcal implementation and this explanation are original corpus content under the repository license; the FAO publication is cited for provenance and is not relicensed here. diff --git a/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl b/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl new file mode 100644 index 0000000..91f8b71 --- /dev/null +++ b/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl @@ -0,0 +1,36 @@ +const unit day: Time = 24.0 h; +const unit MJ: Energy = 1000.0 kJ; +const unit mm_per_day: Velocity = 1.0 mm/day; +const unit MJ_per_square_metre_day: Power / Area = 1.0 MJ/m^2/day; +const unit kPa_per_K: Pressure / Temperature = 1.0 kPa/K; + +param mean_air_temperature: Temperature = 290.05 K; +param wind_speed_2m: Velocity = 2.078 m/s; +param slope_vapour_pressure_curve: Pressure / Temperature = 0.122 kPa_per_K; +param psychrometric_constant: Pressure / Temperature = 0.0666 kPa_per_K; +param vapour_pressure_deficit: Pressure = 0.589 kPa; +param net_radiation_flux: Power / Area = 13.28 MJ_per_square_metre_day; +param soil_heat_flux: Power / Area = 0.0 MJ_per_square_metre_day; + +const node reporting_increment: Velocity = 0.1 mm_per_day; + +node mean_air_temperature_celsius_value: Dimensionless = (@mean_air_temperature - 273.15 K) / 1.0 K; +node normalized_wind_speed: Dimensionless = @wind_speed_2m / 1.0 m/s; +node normalized_slope: Dimensionless = @slope_vapour_pressure_curve / 1.0 kPa_per_K; +node normalized_psychrometric_constant: Dimensionless = @psychrometric_constant / 1.0 kPa_per_K; +node normalized_vapour_pressure_deficit: Dimensionless = @vapour_pressure_deficit / 1.0 kPa; +node normalized_available_radiation: Dimensionless = ( + @net_radiation_flux - @soil_heat_flux +) / 1.0 MJ_per_square_metre_day; +node denominator: Dimensionless = @normalized_slope + @normalized_psychrometric_constant * ( + 1.0 + 0.34 * @normalized_wind_speed +); + +node radiation_component: Velocity = 0.408 * @normalized_available_radiation * @normalized_slope / @denominator * 1.0 mm_per_day -> mm_per_day; +node aerodynamic_component: Velocity = @normalized_psychrometric_constant * ( + 900.0 / (@mean_air_temperature_celsius_value + 273.0) +) * @normalized_wind_speed * @normalized_vapour_pressure_deficit / @denominator * 1.0 mm_per_day -> mm_per_day; +node reference_evapotranspiration: Velocity = @radiation_component + @aerodynamic_component -> mm_per_day; +node reported_reference_evapotranspiration: Velocity = round( + @reference_evapotranspiration / @reporting_increment +) * @reporting_increment -> mm_per_day; diff --git a/projects/nasa-lift-sweep/README.md b/projects/nasa-lift-sweep/README.md new file mode 100644 index 0000000..585054d --- /dev/null +++ b/projects/nasa-lift-sweep/README.md @@ -0,0 +1,5 @@ +# NASA lift-equation sweep + +This source-backed reproduction asks: **What dynamic pressure and lift result at three low-speed flight points, and what speed produces a required lift?** + +It applies the lift and dynamic-pressure equations presented by NASA Glenn Research Center to a fixed set of original, illustrative inputs. The lift coefficient is held constant, so this is a point calculation rather than an aerodynamic prediction across changing Reynolds or Mach number. The asserted values and independent calculation are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/nasa-lift-sweep/graphcal.toml b/projects/nasa-lift-sweep/graphcal.toml new file mode 100644 index 0000000..a1286fe --- /dev/null +++ b/projects/nasa-lift-sweep/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "nasa_lift_sweep" diff --git a/projects/nasa-lift-sweep/reference/calculation.md b/projects/nasa-lift-sweep/reference/calculation.md new file mode 100644 index 0000000..0433c1c --- /dev/null +++ b/projects/nasa-lift-sweep/reference/calculation.md @@ -0,0 +1,58 @@ +# Independent NASA lift-equation calculation + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction. The agent selected the cited public formula, chose original illustrative inputs, wrote an original Graphcal reproduction, and performed the separate calculation below. It does not derive from a private project. Human source, privacy, calculation, and promotion review remain pull-request responsibilities. + +## Source + +NASA Glenn Research Center, “Lift Coefficient,” *Beginner's Guide to Aeronautics*, https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/lift-coefficient/, accessed 2026-08-15. + +NASA states that dynamic pressure and lift coefficient satisfy + +\[ +q = \frac{1}{2}\rho V^2, \qquad C_l = \frac{L}{qA}. +\] + +Rearranging the second equation gives \(L=C_l qA\). Solving the combined equation for the speed that produces a specified lift gives + +\[ +V = \sqrt{\frac{2L}{\rho A C_l}}. +\] + +The source cautions that a lift coefficient carries shape, viscosity, and compressibility effects. This reproduction deliberately holds it constant and uses low-speed points; it does not model those effects. + +## Adapted inputs + +These values are illustrative inputs created for this corpus project, not a copied NASA example: + +- air density: 1.225 kg/m³; +- wing area: 16.2 m²; +- lift coefficient: 0.8; +- airspeeds: 30, 40, and 50 m/s; +- required lift for the inverse calculation: 12,000 N. + +The model assumes steady conditions and uses one constant density, area, and lift coefficient at every flight point. + +## Independent calculation + +Using the formulas above with ordinary binary64 arithmetic, independently of Graphcal: + +| Speed (m/s) | \(q=\rho V^2/2\) (Pa) | \(L=C_lqA\) (N) | +|---:|---:|---:| +| 30 | 551.25 | 7,144.2 | +| 40 | 980.0 | 12,700.8 | +| 50 | 1,531.25 | 19,845.0 | + +For the required-lift calculation: + +\[ +V = \sqrt{\frac{2(12000)}{(1.225)(16.2)(0.8)}} + = 38.88078956798696\ \text{m/s}. +\] + +The manifest checks the 40 m/s dynamic pressure, the 40 m/s lift, the maximum sweep lift, and the inverse speed. Absolute tolerances of 1 × 10⁻⁹ in each asserted SI value allow only last-bit floating-point differences. + +## Licensing and adaptation + +The equations were reimplemented from the cited NASA educational page. No source prose, figures, software, or data files are reproduced. All numerical inputs and explanatory text in this project are original corpus material under the repository license; the NASA page is cited for provenance and is not relicensed here. diff --git a/projects/nasa-lift-sweep/src/nasa_lift_sweep/main.gcl b/projects/nasa-lift-sweep/src/nasa_lift_sweep/main.gcl new file mode 100644 index 0000000..fa4861d --- /dev/null +++ b/projects/nasa-lift-sweep/src/nasa_lift_sweep/main.gcl @@ -0,0 +1,24 @@ +pub index FlightPoint = { Approach, Cruise, Fast }; + +param air_density: Mass / Volume = 1.225 kg/m^3; +param wing_area: Area = 16.2 m^2; +param lift_coefficient: Dimensionless = 0.8; +param airspeed: Velocity[FlightPoint] = { + FlightPoint.Approach: 30.0 m/s, + FlightPoint.Cruise: 40.0 m/s, + FlightPoint.Fast: 50.0 m/s, +}; +param required_lift: Force = 12.0 kN; + +node dynamic_pressure: Pressure[FlightPoint] = for point: FlightPoint { + 0.5 * @air_density * @airspeed[point] ^ 2 +}; +node lift_force: Force[FlightPoint] = for point: FlightPoint { + @lift_coefficient * @dynamic_pressure[point] * @wing_area +}; +node cruise_dynamic_pressure: Pressure = @dynamic_pressure[FlightPoint.Cruise] -> Pa; +node cruise_lift: Force = @lift_force[FlightPoint.Cruise] -> kN; +node maximum_lift: Force = maximum(@lift_force) -> kN; +node level_flight_speed: Velocity = sqrt( + 2.0 * @required_lift / (@air_density * @wing_area * @lift_coefficient) +); diff --git a/projects/pvwatts-hourly-dc-energy/README.md b/projects/pvwatts-hourly-dc-energy/README.md new file mode 100644 index 0000000..e57f341 --- /dev/null +++ b/projects/pvwatts-hourly-dc-energy/README.md @@ -0,0 +1,5 @@ +# PVWatts hourly DC energy + +This source-backed reproduction asks: **How much DC energy does a 5 kW photovoltaic array produce over four one-hour conditions when the PVWatts module model is applied?** + +It reproduces only the PVWatts Version 5 DC module equation. Effective plane-of-array irradiance and cell temperature are already prepared inputs; the project does not model weather, optical losses, cell temperature, inverter conversion, clipping, or AC output. The asserted powers and energy are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/pvwatts-hourly-dc-energy/graphcal.toml b/projects/pvwatts-hourly-dc-energy/graphcal.toml new file mode 100644 index 0000000..5faa3bd --- /dev/null +++ b/projects/pvwatts-hourly-dc-energy/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "pvwatts_hourly_dc_energy" diff --git a/projects/pvwatts-hourly-dc-energy/reference/calculation.md b/projects/pvwatts-hourly-dc-energy/reference/calculation.md new file mode 100644 index 0000000..88d4383 --- /dev/null +++ b/projects/pvwatts-hourly-dc-energy/reference/calculation.md @@ -0,0 +1,57 @@ +# Independent PVWatts hourly DC-energy calculation + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction. The agent selected the cited public model, created a small deterministic set of illustrative operating points, wrote an original Graphcal reproduction, and performed the separate calculation below. It does not derive from a private project. Human source, privacy, calculation, and promotion review remain pull-request responsibilities. + +## Source + +A. P. Dobos, *PVWatts Version 5 Manual*, National Renewable Energy Laboratory, NREL/TP-6A20-62641, September 2014, Section 10, Equation 8, DOI [10.2172/1158421](https://doi.org/10.2172/1158421), https://www.osti.gov/biblio/1158421, accessed 2026-08-15. + +The report defines the DC module model as + +\[ +P_{dc}=\frac{I_{tr}}{1000}P_{dc0} + \left[1+\gamma(T_{cell}-T_{ref})\right], +\] + +where the reference irradiance is 1,000 W/m² and the reference cell temperature is 25 °C. A temperature difference of one degree Celsius is one kelvin, so the coefficient is represented as K⁻¹ and temperatures are stored as absolute kelvin values in Graphcal. + +## Adapted inputs + +The 5 kW nameplate rating, coefficient, and four operating points are original illustrative corpus inputs rather than copied weather or system data: + +| Period | Effective irradiance (W/m²) | Cell temperature (°C / K) | Duration (h) | +|---|---:|---:|---:| +| Low sun | 200 | 15 / 288.15 | 1 | +| Mid-morning | 600 | 25 / 298.15 | 1 | +| Solar noon | 1,000 | 45 / 318.15 | 1 | +| Afternoon | 400 | 35 / 308.15 | 1 | + +Other inputs are \(P_{dc0}=5\) kW, \(\gamma=-0.004\ \text{K}^{-1}\), \(I_{ref}=1000\) W/m², and \(T_{ref}=298.15\) K. + +This project starts at transmitted/effective irradiance and supplied cell temperature. It does not reproduce the other PVWatts submodels or calculate AC energy. + +## Independent calculation + +Applying Equation 8 independently of Graphcal: + +| Period | Irradiance factor | Temperature factor | DC power (kW) | DC energy (kWh) | +|---|---:|---:|---:|---:| +| Low sun | 0.2 | \(1+(-0.004)(15-25)=1.04\) | 1.04 | 1.04 | +| Mid-morning | 0.6 | 1.00 | 3.00 | 3.00 | +| Solar noon | 1.0 | \(1+(-0.004)(45-25)=0.92\) | 4.60 | 4.60 | +| Afternoon | 0.4 | \(1+(-0.004)(35-25)=0.96\) | 1.92 | 1.92 | + +Therefore: + +\[ +E_{dc}=1.04+3.00+4.60+1.92=10.56\ \text{kWh} + =38{,}016{,}000\ \text{J}. +\] + +The manifest checks low-sun power (1,040 W), peak power (4,600 W), total energy (38,016,000 J), and the selected display units. The narrow tolerances permit only floating-point evaluation differences. + +## Licensing and adaptation + +The equation was reimplemented from the cited NREL technical report. No report prose, figures, software, or datasets are reproduced. The operating points, source, and calculation record are original corpus content under the repository license; the report is cited for provenance and is not relicensed here. diff --git a/projects/pvwatts-hourly-dc-energy/src/pvwatts_hourly_dc_energy/main.gcl b/projects/pvwatts-hourly-dc-energy/src/pvwatts_hourly_dc_energy/main.gcl new file mode 100644 index 0000000..ada4d3c --- /dev/null +++ b/projects/pvwatts-hourly-dc-energy/src/pvwatts_hourly_dc_energy/main.gcl @@ -0,0 +1,37 @@ +const unit kWh: Energy = 1.0 kW * h; + +pub index Period = { LowSun, MidMorning, SolarNoon, Afternoon }; + +param nameplate_dc_power: Power = 5.0 kW; +param effective_irradiance: Power / Area[Period] = { + Period.LowSun: 200.0 W/m^2, + Period.MidMorning: 600.0 W/m^2, + Period.SolarNoon: 1000.0 W/m^2, + Period.Afternoon: 400.0 W/m^2, +}; +param cell_temperature: Temperature[Period] = { + Period.LowSun: 288.15 K, + Period.MidMorning: 298.15 K, + Period.SolarNoon: 318.15 K, + Period.Afternoon: 308.15 K, +}; +param temperature_coefficient: Temperature^-1 = -0.004 1/K; +param interval_duration: Time = 1.0 h; + +const node reference_irradiance: Power / Area = 1000.0 W/m^2; +const node reference_cell_temperature: Temperature = 298.15 K; + +node temperature_factor: Dimensionless[Period] = for period: Period { + 1.0 + @temperature_coefficient * (@cell_temperature[period] - @reference_cell_temperature) +}; +node dc_power: Power[Period] = for period: Period { + @nameplate_dc_power * ( + @effective_irradiance[period] / @reference_irradiance + ) * @temperature_factor[period] +}; +node interval_dc_energy: Energy[Period] = for period: Period { + @dc_power[period] * @interval_duration +}; +node low_sun_dc_power: Power = @dc_power[Period.LowSun] -> kW; +node peak_dc_power: Power = maximum(@dc_power) -> kW; +node total_dc_energy: Energy = sum(@interval_dc_energy) -> kWh; From b90633f59c76522a0f736352dd5681e3eb505601 Mon Sep 17 00:00:00 2001 From: Shunichiro Nomura Date: Sun, 16 Aug 2026 02:17:03 +0900 Subject: [PATCH 2/3] Clarify source-backed evidence and add published examples --- .github/pull_request_template.md | 4 +- CONTRIBUTING.md | 26 +-- README.md | 8 +- corpus.toml | 144 +++++++++------- projects/epa-chp-savings-example/README.md | 5 + .../epa-chp-savings-example/graphcal.toml | 2 + .../reference/calculation.md | 46 ++++++ .../src/epa_chp_savings_example/main.gcl | 17 ++ .../README.md | 2 +- .../reference/calculation.md | 82 ++++----- .../main.gcl | 16 +- projects/nasa-lift-sweep/README.md | 4 +- .../expected/three-flight-points.json | 98 +++++++++++ .../nasa-lift-sweep/reference/baseline.md | 43 +++++ .../nasa-lift-sweep/reference/calculation.md | 58 ------- projects/nws-heat-index-examples/README.md | 5 + .../nws-heat-index-examples/graphcal.toml | 2 + .../reference/calculation.md | 45 +++++ .../src/nws_heat_index_examples/main.gcl | 19 +++ projects/pvwatts-hourly-dc-energy/README.md | 4 +- .../expected/four-hour-profile.json | 156 ++++++++++++++++++ .../reference/baseline.md | 43 +++++ .../reference/calculation.md | 57 ------- schema/README.md | 12 +- 24 files changed, 639 insertions(+), 259 deletions(-) create mode 100644 projects/epa-chp-savings-example/README.md create mode 100644 projects/epa-chp-savings-example/graphcal.toml create mode 100644 projects/epa-chp-savings-example/reference/calculation.md create mode 100644 projects/epa-chp-savings-example/src/epa_chp_savings_example/main.gcl create mode 100644 projects/nasa-lift-sweep/expected/three-flight-points.json create mode 100644 projects/nasa-lift-sweep/reference/baseline.md delete mode 100644 projects/nasa-lift-sweep/reference/calculation.md create mode 100644 projects/nws-heat-index-examples/README.md create mode 100644 projects/nws-heat-index-examples/graphcal.toml create mode 100644 projects/nws-heat-index-examples/reference/calculation.md create mode 100644 projects/nws-heat-index-examples/src/nws_heat_index_examples/main.gcl create mode 100644 projects/pvwatts-hourly-dc-energy/expected/four-hour-profile.json create mode 100644 projects/pvwatts-hourly-dc-energy/reference/baseline.md delete mode 100644 projects/pvwatts-hourly-dc-energy/reference/calculation.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0bbd026..ee6e74b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,11 +8,11 @@ - [ ] I performed a human privacy review and found no private project names, paths, source text, inputs, or results. - [ ] I confirmed that all included material may be redistributed. - [ ] I classified each expectation as reference-backed, stability-baseline, or health-only. -- [ ] I independently verified reference-backed assertions without relying solely on Graphcal output. +- [ ] I mapped every reference-backed expected value directly to a value reported by a reliable public source. - [ ] I recorded producing revisions, comparison rules, and repeated-run determinism for stability baselines. - [ ] I recorded candidate-generation and human-review provenance. - [ ] I ran `uv run validate-corpus` and `uv run -m pytest`. ## Evidence - + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 24d2ef4..9df21ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,16 @@ # Contributing to the Graphcal QA Corpus -Contributions are welcome when they add independently traceable correctness evidence or original, realistic Graphcal complexity without exposing private material. +Contributions are welcome when they add directly source-traceable correctness evidence or original, realistic Graphcal complexity without exposing private material. ## Candidate requirements A candidate must be either: -1. a **source-backed reproduction** reimplemented from a reliable, redistributable published or well-known analysis; or +1. a **source-backed reproduction** for which a reliable, redistributable public source supplies both the reproduced inputs and the expected output values; or 2. an **original synthetic complexity project** created without copying or transforming a private user project. +A project that applies a published equation to original or adapted inputs is original synthetic unless the source also reports the corresponding output. Such a case may cite the equation, but its Graphcal-produced output must be classified as a stability baseline. + Do not submit a candidate merely because the current Graphcal implementation accepts it. Each project must answer a stated engineering question, exercise a documented feature or domain gap, and use deterministic checked-in inputs. Initial corpus projects must not require network access, private or unpinned dependencies, native or WASM plugins, current time, randomness, or project-provided executable hooks. @@ -19,7 +21,7 @@ Initial corpus projects must not require network access, private or unpinned dep 2. **Perform privacy review.** Apply [PRIVACY.md](PRIVACY.md) to names, paths, comments, source, inputs, expected outputs, references, and history. Agent generation and automated scanning do not replace human inspection. 3. **Check structure.** Put the project at `projects//`, add `graphcal.toml`, declare the project and all QA cases in `corpus.toml`, and run `uv run validate-corpus`. 4. **Classify every expectation.** Use `reference-backed`, `stability-baseline`, or `health-only` according to the evidence described below. Do not present stability output as a correctness oracle. -5. **Verify evidence.** Independently check reference-backed assertions. Capture provenance and repeated-run determinism for stability baselines. +5. **Verify evidence.** Trace every reference-backed expected value to the exact public source location that reports it. Capture producing revisions and repeated-run determinism for stability baselines. 6. **Submit a pull request.** Explain the project's origin, purpose, coverage, evidence, licensing, and privacy review. 7. **Obtain human review.** At least one human other than the latest contributor must review the structural, technical, provenance, expectation, and privacy evidence before merge. @@ -29,20 +31,20 @@ Coding-agent output remains an untrusted candidate until this process is complet ### Reference-backed -A reference-backed assertion must be supported by at least one of: +A reference-backed assertion requires a reliable public source that reports both: + +- the inputs and assumptions reproduced by the case; and +- the expected numerical or scalar output asserted by the manifest. -- an analytical calculation; -- a separately implemented reference calculation; -- a reliable published example with compatible assumptions; or -- manual verification by a domain expert. +The evidence must map each JSON Pointer and expected value to an exact source location such as a worked example, report table, published test vector, or source-maintained reference output. Assert only the precision the source reports. Document any source-prescribed rounding and any lossless unit or representation conversion. -Do not bless a value solely because `graphcal eval` produced it. Document formulas, assumptions, constants, sign and unit conventions, copied input data, adaptations, tolerances, and the independent result in `reference/calculation.md` or an equivalent non-executable record. +An analytical calculation, separately implemented calculation, domain-expert review, or agreement with `graphcal eval` may corroborate a published value, but none is sufficient as the sole oracle. If a source publishes an equation but no output for the case's inputs, classify the case as `stability-baseline`, not `reference-backed`. -For a published source, include enough bibliographic detail to identify the exact example: author or organization, title, edition or version, page or section, DOI or stable URL when available, and access date where useful. Reimplement the analysis; do not copy copyrighted prose, figures, or substantial tables. Record the license and origin of any included third-party data. +Include enough bibliographic detail to identify the exact example: author or organization, title, edition or version, page, table, equation, or section, DOI or stable URL when available, and access date where useful. Reimplement the analysis; do not copy copyrighted prose, figures, or substantial tables. Record the license and origin of any included third-party data. ### Stability baseline -A stability baseline detects behavioral drift and does not establish engineering correctness. Record: +A stability baseline detects behavioral drift and does not establish engineering correctness. Use it for original synthetic cases and source-informed cases whose references provide equations or methods but no expected values for the reproduced inputs. Record: - the exact Graphcal commit that produced it; - the corpus candidate commit and case inputs; @@ -78,7 +80,7 @@ A project pull request must confirm that: - [ ] all included source material and data may be redistributed; - [ ] the project is explicitly declared and structural validation passes; - [ ] every expectation has the correct evidence class; -- [ ] every reference-backed assertion was independently verified; +- [ ] every reference-backed assertion maps directly to a value reported by a reliable public source; - [ ] every stability baseline records producing revisions, comparison rules, and repeated-run determinism; - [ ] generation and human review provenance are documented; and - [ ] the project requires no network, plugin, randomness, clock, private dependency, or executable project hook. diff --git a/README.md b/README.md index 5f6ed02..9cf0a0d 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,16 @@ Every project has one of two origins: -- **Source-backed reproduction:** a reimplementation of a reliable published or well-known engineering analysis. Independently verified assertions may make correctness claims. Citations, assumptions, adaptations, and redistributable inputs must be recorded. -- **Original synthetic complexity:** a new, imaginary engineering project designed to exercise realistic combinations of Graphcal features. Graphcal-produced expected output is a stability baseline, not proof that the engineering result is correct. +- **Source-backed reproduction:** a reliable public source supplies both the reproduced inputs and the correct output values. Reference-backed assertions must trace directly to values reported by that source, including any explicit source rounding or documented unit conversion. +- **Original synthetic complexity:** a new scenario designed to exercise realistic combinations of Graphcal features. This includes source-informed models that reuse a published equation with original or adapted inputs when the source does not report the corresponding outputs. Graphcal-produced expected output is a stability baseline, not proof that the engineering result is correct. -A project may combine independently verified reference assertions with stability baselines for other outputs. Each expectation must state which class it belongs to. +A published equation alone does not make a case source-backed. A local analytical calculation, separate implementation, or domain review may corroborate a source value, but it cannot be the sole oracle for a reference-backed assertion. Each case has one expectation class; a project with multiple entrypoints may use different classes only when each case independently satisfies its evidence contract. Private project names, paths, source text, inputs, outputs, and results are prohibited, even when edited or anonymized. See [PRIVACY.md](PRIVACY.md). ## Trust model -Coding agents and other generators may prepare **candidates**, but generated content is untrusted. A human promotes a candidate only after reviewing its privacy, structure, provenance, expectation classification, independent calculations, and determinism evidence. The complete process is in [CONTRIBUTING.md](CONTRIBUTING.md). +Coding agents and other generators may prepare **candidates**, but generated content is untrusted. A human promotes a candidate only after reviewing its privacy, structure, provenance, expectation classification, source-to-assertion traceability, and determinism evidence. The complete process is in [CONTRIBUTING.md](CONTRIBUTING.md). Corpus projects are data-only and must not contain executable test hooks. This repository provides an opt-in local runner for a caller-supplied Graphcal executable; it never invokes project-provided programs. Repository CI performs structural validation only and does not run Graphcal. diff --git a/corpus.toml b/corpus.toml index eb13c06..21f6b89 100644 --- a/corpus.toml +++ b/corpus.toml @@ -60,116 +60,138 @@ id = "nasa-lift-sweep" path = "projects/nasa-lift-sweep" status = "active" domain = "aerodynamics" -origin = "source-backed" -purpose = "Verify dynamic pressure, lift, and inverse speed against NASA's lift equation." +origin = "original-synthetic" +purpose = "Detect semantic drift in a source-informed lift sweep with original inputs." [[projects.cases]] id = "three-flight-points" entry = "src/nasa_lift_sweep/main.gcl" +[projects.cases.expectation] +kind = "stability-baseline" +expected = "expected/three-flight-points.json" +evidence = "reference/baseline.md" + +[projects.cases.expectation.comparison] +mode = "semantic-json" +tolerances = [] + +[[projects]] +id = "pvwatts-hourly-dc-energy" +path = "projects/pvwatts-hourly-dc-energy" +status = "active" +domain = "solar-energy" +origin = "original-synthetic" +purpose = "Detect semantic drift in a source-informed PVWatts profile with original inputs." + +[[projects.cases]] +id = "four-hour-profile" +entry = "src/pvwatts_hourly_dc_energy/main.gcl" + +[projects.cases.expectation] +kind = "stability-baseline" +expected = "expected/four-hour-profile.json" +evidence = "reference/baseline.md" + +[projects.cases.expectation.comparison] +mode = "semantic-json" +tolerances = [] + +[[projects]] +id = "fao56-reference-evapotranspiration" +path = "projects/fao56-reference-evapotranspiration" +status = "active" +domain = "agricultural-water-management" +origin = "source-backed" +purpose = "Reproduce the FAO-56 Example 18 daily reference evapotranspiration result." + +[[projects.cases]] +id = "example-18" +entry = "src/fao56_reference_evapotranspiration/main.gcl" + [projects.cases.expectation] kind = "reference-backed" evidence = "reference/calculation.md" [[projects.cases.expectation.assertions]] -pointer = "/node/cruise_dynamic_pressure/si_value" -expected = 980.0 -absolute_tolerance = 1e-9 +pointer = "/node/reported_radiation_component/display_value" +expected = 2.81 [[projects.cases.expectation.assertions]] -pointer = "/node/cruise_lift/si_value" -expected = 12700.8 -absolute_tolerance = 1e-9 +pointer = "/node/reported_aerodynamic_component/display_value" +expected = 1.07 [[projects.cases.expectation.assertions]] -pointer = "/node/maximum_lift/si_value" -expected = 19845.0 -absolute_tolerance = 1e-9 +pointer = "/node/reported_equation_reference_evapotranspiration/display_value" +expected = 3.88 [[projects.cases.expectation.assertions]] -pointer = "/node/level_flight_speed/si_value" -expected = 38.88078956798696 -absolute_tolerance = 1e-9 +pointer = "/node/reported_reference_evapotranspiration/display_value" +expected = 3.9 +absolute_tolerance = 1e-12 [[projects.cases.expectation.assertions]] -pointer = "/node/maximum_lift/unit" -expected = "kN" +pointer = "/node/reported_reference_evapotranspiration/unit" +expected = "mm_per_day" [[projects]] -id = "pvwatts-hourly-dc-energy" -path = "projects/pvwatts-hourly-dc-energy" +id = "nws-heat-index-examples" +path = "projects/nws-heat-index-examples" status = "active" -domain = "solar-energy" +domain = "weather-safety" origin = "source-backed" -purpose = "Verify an hourly DC-energy calculation against the PVWatts Version 5 module model." +purpose = "Reproduce two heat-index values explicitly reported by the National Weather Service." [[projects.cases]] -id = "four-hour-profile" -entry = "src/pvwatts_hourly_dc_energy/main.gcl" +id = "published-examples" +entry = "src/nws_heat_index_examples/main.gcl" [projects.cases.expectation] kind = "reference-backed" evidence = "reference/calculation.md" [[projects.cases.expectation.assertions]] -pointer = "/node/low_sun_dc_power/si_value" -expected = 1040.0 -absolute_tolerance = 1e-9 +pointer = "/node/humid_example_heat_index_fahrenheit_value/si_value" +expected = 124.0 [[projects.cases.expectation.assertions]] -pointer = "/node/peak_dc_power/si_value" -expected = 4600.0 -absolute_tolerance = 1e-9 - -[[projects.cases.expectation.assertions]] -pointer = "/node/total_dc_energy/si_value" -expected = 38016000.0 -absolute_tolerance = 1e-6 - -[[projects.cases.expectation.assertions]] -pointer = "/node/peak_dc_power/unit" -expected = "kW" - -[[projects.cases.expectation.assertions]] -pointer = "/node/total_dc_energy/unit" -expected = "kWh" +pointer = "/node/dry_example_heat_index_fahrenheit_value/si_value" +expected = 96.0 [[projects]] -id = "fao56-reference-evapotranspiration" -path = "projects/fao56-reference-evapotranspiration" +id = "epa-chp-savings-example" +path = "projects/epa-chp-savings-example" status = "active" -domain = "agricultural-water-management" +domain = "energy-and-emissions" origin = "source-backed" -purpose = "Reproduce the FAO-56 Example 18 daily reference evapotranspiration result." +purpose = "Reproduce fuel and carbon-dioxide savings reported in a U.S. EPA CHP example." [[projects.cases]] -id = "example-18" -entry = "src/fao56_reference_evapotranspiration/main.gcl" +id = "appendix-a" +entry = "src/epa_chp_savings_example/main.gcl" [projects.cases.expectation] kind = "reference-backed" evidence = "reference/calculation.md" [[projects.cases.expectation.assertions]] -pointer = "/node/radiation_component/si_value" -expected = 3.2466022318476985e-8 -absolute_tolerance = 1e-18 +pointer = "/node/total_fuel_savings/display_value" +expected = 115546.0 +absolute_tolerance = 1e-6 [[projects.cases.expectation.assertions]] -pointer = "/node/aerodynamic_component/si_value" -expected = 1.2429119836677152e-8 -absolute_tolerance = 1e-18 +pointer = "/node/total_fuel_savings/unit" +expected = "MMBtu" [[projects.cases.expectation.assertions]] -pointer = "/node/reference_evapotranspiration/si_value" -expected = 4.489514215515413e-8 -absolute_tolerance = 1e-18 +pointer = "/node/reported_fuel_savings_percent/si_value" +expected = 21.0 [[projects.cases.expectation.assertions]] -pointer = "/node/reported_reference_evapotranspiration/si_value" -expected = 4.5138888888888884e-8 -absolute_tolerance = 1e-18 +pointer = "/node/total_co2_savings/display_value" +expected = 18065.0 +absolute_tolerance = 1e-9 [[projects.cases.expectation.assertions]] -pointer = "/node/reported_reference_evapotranspiration/unit" -expected = "mm_per_day" +pointer = "/node/total_co2_savings/unit" +expected = "short_ton" diff --git a/projects/epa-chp-savings-example/README.md b/projects/epa-chp-savings-example/README.md new file mode 100644 index 0000000..47051b4 --- /dev/null +++ b/projects/epa-chp-savings-example/README.md @@ -0,0 +1,5 @@ +# EPA combined-heat-and-power savings example + +This source-backed reproduction asks: **Do the U.S. EPA's published combined-heat-and-power fuel and carbon-dioxide savings equations reproduce the results in its CEESC worked example?** + +The project uses the rounded annual fuel-use and CO₂ values printed in Appendix A of the EPA methodology and evaluates the report's total-savings equations. The manifest checks only values explicitly reported by EPA. Source locations, unit adaptations, and assertion mappings are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/epa-chp-savings-example/graphcal.toml b/projects/epa-chp-savings-example/graphcal.toml new file mode 100644 index 0000000..ac34c11 --- /dev/null +++ b/projects/epa-chp-savings-example/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "epa_chp_savings_example" diff --git a/projects/epa-chp-savings-example/reference/calculation.md b/projects/epa-chp-savings-example/reference/calculation.md new file mode 100644 index 0000000..7d8dde9 --- /dev/null +++ b/projects/epa-chp-savings-example/reference/calculation.md @@ -0,0 +1,46 @@ +# EPA CHP savings source evidence + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction from the cited public U.S. EPA worked example. It does not derive from private material. Human source, privacy, adaptation, and promotion review remain pull-request responsibilities. + +## Source and published expected values + +U.S. Environmental Protection Agency Combined Heat and Power Partnership, *Fuel and Carbon Dioxide Emissions Savings Calculation Methodology for Combined Heat and Power Systems*, June 2021, Appendix A, especially pages 20–21, https://www.epa.gov/sites/default/files/2015-07/documents/fuel_and_carbon_dioxide_emissions_savings_calculation_methodology_for_combined_heat_and_power_systems.pdf, accessed 2026-08-16. + +Appendix A publishes a complete CEESC example. Its Equation 1 reports total fuel savings as + +\[ +115{,}546=(257{,}964+300{,}437)-442{,}855\ \text{MMBtu/year}. +\] + +Its Equation 2 reports total carbon-dioxide savings as + +\[ +18{,}065=(15{,}078+28{,}872)-25{,}885\ \text{tons CO}_2/\text{year}. +\] + +Table 1 on page 20 also reports fuel savings of 115,546 MMBtu/year and 21%. + +These EPA-reported values—not locally generated higher-precision outputs—are the manifest's expected values. + +## Adaptation and source-to-assertion mapping + +The source quantities are annual totals. The Graphcal project represents the one-year fuel totals as `Energy` and CO₂ totals as `Mass`; it does not divide both sides by a year because that common reporting interval cancels in the savings equations. + +`MMBtu` is represented using the international-table Btu conversion, and `short_ton` uses the U.S. short ton. Conversion provenance is recorded by NIST, *Guide to the SI*, Appendix B.8, https://www.nist.gov/pml/special-publication-811/nist-guide-si-appendix-b-conversion-factors/nist-guide-si-appendix-b8. The assertions target source-unit display values so SI conversion does not become the numerical oracle. + +The manifest maps the source values as follows: + +- `/node/total_fuel_savings/display_value` = `115546.0` MMBtu, from Appendix A Equation 1 and Table 1; +- `/node/reported_fuel_savings_percent/si_value` = `21.0`, from Appendix A Table 1; +- `/node/total_co2_savings/display_value` = `18065.0` short tons, from Appendix A Equation 2; +- exact unit-label assertions distinguish the source-unit presentations. + +Small absolute tolerances on the two display values cover only binary floating-point roundoff introduced by unit scaling. They do not widen the source's published whole-unit precision. + +The report notes that some detailed figures do not equate exactly because of rounding. This project intentionally reproduces the rounded Equation 1 and Equation 2 arithmetic rather than claiming unreported precision. + +## Licensing and adaptation + +Only the equations and the small set of numerical facts needed for the cited worked result are reimplemented. No EPA prose, figures, calculator software, or substantial tables are copied. The Graphcal source and this evidence record are original corpus content under the repository license; the EPA and NIST pages are cited for provenance and are not relicensed here. diff --git a/projects/epa-chp-savings-example/src/epa_chp_savings_example/main.gcl b/projects/epa-chp-savings-example/src/epa_chp_savings_example/main.gcl new file mode 100644 index 0000000..abf07aa --- /dev/null +++ b/projects/epa-chp-savings-example/src/epa_chp_savings_example/main.gcl @@ -0,0 +1,17 @@ +const unit Btu_IT: Energy = 1055.056 J; +const unit MMBtu: Energy = 1000000.0 Btu_IT; +const unit short_ton: Mass = 907.18474 kg; + +param displaced_thermal_fuel_use: Energy = 257964.0 MMBtu; +param displaced_grid_fuel_use: Energy = 300437.0 MMBtu; +param chp_fuel_use: Energy = 442855.0 MMBtu; +param displaced_thermal_co2: Mass = 15078.0 short_ton; +param displaced_grid_co2: Mass = 28872.0 short_ton; +param chp_co2: Mass = 25885.0 short_ton; + +node conventional_fuel_use: Energy = @displaced_thermal_fuel_use + @displaced_grid_fuel_use; +node total_fuel_savings: Energy = @conventional_fuel_use - @chp_fuel_use -> MMBtu; +node reported_fuel_savings_percent: Dimensionless = round( + @total_fuel_savings / @conventional_fuel_use * 100.0 +); +node total_co2_savings: Mass = @displaced_thermal_co2 + @displaced_grid_co2 - @chp_co2 -> short_ton; diff --git a/projects/fao56-reference-evapotranspiration/README.md b/projects/fao56-reference-evapotranspiration/README.md index 7e4d575..17e195c 100644 --- a/projects/fao56-reference-evapotranspiration/README.md +++ b/projects/fao56-reference-evapotranspiration/README.md @@ -2,4 +2,4 @@ This source-backed reproduction asks: **Does the FAO Penman–Monteith equation reproduce the daily reference evapotranspiration reported in FAO-56 Example 18?** -It evaluates Equation 6 from the rounded intermediate meteorological values published for the example and reports the result to 0.1 mm/day. Celsius is handled explicitly as a normalized numeric value while physical temperatures remain kelvin quantities. The source comparison, assumptions, unit adaptation, and independent calculation are documented in [`reference/calculation.md`](reference/calculation.md). +It evaluates Equation 6 from the rounded intermediate meteorological values published for the example and exposes results at the precision printed by FAO. Celsius is handled explicitly as a normalized numeric value while physical temperatures remain kelvin quantities. The source-to-assertion mapping and unit adaptation are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/fao56-reference-evapotranspiration/reference/calculation.md b/projects/fao56-reference-evapotranspiration/reference/calculation.md index 574d486..a3131da 100644 --- a/projects/fao56-reference-evapotranspiration/reference/calculation.md +++ b/projects/fao56-reference-evapotranspiration/reference/calculation.md @@ -1,14 +1,14 @@ -# Independent FAO-56 reference-evapotranspiration calculation +# FAO-56 reference-evapotranspiration source evidence ## Candidate generation -This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction. The agent selected the cited public worked example, wrote an original Graphcal reproduction from its formula and rounded intermediate values, and performed the separate calculation below. It does not derive from a private project. Human source, privacy, calculation, and promotion review remain pull-request responsibilities. +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction from the cited public worked example. It does not derive from private material. Human source, privacy, adaptation, and promotion review remain pull-request responsibilities. -## Source +## Source and published expected values R. G. Allen, L. S. Pereira, D. Raes, and M. Smith, *Crop Evapotranspiration: Guidelines for Computing Crop Water Requirements*, FAO Irrigation and Drainage Paper 56, Food and Agriculture Organization of the United Nations, Rome, 1998, Chapter 4, Equation 6 and Example 18, https://www.fao.org/4/x0490e/x0490e08.htm, accessed 2026-08-15. -For a daily time step, the FAO Penman–Monteith equation is +For a daily time step, the source gives the FAO Penman–Monteith equation \[ ET_0 = @@ -20,65 +20,41 @@ ET_0 = }. \] -Under the equation's stated conventional units, the result is millimetres per day. Example 18 reports 3.88 mm/day before presenting the result as 3.9 mm/day. +Example 18 publishes the rounded intermediate inputs reproduced by the project: -## Reproduced inputs and adaptations +- \(T=16.9\ ^\circ\mathrm{C}\); +- \(u_2=2.078\ \mathrm{m/s}\); +- \(\Delta=0.122\ \mathrm{kPa/^{\circ}C}\); +- \(\gamma=0.0666\ \mathrm{kPa/^{\circ}C}\); +- \(e_s-e_a=0.589\ \mathrm{kPa}\); +- \(R_n=13.28\ \mathrm{MJ/(m^2\,day)}\); +- \(G=0\ \mathrm{MJ/(m^2\,day)}\). -This project begins from the rounded intermediate values printed in Example 18: +The worked example then reports: -- mean air temperature \(T=16.9\ ^\circ\mathrm{C}\); -- wind speed at 2 m \(u_2=2.078\ \mathrm{m/s}\); -- slope of the vapour-pressure curve \(\Delta=0.122\ \mathrm{kPa/K}\); -- psychrometric constant \(\gamma=0.0666\ \mathrm{kPa/K}\); -- vapour-pressure deficit \(e_s-e_a=0.589\ \mathrm{kPa}\); -- net radiation \(R_n=13.28\ \mathrm{MJ/(m^2\,day)}\); -- daily soil heat flux \(G=0\ \mathrm{MJ/(m^2\,day)}\). +- radiation component: 2.81 mm/day; +- aerodynamic component: 1.07 mm/day; +- Equation 6 total before final presentation: 3.88 mm/day; +- final reported reference evapotranspiration: 3.9 mm/day. -The example's intermediate values are already rounded, so this is a reproduction of its final Equation 6 calculation, not a recomputation from the raw weather observations. +Those four source-reported values—not locally calculated higher-precision values—are the manifest's expected values. -Graphcal intentionally has no affine Celsius unit. The model stores 16.9 °C as 290.05 K and explicitly computes the Celsius numeric value as \((T_K-273.15\,K)/(1\,K)\) before using the empirical \(T+273\) term. Temperature differences in \(\Delta\) and \(\gamma\) use kelvin because one kelvin and one degree Celsius have the same interval size. +## Adaptation and source-to-assertion mapping -The empirical equation combines values expressed in prescribed conventional units. The Graphcal model makes each normalization explicit, computes the conventional numerical terms dimensionlessly, and attaches the physical output unit mm/day. +Graphcal intentionally has no affine Celsius unit. The project stores 16.9 °C as 290.05 K and explicitly obtains the conventional Celsius numeric value as \((T_K-273.15\,K)/(1\,K)\) before using the empirical \(T+273\) term. One degree Celsius and one kelvin have the same interval size, so \(\Delta\) and \(\gamma\) use kPa/K. -## Independent calculation +The empirical equation requires values normalized to its prescribed conventional units. The model makes those normalizations explicit, attaches mm/day to the output, and adds reporting nodes at the precision printed by Example 18. -Using the published rounded values with ordinary binary64 arithmetic, independently of Graphcal: +The manifest maps the published outputs as follows: -\[ -D = 0.122 + 0.0666(1+0.34(2.078)) - = 0.23565423200000002. -\] - -Radiation component: - -\[ -ET_{rad} = \frac{0.408(13.28)(0.122)}{D} - = 2.805064328316411\ \mathrm{mm/day}. -\] - -Aerodynamic component: - -\[ -ET_{aero} = -\frac{0.0666\,[900/(16.9+273)](2.078)(0.589)}{D} -=1.073875953888906\ \mathrm{mm/day}. -\] - -Therefore: - -\[ -ET_0=3.878940282205317\ \mathrm{mm/day}, -\] - -which rounds to 3.9 mm/day and agrees with the reported Example 18 result. Using \(1\ \mathrm{mm/day}=10^{-3}/86400\ \mathrm{m/s}\), the corresponding SI values are: - -- radiation component: 3.2466022318476985 × 10⁻⁸ m/s; -- aerodynamic component: 1.2429119836677152 × 10⁻⁸ m/s; -- unrounded total: 4.489514215515413 × 10⁻⁸ m/s; -- reported 3.9 mm/day: 4.5138888888888884 × 10⁻⁸ m/s. +- `/node/reported_radiation_component/display_value` = `2.81`; +- `/node/reported_aerodynamic_component/display_value` = `1.07`; +- `/node/reported_equation_reference_evapotranspiration/display_value` = `3.88`; +- `/node/reported_reference_evapotranspiration/display_value` = `3.9`; +- exact unit assertions require `mm_per_day`. -The manifest checks these SI values with narrowly scoped tolerances and checks the displayed mm/day unit exactly. +The unrounded internal nodes remain useful corpus coverage, but they are deliberately not reference-backed assertions because FAO does not report those extra digits. ## Licensing and adaptation -Only the equation and the small set of numerical facts needed to reproduce the cited worked example are used. No FAO prose, figures, calculation-sheet layout, software, or data files are copied. The Graphcal implementation and this explanation are original corpus content under the repository license; the FAO publication is cited for provenance and is not relicensed here. +Only the equation and the small set of numerical facts needed for the cited worked result are reimplemented. No FAO prose, figures, calculation-sheet layout, software, or data files are copied. The Graphcal source and this evidence record are original corpus content under the repository license; the FAO publication is cited for provenance and is not relicensed here. diff --git a/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl b/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl index 91f8b71..1aa410e 100644 --- a/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl +++ b/projects/fao56-reference-evapotranspiration/src/fao56_reference_evapotranspiration/main.gcl @@ -12,7 +12,8 @@ param vapour_pressure_deficit: Pressure = 0.589 kPa; param net_radiation_flux: Power / Area = 13.28 MJ_per_square_metre_day; param soil_heat_flux: Power / Area = 0.0 MJ_per_square_metre_day; -const node reporting_increment: Velocity = 0.1 mm_per_day; +const node equation_reporting_increment: Velocity = 0.01 mm_per_day; +const node final_reporting_increment: Velocity = 0.1 mm_per_day; node mean_air_temperature_celsius_value: Dimensionless = (@mean_air_temperature - 273.15 K) / 1.0 K; node normalized_wind_speed: Dimensionless = @wind_speed_2m / 1.0 m/s; @@ -31,6 +32,15 @@ node aerodynamic_component: Velocity = @normalized_psychrometric_constant * ( 900.0 / (@mean_air_temperature_celsius_value + 273.0) ) * @normalized_wind_speed * @normalized_vapour_pressure_deficit / @denominator * 1.0 mm_per_day -> mm_per_day; node reference_evapotranspiration: Velocity = @radiation_component + @aerodynamic_component -> mm_per_day; +node reported_radiation_component: Velocity = round( + @radiation_component / @equation_reporting_increment +) * @equation_reporting_increment -> mm_per_day; +node reported_aerodynamic_component: Velocity = round( + @aerodynamic_component / @equation_reporting_increment +) * @equation_reporting_increment -> mm_per_day; +node reported_equation_reference_evapotranspiration: Velocity = round( + @reference_evapotranspiration / @equation_reporting_increment +) * @equation_reporting_increment -> mm_per_day; node reported_reference_evapotranspiration: Velocity = round( - @reference_evapotranspiration / @reporting_increment -) * @reporting_increment -> mm_per_day; + @reference_evapotranspiration / @final_reporting_increment +) * @final_reporting_increment -> mm_per_day; diff --git a/projects/nasa-lift-sweep/README.md b/projects/nasa-lift-sweep/README.md index 585054d..2428731 100644 --- a/projects/nasa-lift-sweep/README.md +++ b/projects/nasa-lift-sweep/README.md @@ -1,5 +1,5 @@ # NASA lift-equation sweep -This source-backed reproduction asks: **What dynamic pressure and lift result at three low-speed flight points, and what speed produces a required lift?** +This source-informed synthetic project asks: **What dynamic pressure and lift result at three low-speed flight points, and what speed produces a required lift?** -It applies the lift and dynamic-pressure equations presented by NASA Glenn Research Center to a fixed set of original, illustrative inputs. The lift coefficient is held constant, so this is a point calculation rather than an aerodynamic prediction across changing Reynolds or Mach number. The asserted values and independent calculation are documented in [`reference/calculation.md`](reference/calculation.md). +It applies NASA's lift and dynamic-pressure equations to original illustrative inputs. NASA does not publish expected values for this scenario, so the checked-in output is a stability baseline rather than an aerodynamic correctness claim. Its generation and determinism evidence are documented in [`reference/baseline.md`](reference/baseline.md). diff --git a/projects/nasa-lift-sweep/expected/three-flight-points.json b/projects/nasa-lift-sweep/expected/three-flight-points.json new file mode 100644 index 0000000..ace92f1 --- /dev/null +++ b/projects/nasa-lift-sweep/expected/three-flight-points.json @@ -0,0 +1,98 @@ +{ + "const": {}, + "node": { + "cruise_dynamic_pressure": { + "display_value": 980.0000000000001, + "si_value": 980.0000000000001, + "unit": "Pa" + }, + "cruise_lift": { + "display_value": 12.700800000000001, + "si_value": 12700.800000000001, + "unit": "kN" + }, + "dynamic_pressure": { + "entries": { + "Approach": { + "si_value": 551.25, + "unit": "kg/m/s^2" + }, + "Cruise": { + "si_value": 980.0000000000001, + "unit": "kg/m/s^2" + }, + "Fast": { + "si_value": 1531.25, + "unit": "kg/m/s^2" + } + }, + "index": "FlightPoint" + }, + "level_flight_speed": { + "si_value": 38.88078956798696, + "unit": "m/s" + }, + "lift_force": { + "entries": { + "Approach": { + "si_value": 7144.2, + "unit": "m*kg/s^2" + }, + "Cruise": { + "si_value": 12700.800000000001, + "unit": "m*kg/s^2" + }, + "Fast": { + "si_value": 19845.0, + "unit": "m*kg/s^2" + } + }, + "index": "FlightPoint" + }, + "maximum_lift": { + "display_value": 19.845, + "si_value": 19845.0, + "unit": "kN" + } + }, + "param": { + "air_density": { + "display_value": 1.225, + "si_value": 1.225, + "unit": "kg/m^3" + }, + "airspeed": { + "entries": { + "Approach": { + "display_value": 30.0, + "si_value": 30.0, + "unit": "m/s" + }, + "Cruise": { + "display_value": 40.0, + "si_value": 40.0, + "unit": "m/s" + }, + "Fast": { + "display_value": 50.0, + "si_value": 50.0, + "unit": "m/s" + } + }, + "index": "FlightPoint" + }, + "lift_coefficient": { + "si_value": 0.8 + }, + "required_lift": { + "display_value": 12.0, + "si_value": 12000.0, + "unit": "kN" + }, + "wing_area": { + "display_value": 16.2, + "si_value": 16.2, + "unit": "m^2" + } + } +} diff --git a/projects/nasa-lift-sweep/reference/baseline.md b/projects/nasa-lift-sweep/reference/baseline.md new file mode 100644 index 0000000..7bd871f --- /dev/null +++ b/projects/nasa-lift-sweep/reference/baseline.md @@ -0,0 +1,43 @@ +# Stability baseline evidence + +## Classification and generation + +This is an original synthetic, source-informed project prepared as a candidate by an AI coding agent at the repository maintainer's direction. NASA publishes the lift and dynamic-pressure equations, but it does not publish expected outputs for this project's invented density, wing, coefficient, speeds, and required lift. The checked-in output is therefore a Graphcal stability baseline, not an aerodynamic correctness oracle. The project does not derive from private material. Human privacy, technical, and promotion review remain pull-request responsibilities. + +## Producing revisions and inputs + +- Graphcal: `0.0.1-alpha.23`, commit `04ab7150534de0b795acae1b3a7bcc282266ec3c` +- Corpus source revision: `42259833d1b8d6c60c761195a4a7981019058e17` +- Entrypoint: `src/nasa_lift_sweep/main.gcl` +- Inputs: checked-in parameter defaults; no `--set` or `--input` overrides +- Expected output: `expected/three-flight-points.json` +- Canonical expected-output SHA-256: `c06e90a3f2e52cd3a621bb2a2c49e7beea35a5413059288105d25dbe354bf299` + +The source equations are documented by NASA Glenn Research Center, “Lift Coefficient,” *Beginner's Guide to Aeronautics*, https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/lift-coefficient/, accessed 2026-08-15. That citation motivates the model but does not supply its expected values. + +The baseline was generated from the project directory with: + +```console +graphcal eval --format json --root . src/nasa_lift_sweep/main.gcl \ + | jq -S . > expected/three-flight-points.json +``` + +## Comparison rules + +The runner parses both outputs as strict JSON and compares them semantically. Object key order is ignored; array order and length are significant; missing or additional values fail; and JSON values compare exactly by type and value. This baseline declares no numeric tolerances. + +Exact comparison intentionally detects deterministic changes across indexed evaluation, powers, reductions, square roots, and unit display. It does not prove that the synthetic aerodynamic assumptions are correct. + +## Repeated-run determinism + +Five consecutive evaluations with the recorded Graphcal executable and source revision produced the same canonical semantic JSON. Each result was canonicalized with `jq -S -c` and hashed with SHA-256: + +```text +c06e90a3f2e52cd3a621bb2a2c49e7beea35a5413059288105d25dbe354bf299 +c06e90a3f2e52cd3a621bb2a2c49e7beea35a5413059288105d25dbe354bf299 +c06e90a3f2e52cd3a621bb2a2c49e7beea35a5413059288105d25dbe354bf299 +c06e90a3f2e52cd3a621bb2a2c49e7beea35a5413059288105d25dbe354bf299 +c06e90a3f2e52cd3a621bb2a2c49e7beea35a5413059288105d25dbe354bf299 +``` + +This establishes repeatability only for the recorded executable and inputs. diff --git a/projects/nasa-lift-sweep/reference/calculation.md b/projects/nasa-lift-sweep/reference/calculation.md deleted file mode 100644 index 0433c1c..0000000 --- a/projects/nasa-lift-sweep/reference/calculation.md +++ /dev/null @@ -1,58 +0,0 @@ -# Independent NASA lift-equation calculation - -## Candidate generation - -This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction. The agent selected the cited public formula, chose original illustrative inputs, wrote an original Graphcal reproduction, and performed the separate calculation below. It does not derive from a private project. Human source, privacy, calculation, and promotion review remain pull-request responsibilities. - -## Source - -NASA Glenn Research Center, “Lift Coefficient,” *Beginner's Guide to Aeronautics*, https://www1.grc.nasa.gov/beginners-guide-to-aeronautics/lift-coefficient/, accessed 2026-08-15. - -NASA states that dynamic pressure and lift coefficient satisfy - -\[ -q = \frac{1}{2}\rho V^2, \qquad C_l = \frac{L}{qA}. -\] - -Rearranging the second equation gives \(L=C_l qA\). Solving the combined equation for the speed that produces a specified lift gives - -\[ -V = \sqrt{\frac{2L}{\rho A C_l}}. -\] - -The source cautions that a lift coefficient carries shape, viscosity, and compressibility effects. This reproduction deliberately holds it constant and uses low-speed points; it does not model those effects. - -## Adapted inputs - -These values are illustrative inputs created for this corpus project, not a copied NASA example: - -- air density: 1.225 kg/m³; -- wing area: 16.2 m²; -- lift coefficient: 0.8; -- airspeeds: 30, 40, and 50 m/s; -- required lift for the inverse calculation: 12,000 N. - -The model assumes steady conditions and uses one constant density, area, and lift coefficient at every flight point. - -## Independent calculation - -Using the formulas above with ordinary binary64 arithmetic, independently of Graphcal: - -| Speed (m/s) | \(q=\rho V^2/2\) (Pa) | \(L=C_lqA\) (N) | -|---:|---:|---:| -| 30 | 551.25 | 7,144.2 | -| 40 | 980.0 | 12,700.8 | -| 50 | 1,531.25 | 19,845.0 | - -For the required-lift calculation: - -\[ -V = \sqrt{\frac{2(12000)}{(1.225)(16.2)(0.8)}} - = 38.88078956798696\ \text{m/s}. -\] - -The manifest checks the 40 m/s dynamic pressure, the 40 m/s lift, the maximum sweep lift, and the inverse speed. Absolute tolerances of 1 × 10⁻⁹ in each asserted SI value allow only last-bit floating-point differences. - -## Licensing and adaptation - -The equations were reimplemented from the cited NASA educational page. No source prose, figures, software, or data files are reproduced. All numerical inputs and explanatory text in this project are original corpus material under the repository license; the NASA page is cited for provenance and is not relicensed here. diff --git a/projects/nws-heat-index-examples/README.md b/projects/nws-heat-index-examples/README.md new file mode 100644 index 0000000..a401eef --- /dev/null +++ b/projects/nws-heat-index-examples/README.md @@ -0,0 +1,5 @@ +# NWS heat-index examples + +This source-backed reproduction asks: **Does the National Weather Service heat-index regression reproduce two values explicitly reported by NWS for 100 °F air?** + +The NWS page publishes the regression and reports heat indexes of 124 °F at 55% relative humidity and 96 °F at 15% relative humidity. The project applies the published regression and rounds to the whole-degree presentation used by the source. The source-to-assertion mapping and the required Fahrenheit adaptation are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/nws-heat-index-examples/graphcal.toml b/projects/nws-heat-index-examples/graphcal.toml new file mode 100644 index 0000000..6201658 --- /dev/null +++ b/projects/nws-heat-index-examples/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "nws_heat_index_examples" diff --git a/projects/nws-heat-index-examples/reference/calculation.md b/projects/nws-heat-index-examples/reference/calculation.md new file mode 100644 index 0000000..2c2525a --- /dev/null +++ b/projects/nws-heat-index-examples/reference/calculation.md @@ -0,0 +1,45 @@ +# NWS heat-index source evidence + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction from the cited public National Weather Service page. It does not derive from private material. Human source, privacy, adaptation, and promotion review remain pull-request responsibilities. + +## Source and published expected values + +National Weather Service, Weather Forecast Office Amarillo, “What is the heat index?”, https://www.weather.gov/ama/heatindex, accessed 2026-08-16. + +The page publishes the Rothfusz regression + +\[ +\begin{aligned} +HI={}&-42.379+2.04901523T+10.14333127RH-0.22475541T RH\\ +&-0.00683783T^2-0.05481717RH^2+0.00122874T^2RH\\ +&+0.00085282T RH^2-0.00000199T^2RH^2, +\end{aligned} +\] + +with \(T\) in degrees Fahrenheit, \(RH\) as a percentage, and \(HI\) in degrees Fahrenheit. The same NWS page explicitly reports these examples: + +| Example | Source air temperature | Source relative humidity | Source heat index | +|---|---:|---:|---:| +| Humid | 100 °F | 55% | 124 °F | +| Dry | 100 °F | 15% | 96 °F | + +Those two source-reported output values—not a locally calculated higher-precision result—are the manifest's expected values. + +## Adaptation and source-to-assertion mapping + +Graphcal does not define affine Fahrenheit units. The regression itself requires conventional Fahrenheit and percentage numeric values, so the project names and types those inputs explicitly as dimensionless numeric values rather than pretending they are multiplicative temperature quantities. The output is likewise named `*_fahrenheit_value`. + +The page presents the examples to whole degrees. Evaluating the published regression gives values near 123.64 and 95.85 before presentation; Graphcal applies `round` and the manifest asserts exactly: + +- `/node/humid_example_heat_index_fahrenheit_value/si_value` = `124.0`, from the NWS 100 °F / 55% example; +- `/node/dry_example_heat_index_fahrenheit_value/si_value` = `96.0`, from the NWS 100 °F / 15% example. + +The local regression evaluation only connects the model to the published whole-degree examples; it is not the source of the expected values. + +The NWS notes that the regression is an approximation with an error of ±1.3 °F and that chart values are for shady locations. This project reproduces the two reported examples only; it does not make a broader heat-safety claim. + +## Licensing and adaptation + +Only the published equation and two numerical examples are reimplemented. No source prose, chart image, software, or dataset is copied. The Graphcal source and this evidence record are original corpus content under the repository license; the NWS page is cited for provenance and is not relicensed here. diff --git a/projects/nws-heat-index-examples/src/nws_heat_index_examples/main.gcl b/projects/nws-heat-index-examples/src/nws_heat_index_examples/main.gcl new file mode 100644 index 0000000..3bae37c --- /dev/null +++ b/projects/nws-heat-index-examples/src/nws_heat_index_examples/main.gcl @@ -0,0 +1,19 @@ +pub index Example = { Humid, Dry }; + +param air_temperature_fahrenheit_value: Dimensionless[Example] = { + Example.Humid: 100.0, + Example.Dry: 100.0, +}; +param relative_humidity_percent_value: Dimensionless[Example] = { + Example.Humid: 55.0, + Example.Dry: 15.0, +}; + +node regression_heat_index_fahrenheit_value: Dimensionless[Example] = for example: Example { + -42.379 + 2.04901523 * @air_temperature_fahrenheit_value[example] + 10.14333127 * @relative_humidity_percent_value[example] - 0.22475541 * @air_temperature_fahrenheit_value[example] * @relative_humidity_percent_value[example] - 0.00683783 * @air_temperature_fahrenheit_value[example] ^ 2 - 0.05481717 * @relative_humidity_percent_value[example] ^ 2 + 0.00122874 * @air_temperature_fahrenheit_value[example] ^ 2 * @relative_humidity_percent_value[example] + 0.00085282 * @air_temperature_fahrenheit_value[example] * @relative_humidity_percent_value[example] ^ 2 - 0.00000199 * @air_temperature_fahrenheit_value[example] ^ 2 * @relative_humidity_percent_value[example] ^ 2 +}; +node reported_heat_index_fahrenheit_value: Dimensionless[Example] = for example: Example { + round(@regression_heat_index_fahrenheit_value[example]) +}; +node humid_example_heat_index_fahrenheit_value: Dimensionless = @reported_heat_index_fahrenheit_value[Example.Humid]; +node dry_example_heat_index_fahrenheit_value: Dimensionless = @reported_heat_index_fahrenheit_value[Example.Dry]; diff --git a/projects/pvwatts-hourly-dc-energy/README.md b/projects/pvwatts-hourly-dc-energy/README.md index e57f341..f1c0a61 100644 --- a/projects/pvwatts-hourly-dc-energy/README.md +++ b/projects/pvwatts-hourly-dc-energy/README.md @@ -1,5 +1,5 @@ # PVWatts hourly DC energy -This source-backed reproduction asks: **How much DC energy does a 5 kW photovoltaic array produce over four one-hour conditions when the PVWatts module model is applied?** +This source-informed synthetic project asks: **How much DC energy does a 5 kW photovoltaic array produce over four one-hour conditions when the PVWatts module model is applied?** -It reproduces only the PVWatts Version 5 DC module equation. Effective plane-of-array irradiance and cell temperature are already prepared inputs; the project does not model weather, optical losses, cell temperature, inverter conversion, clipping, or AC output. The asserted powers and energy are documented in [`reference/calculation.md`](reference/calculation.md). +It uses the published PVWatts Version 5 DC module equation with an original four-period profile. NREL does not publish expected values for these inputs, so the checked-in output is a stability baseline rather than a photovoltaic correctness claim. Its generation and determinism evidence are documented in [`reference/baseline.md`](reference/baseline.md). diff --git a/projects/pvwatts-hourly-dc-energy/expected/four-hour-profile.json b/projects/pvwatts-hourly-dc-energy/expected/four-hour-profile.json new file mode 100644 index 0000000..73ba25a --- /dev/null +++ b/projects/pvwatts-hourly-dc-energy/expected/four-hour-profile.json @@ -0,0 +1,156 @@ +{ + "const": { + "reference_cell_temperature": { + "display_value": 298.15, + "si_value": 298.15, + "unit": "K" + }, + "reference_irradiance": { + "display_value": 1000.0, + "si_value": 1000.0, + "unit": "W/m^2" + } + }, + "node": { + "dc_power": { + "entries": { + "Afternoon": { + "si_value": 1920.0, + "unit": "m^2*kg/s^3" + }, + "LowSun": { + "si_value": 1040.0, + "unit": "m^2*kg/s^3" + }, + "MidMorning": { + "si_value": 3000.0, + "unit": "m^2*kg/s^3" + }, + "SolarNoon": { + "si_value": 4600.0, + "unit": "m^2*kg/s^3" + } + }, + "index": "Period" + }, + "interval_dc_energy": { + "entries": { + "Afternoon": { + "si_value": 6912000.0, + "unit": "m^2*kg/s^2" + }, + "LowSun": { + "si_value": 3744000.0, + "unit": "m^2*kg/s^2" + }, + "MidMorning": { + "si_value": 10800000.0, + "unit": "m^2*kg/s^2" + }, + "SolarNoon": { + "si_value": 16560000.0, + "unit": "m^2*kg/s^2" + } + }, + "index": "Period" + }, + "low_sun_dc_power": { + "display_value": 1.04, + "si_value": 1040.0, + "unit": "kW" + }, + "peak_dc_power": { + "display_value": 4.6, + "si_value": 4600.0, + "unit": "kW" + }, + "temperature_factor": { + "entries": { + "Afternoon": { + "si_value": 0.96 + }, + "LowSun": { + "si_value": 1.04 + }, + "MidMorning": { + "si_value": 1.0 + }, + "SolarNoon": { + "si_value": 0.92 + } + }, + "index": "Period" + }, + "total_dc_energy": { + "display_value": 10.56, + "si_value": 38016000.0, + "unit": "kWh" + } + }, + "param": { + "cell_temperature": { + "entries": { + "Afternoon": { + "display_value": 308.15, + "si_value": 308.15, + "unit": "K" + }, + "LowSun": { + "display_value": 288.15, + "si_value": 288.15, + "unit": "K" + }, + "MidMorning": { + "display_value": 298.15, + "si_value": 298.15, + "unit": "K" + }, + "SolarNoon": { + "display_value": 318.15, + "si_value": 318.15, + "unit": "K" + } + }, + "index": "Period" + }, + "effective_irradiance": { + "entries": { + "Afternoon": { + "display_value": 400.0, + "si_value": 400.0, + "unit": "W/m^2" + }, + "LowSun": { + "display_value": 200.0, + "si_value": 200.0, + "unit": "W/m^2" + }, + "MidMorning": { + "display_value": 600.0, + "si_value": 600.0, + "unit": "W/m^2" + }, + "SolarNoon": { + "display_value": 1000.0, + "si_value": 1000.0, + "unit": "W/m^2" + } + }, + "index": "Period" + }, + "interval_duration": { + "display_value": 1.0, + "si_value": 3600.0, + "unit": "h" + }, + "nameplate_dc_power": { + "display_value": 5.0, + "si_value": 5000.0, + "unit": "kW" + }, + "temperature_coefficient": { + "si_value": -0.004, + "unit": "K^-1" + } + } +} diff --git a/projects/pvwatts-hourly-dc-energy/reference/baseline.md b/projects/pvwatts-hourly-dc-energy/reference/baseline.md new file mode 100644 index 0000000..2ca0c24 --- /dev/null +++ b/projects/pvwatts-hourly-dc-energy/reference/baseline.md @@ -0,0 +1,43 @@ +# Stability baseline evidence + +## Classification and generation + +This is an original synthetic, source-informed project prepared as a candidate by an AI coding agent at the repository maintainer's direction. NREL publishes the PVWatts Version 5 module equation, but it does not publish expected outputs for this project's invented four-period irradiance and temperature profile. The checked-in output is therefore a Graphcal stability baseline, not a photovoltaic correctness oracle. The project does not derive from private material. Human privacy, technical, and promotion review remain pull-request responsibilities. + +## Producing revisions and inputs + +- Graphcal: `0.0.1-alpha.23`, commit `04ab7150534de0b795acae1b3a7bcc282266ec3c` +- Corpus source revision: `42259833d1b8d6c60c761195a4a7981019058e17` +- Entrypoint: `src/pvwatts_hourly_dc_energy/main.gcl` +- Inputs: checked-in parameter defaults; no `--set` or `--input` overrides +- Expected output: `expected/four-hour-profile.json` +- Canonical expected-output SHA-256: `0b9d5330bcb9ae8cdb30f9971b97a0420e518fe72c05a676b85692bcba087a44` + +The source equation is A. P. Dobos, *PVWatts Version 5 Manual*, NREL/TP-6A20-62641, September 2014, Section 10, Equation 8, DOI [10.2172/1158421](https://doi.org/10.2172/1158421). That citation motivates the model but does not supply its expected values. + +The baseline was generated from the project directory with: + +```console +graphcal eval --format json --root . src/pvwatts_hourly_dc_energy/main.gcl \ + | jq -S . > expected/four-hour-profile.json +``` + +## Comparison rules + +The runner parses both outputs as strict JSON and compares them semantically. Object key order is ignored; array order and length are significant; missing or additional values fail; and JSON values compare exactly by type and value. This baseline declares no numeric tolerances. + +Exact comparison intentionally detects deterministic changes across indexed calculations, temperature differences, aggregation, and custom energy-unit display. It does not prove that the synthetic operating profile or its outputs match a published PV system. + +## Repeated-run determinism + +Five consecutive evaluations with the recorded Graphcal executable and source revision produced the same canonical semantic JSON. Each result was canonicalized with `jq -S -c` and hashed with SHA-256: + +```text +0b9d5330bcb9ae8cdb30f9971b97a0420e518fe72c05a676b85692bcba087a44 +0b9d5330bcb9ae8cdb30f9971b97a0420e518fe72c05a676b85692bcba087a44 +0b9d5330bcb9ae8cdb30f9971b97a0420e518fe72c05a676b85692bcba087a44 +0b9d5330bcb9ae8cdb30f9971b97a0420e518fe72c05a676b85692bcba087a44 +0b9d5330bcb9ae8cdb30f9971b97a0420e518fe72c05a676b85692bcba087a44 +``` + +This establishes repeatability only for the recorded executable and inputs. diff --git a/projects/pvwatts-hourly-dc-energy/reference/calculation.md b/projects/pvwatts-hourly-dc-energy/reference/calculation.md deleted file mode 100644 index 88d4383..0000000 --- a/projects/pvwatts-hourly-dc-energy/reference/calculation.md +++ /dev/null @@ -1,57 +0,0 @@ -# Independent PVWatts hourly DC-energy calculation - -## Candidate generation - -This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction. The agent selected the cited public model, created a small deterministic set of illustrative operating points, wrote an original Graphcal reproduction, and performed the separate calculation below. It does not derive from a private project. Human source, privacy, calculation, and promotion review remain pull-request responsibilities. - -## Source - -A. P. Dobos, *PVWatts Version 5 Manual*, National Renewable Energy Laboratory, NREL/TP-6A20-62641, September 2014, Section 10, Equation 8, DOI [10.2172/1158421](https://doi.org/10.2172/1158421), https://www.osti.gov/biblio/1158421, accessed 2026-08-15. - -The report defines the DC module model as - -\[ -P_{dc}=\frac{I_{tr}}{1000}P_{dc0} - \left[1+\gamma(T_{cell}-T_{ref})\right], -\] - -where the reference irradiance is 1,000 W/m² and the reference cell temperature is 25 °C. A temperature difference of one degree Celsius is one kelvin, so the coefficient is represented as K⁻¹ and temperatures are stored as absolute kelvin values in Graphcal. - -## Adapted inputs - -The 5 kW nameplate rating, coefficient, and four operating points are original illustrative corpus inputs rather than copied weather or system data: - -| Period | Effective irradiance (W/m²) | Cell temperature (°C / K) | Duration (h) | -|---|---:|---:|---:| -| Low sun | 200 | 15 / 288.15 | 1 | -| Mid-morning | 600 | 25 / 298.15 | 1 | -| Solar noon | 1,000 | 45 / 318.15 | 1 | -| Afternoon | 400 | 35 / 308.15 | 1 | - -Other inputs are \(P_{dc0}=5\) kW, \(\gamma=-0.004\ \text{K}^{-1}\), \(I_{ref}=1000\) W/m², and \(T_{ref}=298.15\) K. - -This project starts at transmitted/effective irradiance and supplied cell temperature. It does not reproduce the other PVWatts submodels or calculate AC energy. - -## Independent calculation - -Applying Equation 8 independently of Graphcal: - -| Period | Irradiance factor | Temperature factor | DC power (kW) | DC energy (kWh) | -|---|---:|---:|---:|---:| -| Low sun | 0.2 | \(1+(-0.004)(15-25)=1.04\) | 1.04 | 1.04 | -| Mid-morning | 0.6 | 1.00 | 3.00 | 3.00 | -| Solar noon | 1.0 | \(1+(-0.004)(45-25)=0.92\) | 4.60 | 4.60 | -| Afternoon | 0.4 | \(1+(-0.004)(35-25)=0.96\) | 1.92 | 1.92 | - -Therefore: - -\[ -E_{dc}=1.04+3.00+4.60+1.92=10.56\ \text{kWh} - =38{,}016{,}000\ \text{J}. -\] - -The manifest checks low-sun power (1,040 W), peak power (4,600 W), total energy (38,016,000 J), and the selected display units. The narrow tolerances permit only floating-point evaluation differences. - -## Licensing and adaptation - -The equation was reimplemented from the cited NREL technical report. No report prose, figures, software, or datasets are reproduced. The operating points, source, and calculation record are original corpus content under the repository license; the report is cited for provenance and is not relicensed here. diff --git a/schema/README.md b/schema/README.md index 017c176..8906afd 100644 --- a/schema/README.md +++ b/schema/README.md @@ -98,9 +98,13 @@ kind = "reference-backed" evidence = "reference/calculation.md" [[projects.cases.expectation.assertions]] -pointer = "/node/mass_ratio/si_value" -expected = 10.0 -absolute_tolerance = 1.0 +pointer = "/node/reported_reference_evapotranspiration/display_value" +expected = 3.9 +absolute_tolerance = 1e-12 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_reference_evapotranspiration/unit" +expected = "mm_per_day" ``` A reference-backed expectation requires: @@ -110,7 +114,7 @@ A reference-backed expectation requires: `expected` is a JSON scalar representable in TOML: boolean, integer, float, or string. Numeric assertions use optional non-negative finite `absolute_tolerance` and `relative_tolerance` values, both zero by default. Non-numeric assertions are exact and cannot declare a positive tolerance. -The checked-in evidence must identify the source, assumptions, adaptations, conventions, independent calculation, and licensing status. The runner enforces the declared values but cannot establish that the evidence itself is trustworthy; human review remains required. +The checked-in evidence must identify the reliable public source that reports both the reproduced inputs and each asserted output. It must map every assertion to an exact example, page, table, test vector, or other source location; document assumptions, adaptations, conventions, source precision, rounding, unit conversions, and licensing status; and avoid asserting locally generated extra precision. A local analytical or independent calculation may corroborate the source but cannot be the sole oracle. If the source provides only an equation or method, use `stability-baseline` instead. The runner enforces the declared values but cannot establish that the evidence itself is trustworthy; human review remains required. ## Project files and paths From 70963916d825cd6dcdd37c2bfa6d0bfba75e9477 Mon Sep 17 00:00:00 2001 From: Shunichiro Nomura Date: Sun, 16 Aug 2026 03:38:29 +0900 Subject: [PATCH 3/3] Add published government calculation examples --- corpus.toml | 92 +++++++++++++++++++ .../epa-cutback-asphalt-voc-example/README.md | 5 + .../graphcal.toml | 2 + .../reference/calculation.md | 50 ++++++++++ .../epa_cutback_asphalt_voc_example/main.gcl | 30 ++++++ projects/nws-wind-chill-example/README.md | 5 + projects/nws-wind-chill-example/graphcal.toml | 2 + .../reference/calculation.md | 35 +++++++ .../src/nws_wind_chill_example/main.gcl | 9 ++ projects/osha-noise-examples/README.md | 5 + projects/osha-noise-examples/graphcal.toml | 2 + .../reference/calculation.md | 44 +++++++++ .../src/osha_noise_examples/main.gcl | 19 ++++ 13 files changed, 300 insertions(+) create mode 100644 projects/epa-cutback-asphalt-voc-example/README.md create mode 100644 projects/epa-cutback-asphalt-voc-example/graphcal.toml create mode 100644 projects/epa-cutback-asphalt-voc-example/reference/calculation.md create mode 100644 projects/epa-cutback-asphalt-voc-example/src/epa_cutback_asphalt_voc_example/main.gcl create mode 100644 projects/nws-wind-chill-example/README.md create mode 100644 projects/nws-wind-chill-example/graphcal.toml create mode 100644 projects/nws-wind-chill-example/reference/calculation.md create mode 100644 projects/nws-wind-chill-example/src/nws_wind_chill_example/main.gcl create mode 100644 projects/osha-noise-examples/README.md create mode 100644 projects/osha-noise-examples/graphcal.toml create mode 100644 projects/osha-noise-examples/reference/calculation.md create mode 100644 projects/osha-noise-examples/src/osha_noise_examples/main.gcl diff --git a/corpus.toml b/corpus.toml index 21f6b89..39a7023 100644 --- a/corpus.toml +++ b/corpus.toml @@ -195,3 +195,95 @@ absolute_tolerance = 1e-9 [[projects.cases.expectation.assertions]] pointer = "/node/total_co2_savings/unit" expected = "short_ton" + +[[projects]] +id = "nws-wind-chill-example" +path = "projects/nws-wind-chill-example" +status = "active" +domain = "weather-safety" +origin = "source-backed" +purpose = "Reproduce a wind-chill value explicitly reported by the National Weather Service." + +[[projects.cases]] +id = "zero-fifteen" +entry = "src/nws_wind_chill_example/main.gcl" + +[projects.cases.expectation] +kind = "reference-backed" +evidence = "reference/calculation.md" + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_wind_chill_fahrenheit_value/si_value" +expected = -19.0 + +[[projects]] +id = "osha-noise-examples" +path = "projects/osha-noise-examples" +status = "active" +domain = "occupational-safety" +origin = "source-backed" +purpose = "Reproduce free-field sound-level and noise-dose results reported by OSHA." + +[[projects.cases]] +id = "manual-examples" +entry = "src/osha_noise_examples/main.gcl" + +[projects.cases.expectation] +kind = "reference-backed" +evidence = "reference/calculation.md" + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_target_sound_level_dba_value/si_value" +expected = 116.0 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_eight_hour_twa_dba_value/si_value" +expected = 94.4 +absolute_tolerance = 1e-12 + +[[projects]] +id = "epa-cutback-asphalt-voc-example" +path = "projects/epa-cutback-asphalt-voc-example" +status = "active" +domain = "air-emissions" +origin = "source-backed" +purpose = "Reproduce diluent and VOC values reported in an EPA cutback-asphalt example." + +[[projects.cases]] +id = "ap-42-example" +entry = "src/epa_cutback_asphalt_voc_example/main.gcl" + +[projects.cases.expectation] +kind = "reference-backed" +evidence = "reference/calculation.md" + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_diluent_volume/display_value" +expected = 4900.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_diluent_volume/unit" +expected = "L" + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_diluent_mass/display_value" +expected = 3400.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_diluent_mass/unit" +expected = "kg" + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_voc_mass/display_value" +expected = 3200.0 +absolute_tolerance = 1e-9 + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_voc_mass/unit" +expected = "kg" + +[[projects.cases.expectation.assertions]] +pointer = "/node/reported_voc_percent_by_mass/si_value" +expected = 32.0 diff --git a/projects/epa-cutback-asphalt-voc-example/README.md b/projects/epa-cutback-asphalt-voc-example/README.md new file mode 100644 index 0000000..7ea62e5 --- /dev/null +++ b/projects/epa-cutback-asphalt-voc-example/README.md @@ -0,0 +1,5 @@ +# EPA cutback-asphalt VOC example + +This source-backed reproduction asks: **Does the U.S. EPA AP-42 cutback-asphalt calculation reproduce the diluent and volatile-organic-compound values reported in its worked example?** + +The source reports about 4,900 L of diluent, 3,400 kg of diluent, 3,200 kg of VOC emissions, and 32% VOC by cutback-asphalt mass. The project preserves the source's staged rounding. Source locations and assertion mappings are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/epa-cutback-asphalt-voc-example/graphcal.toml b/projects/epa-cutback-asphalt-voc-example/graphcal.toml new file mode 100644 index 0000000..61f536a --- /dev/null +++ b/projects/epa-cutback-asphalt-voc-example/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "epa_cutback_asphalt_voc_example" diff --git a/projects/epa-cutback-asphalt-voc-example/reference/calculation.md b/projects/epa-cutback-asphalt-voc-example/reference/calculation.md new file mode 100644 index 0000000..358c3b7 --- /dev/null +++ b/projects/epa-cutback-asphalt-voc-example/reference/calculation.md @@ -0,0 +1,50 @@ +# EPA cutback-asphalt VOC source evidence + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction from the cited public U.S. Environmental Protection Agency worked example. It does not derive from private material. Human source, privacy, adaptation, and promotion review remain pull-request responsibilities. + +## Source and published expected values + +U.S. Environmental Protection Agency, AP-42, Volume I, Chapter 4.5, “Asphalt Paving Operations,” Section 4.5.2, worked example on page 4.5-2, July 1979, reformatted January 1995, https://www.epa.gov/sites/default/files/2020-10/documents/c4s05.pdf, accessed 2026-08-16. + +The example uses: + +- 10,000 kg of rapid-cure cutback asphalt; +- 45% diluent by volume; +- diluent density of 0.7 kg/L; +- asphalt-cement density of 1.1 kg/L; and +- 95% of the diluent mass treated as evaporative VOC. + +The source solves the total-mass and volume-fraction equations and reports approximately: + +- 4,900 L of diluent; +- 3,400 kg of diluent; +- 3,200 kg of emitted VOC; and +- 32% of the cutback-asphalt mass emitted as VOC. + +Those four EPA-reported values—not locally generated higher-precision results—are the manifest's expected values. + +## Adaptation and source-to-assertion mapping + +Writing diluent volume as \(x\), asphalt-cement volume as \(y\), total mass as \(M\), diluent volume fraction as \(f\), and the two densities as \(\rho_d\) and \(\rho_a\), the source equations are + +\[ +M=\rho_dx+\rho_ay, \qquad x=f(x+y). +\] + +The model eliminates \(y\) to evaluate the same system. EPA reports staged approximate values: it first rounds diluent volume and mass, then multiplies the reported 3,400 kg by 0.95 and reports 3,200 kg. The Graphcal reporting nodes intentionally preserve that sequence instead of asserting local extra precision. + +The manifest maps the source outputs as: + +- `/node/reported_diluent_volume/display_value` = `4900.0` L; +- `/node/reported_diluent_mass/display_value` = `3400.0` kg; +- `/node/reported_voc_mass/display_value` = `3200.0` kg; +- `/node/reported_voc_percent_by_mass/si_value` = `32.0`; +- exact unit assertions require `L` and `kg` where applicable. + +Narrow display-value tolerances cover only binary unit-scaling representation and do not widen the source's hundred-unit precision. + +## Licensing and adaptation + +Only the equations and small set of numerical facts needed for the cited worked result are reimplemented. No EPA prose, figure, software, or substantial table is copied. The Graphcal source and this evidence record are original corpus content under the repository license; the EPA publication is cited for provenance and is not relicensed here. diff --git a/projects/epa-cutback-asphalt-voc-example/src/epa_cutback_asphalt_voc_example/main.gcl b/projects/epa-cutback-asphalt-voc-example/src/epa_cutback_asphalt_voc_example/main.gcl new file mode 100644 index 0000000..958c6d3 --- /dev/null +++ b/projects/epa-cutback-asphalt-voc-example/src/epa_cutback_asphalt_voc_example/main.gcl @@ -0,0 +1,30 @@ +const unit L: Volume = 0.001 m^3; + +param cutback_asphalt_mass: Mass = 10000.0 kg; +param diluent_volume_fraction: Dimensionless = 0.45; +param diluent_density: Mass / Volume = 0.7 kg/L; +param asphalt_cement_density: Mass / Volume = 1.1 kg/L; +param evaporated_diluent_fraction: Dimensionless = 0.95; + +const node volume_reporting_increment: Volume = 100.0 L; +const node mass_reporting_increment: Mass = 100.0 kg; + +node asphalt_to_diluent_volume_ratio: Dimensionless = ( + 1.0 - @diluent_volume_fraction +) / @diluent_volume_fraction; +node diluent_volume: Volume = @cutback_asphalt_mass / ( + @diluent_density + @asphalt_cement_density * @asphalt_to_diluent_volume_ratio +); +node diluent_mass: Mass = @diluent_volume * @diluent_density; +node reported_diluent_volume: Volume = round( + @diluent_volume / @volume_reporting_increment +) * @volume_reporting_increment -> L; +node reported_diluent_mass: Mass = round( + @diluent_mass / @mass_reporting_increment +) * @mass_reporting_increment -> kg; +node reported_voc_mass: Mass = round( + @reported_diluent_mass * @evaporated_diluent_fraction / @mass_reporting_increment +) * @mass_reporting_increment -> kg; +node reported_voc_percent_by_mass: Dimensionless = round( + @reported_voc_mass / @cutback_asphalt_mass * 100.0 +); diff --git a/projects/nws-wind-chill-example/README.md b/projects/nws-wind-chill-example/README.md new file mode 100644 index 0000000..11b9bff --- /dev/null +++ b/projects/nws-wind-chill-example/README.md @@ -0,0 +1,5 @@ +# NWS wind-chill example + +This source-backed reproduction asks: **Does the National Weather Service wind-chill equation reproduce the NWS example for 0 °F air and a 15 mph wind?** + +The NWS publishes both the equation and the expected whole-degree result of −19 °F. The source-to-assertion mapping and Fahrenheit adaptation are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/nws-wind-chill-example/graphcal.toml b/projects/nws-wind-chill-example/graphcal.toml new file mode 100644 index 0000000..42b3b83 --- /dev/null +++ b/projects/nws-wind-chill-example/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "nws_wind_chill_example" diff --git a/projects/nws-wind-chill-example/reference/calculation.md b/projects/nws-wind-chill-example/reference/calculation.md new file mode 100644 index 0000000..12c6ac1 --- /dev/null +++ b/projects/nws-wind-chill-example/reference/calculation.md @@ -0,0 +1,35 @@ +# NWS wind-chill source evidence + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction from the cited public National Weather Service page. It does not derive from private material. Human source, privacy, adaptation, and promotion review remain pull-request responsibilities. + +## Source and published expected value + +National Weather Service, “Understanding Wind Chill,” https://www.weather.gov/safety/cold-wind-chill-chart, accessed 2026-08-16. + +The page publishes the U.S. wind-chill equation + +\[ +W = 35.74 + 0.6215T - 35.75V^{0.16} + 0.4275TV^{0.16}, +\] + +where \(T\) is air temperature in degrees Fahrenheit and \(V\) is wind speed in miles per hour. The same page explicitly states that 0 °F air with a 15 mph wind produces a wind chill of −19 °F. + +That source-reported −19 °F value—not a locally generated higher-precision result—is the manifest's expected value. + +## Adaptation and source-to-assertion mapping + +Graphcal has no affine Fahrenheit unit, so the model explicitly names the temperature and output as conventional Fahrenheit numeric values. Wind speed remains a physical `Velocity` and is normalized by an explicitly defined mph before entering the empirical equation. + +The source presents the result to a whole degree. The model applies `round`, and the manifest maps the source output as: + +- `/node/reported_wind_chill_fahrenheit_value/si_value` = `-19.0`. + +The unrounded internal result is intentionally not asserted because the NWS page does not report those extra digits. + +The NWS defines wind chill only for temperatures at or below 50 °F and wind speeds above 3 mph. The reproduced inputs are within that domain. This case reproduces one published example and does not make a broader weather-safety claim. + +## Licensing and adaptation + +Only the published equation and one numerical example are reimplemented. No source prose, chart image, calculator software, or dataset is copied. The Graphcal source and this evidence record are original corpus content under the repository license; the NWS page is cited for provenance and is not relicensed here. diff --git a/projects/nws-wind-chill-example/src/nws_wind_chill_example/main.gcl b/projects/nws-wind-chill-example/src/nws_wind_chill_example/main.gcl new file mode 100644 index 0000000..ca41937 --- /dev/null +++ b/projects/nws-wind-chill-example/src/nws_wind_chill_example/main.gcl @@ -0,0 +1,9 @@ +const unit mph: Velocity = 0.44704 m/s; + +param air_temperature_fahrenheit_value: Dimensionless = 0.0; +param wind_speed: Velocity = 15.0 mph; + +node wind_speed_mph_value: Dimensionless = @wind_speed / 1.0 mph; +node wind_speed_factor: Dimensionless = @wind_speed_mph_value ^ 0.16; +node wind_chill_fahrenheit_value: Dimensionless = 35.74 + 0.6215 * @air_temperature_fahrenheit_value - 35.75 * @wind_speed_factor + 0.4275 * @air_temperature_fahrenheit_value * @wind_speed_factor; +node reported_wind_chill_fahrenheit_value: Dimensionless = round(@wind_chill_fahrenheit_value); diff --git a/projects/osha-noise-examples/README.md b/projects/osha-noise-examples/README.md new file mode 100644 index 0000000..6713585 --- /dev/null +++ b/projects/osha-noise-examples/README.md @@ -0,0 +1,5 @@ +# OSHA noise-calculation examples + +This source-backed reproduction asks: **Do two equations in the OSHA Technical Manual reproduce OSHA's published free-field sound-level and noise-dose examples?** + +The source reports 116 dBA at 80 ft for its aircraft-engine example and 94.4 dBA for its 183% dose example. The model reports only the source precision. The source-to-assertion mappings and logarithmic-level conventions are documented in [`reference/calculation.md`](reference/calculation.md). diff --git a/projects/osha-noise-examples/graphcal.toml b/projects/osha-noise-examples/graphcal.toml new file mode 100644 index 0000000..5c5bace --- /dev/null +++ b/projects/osha-noise-examples/graphcal.toml @@ -0,0 +1,2 @@ +[package] +name = "osha_noise_examples" diff --git a/projects/osha-noise-examples/reference/calculation.md b/projects/osha-noise-examples/reference/calculation.md new file mode 100644 index 0000000..3b23f20 --- /dev/null +++ b/projects/osha-noise-examples/reference/calculation.md @@ -0,0 +1,44 @@ +# OSHA noise-example source evidence + +## Candidate generation + +This source-backed candidate was prepared by an AI coding agent at the repository maintainer's direction from the cited public Occupational Safety and Health Administration manual. It does not derive from private material. Human source, privacy, adaptation, and promotion review remain pull-request responsibilities. + +## Source and published expected values + +Occupational Safety and Health Administration, *OSHA Technical Manual*, Section III, Chapter 5, “Noise,” Appendix B.6 and B.8, https://www.osha.gov/otm/section-3-health-hazards/chapter-5, accessed 2026-08-16. + +Appendix B.6 publishes the free-field distance equation + +\[ +L_{p,d2}=L_{p,d1}+20\log_{10}(d_1/d_2). +\] + +Its worked aircraft-engine example gives \(L_{p,d1}=120\) dBA at \(d_1=50\) ft and asks for the level at \(d_2=80\) ft. OSHA reports the result as 116 dBA. + +Appendix B.8 publishes the eight-hour dose conversion + +\[ +TWA=16.61\log_{10}(D/100)+90. +\] + +Its worked example uses \(D=183\%\) and reports an eight-hour TWA of 94.4 dBA. + +Those source-reported 116 dBA and 94.4 dBA values—not locally generated higher-precision results—are the manifest's expected values. + +## Adaptation and source-to-assertion mapping + +A-weighted decibels are logarithmic levels, not multiplicative physical quantities, so the project names them explicitly as dimensionless dBA numeric values. Distances retain the physical `Length` type and cancel to the dimensionless ratio required by the logarithm. + +The model rounds each output to the precision printed by OSHA. The manifest maps the source outputs as: + +- `/node/reported_target_sound_level_dba_value/si_value` = `116.0`, from Appendix B.6; +- `/node/reported_eight_hour_twa_dba_value/si_value` = `94.4`, from Appendix B.8. + +A narrow tolerance on 94.4 covers only binary representation of the reported decimal; it does not assert unreported precision. + +The distance equation assumes a point source in a free field without walls or obstructions, exactly as stated for the source example. This project does not generalize the result to reflective workplaces or non-point sources. + +## Licensing and adaptation + +Only two published equations and their small worked examples are reimplemented. No source prose, figures, software, or substantial table is copied. The Graphcal source and this evidence record are original corpus content under the repository license; the OSHA page is cited for provenance and is not relicensed here. diff --git a/projects/osha-noise-examples/src/osha_noise_examples/main.gcl b/projects/osha-noise-examples/src/osha_noise_examples/main.gcl new file mode 100644 index 0000000..bb2c9e3 --- /dev/null +++ b/projects/osha-noise-examples/src/osha_noise_examples/main.gcl @@ -0,0 +1,19 @@ +const unit ft: Length = 0.3048 m; + +param initial_sound_level_dba_value: Dimensionless = 120.0; +param initial_distance: Length = 50.0 ft; +param target_distance: Length = 80.0 ft; +param noise_dose_percent_value: Dimensionless = 183.0; + +const node twa_reporting_increment: Dimensionless = 0.1; + +node target_sound_level_dba_value: Dimensionless = @initial_sound_level_dba_value + 20.0 * log10( + @initial_distance / @target_distance +); +node reported_target_sound_level_dba_value: Dimensionless = round(@target_sound_level_dba_value); +node eight_hour_twa_dba_value: Dimensionless = 16.61 * log10( + @noise_dose_percent_value / 100.0 +) + 90.0; +node reported_eight_hour_twa_dba_value: Dimensionless = round( + @eight_hour_twa_dba_value / @twa_reporting_increment +) * @twa_reporting_increment;