{"abstract":"Panels appear best lit at dawn and worst at noon.","category":"Solar tracker geometry","checks":7,"contract":"Panel tilted by tilt degrees from horizontal, facing pan_az (clockwise from north). zenith = 90 - sun_el. cos(aoi) = cos(zen)cos(tilt) + sin(zen)sin(tilt)cos(sun_az - pan_az), clamped to [-1, 1]. Return [aoi degrees rounded 3, max(cos aoi, 0) rounded 4, 'front' or 'back'], or [None, 0.0, 'night'] when sun_el <= 0.","evaluation_group":"w2-solar_tracker_geometry-fixed-panel-incidence","failed_approach":"Adding the elevation to 90 puts the sun below the horizon.","family":"w2-solar_tracker_geometry-fixed-panel-incidence-zenith-from-elevation","id":"FA-93396","implementations":{"attempt":{"sha256":"a666d40b50f7959ff10e088108cbe6c152b0d50c59df2e9465e090ceb2d51e9f","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(tilt, pan_az, sun_az, sun_el):\n    if sun_el <= 0:\n        return [None, 0.0, 'night']\n    zen = math.radians(90 + sun_el)\n    t = math.radians(tilt)\n    c = math.cos(zen) * math.cos(t) + math.sin(zen) * math.sin(t) * math.cos(math.radians(sun_az - pan_az))\n    c = max(-1.0, min(1.0, c))\n    aoi = math.degrees(math.acos(c))\n    side = 'front' if c >= 0 else 'back'\n    return [round(aoi, 3), round(max(c, 0.0), 4), side]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 135, 0, 10], [101.408, 0.0, 'back']],\n  ['regression: zenith from elevation (partial repair)', [10, 225, 60, 89],\n   [10.969, 0.9817, 'front']],\n  ['control 1', [0, 180, 225, -5], [None, 0.0, 'night']],\n  ['control 2', [0, 135, 150, 45], [45.0, 0.7071, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [20, 225, 270, 3], [73.101, 0.2907, 'front']],\n  ['regression: zenith from elevation (partial repair)', [0, 90, 225, 60], [30.0, 0.866, 'front']],\n  ['control 1', [25, 180, 60, 10], [92.907, 0.0, 'back']],\n  ['control 2', [60, 225, 270, 20], [41.716, 0.7465, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 270, 225, 10], [60.095, 0.4986, 'front']],\n  ['regression: zenith from elevation (partial repair)', [10, 135, 30, 45],\n   [48.35, 0.6646, 'front']],\n  ['control 1', [60, 90, 135, 30], [38.709, 0.7803, 'front']],\n  ['control 2', [45, 270, 60, 89], [45.868, 0.6963, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 135, 100, 10], [56.376, 0.5537, 'front']],\n  ['regression: zenith from elevation (partial repair)', [20, 225, 270, 3],\n   [73.101, 0.2907, 'front']],\n  ['control 1', [45, 180, 315, 0], [None, 0.0, 'night']],\n  ['control 2', [30, 90, 225, 45], [68.754, 0.3624, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [10, 180, 100, 30], [58.767, 0.5185, 'front']],\n  ['regression: zenith from elevation (partial repair)', [30, 225, 270, 60],\n   [22.062, 0.9268, 'front']],\n  ['control 1', [45, 180, 0, 75], [60.0, 0.5, 'front']],\n  ['control 2', [45, 225, 270, -5], [None, 0.0, 'night']]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"f4667a394aa90043894e61ae9d9af1d78b772d13700aa0570b092f2fce71c482","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(tilt, pan_az, sun_az, sun_el):\n    if sun_el <= 0:\n        return [None, 0.0, 'night']\n    zen = math.radians(sun_el)\n    t = math.radians(tilt)\n    c = math.cos(zen) * math.cos(t) + math.sin(zen) * math.sin(t) * math.cos(math.radians(sun_az - pan_az))\n    c = max(-1.0, min(1.0, c))\n    aoi = math.degrees(math.acos(c))\n    side = 'front' if c >= 0 else 'back'\n    return [round(aoi, 3), round(max(c, 0.0), 4), side]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 135, 0, 10], [101.408, 0.0, 'back']],\n  ['regression: zenith from elevation (partial repair)', [10, 225, 60, 89],\n   [10.969, 0.9817, 'front']],\n  ['control 1', [0, 180, 225, -5], [None, 0.0, 'night']],\n  ['control 2', [0, 135, 150, 45], [45.0, 0.7071, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [20, 225, 270, 3], [73.101, 0.2907, 'front']],\n  ['regression: zenith from elevation (partial repair)', [0, 90, 225, 60], [30.0, 0.866, 'front']],\n  ['control 1', [25, 180, 60, 10], [92.907, 0.0, 'back']],\n  ['control 2', [60, 225, 270, 20], [41.716, 0.7465, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 270, 225, 10], [60.095, 0.4986, 'front']],\n  ['regression: zenith from elevation (partial repair)', [10, 135, 30, 45],\n   [48.35, 0.6646, 'front']],\n  ['control 1', [60, 90, 135, 30], [38.709, 0.7803, 'front']],\n  ['control 2', [45, 270, 60, 89], [45.868, 0.6963, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 135, 100, 10], [56.376, 0.5537, 'front']],\n  ['regression: zenith from elevation (partial repair)', [20, 225, 270, 3],\n   [73.101, 0.2907, 'front']],\n  ['control 1', [45, 180, 315, 0], [None, 0.0, 'night']],\n  ['control 2', [30, 90, 225, 45], [68.754, 0.3624, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [10, 180, 100, 30], [58.767, 0.5185, 'front']],\n  ['regression: zenith from elevation (partial repair)', [30, 225, 270, 60],\n   [22.062, 0.9268, 'front']],\n  ['control 1', [45, 180, 0, 75], [60.0, 0.5, 'front']],\n  ['control 2', [45, 225, 270, -5], [None, 0.0, 'night']]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"ecdbec6d2a7f8ae908d047246d0a6d26f74e990fc1e7b3fc0d75d919b52bf61d","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(tilt, pan_az, sun_az, sun_el):\n    if sun_el <= 0:\n        return [None, 0.0, 'night']\n    zen = math.radians(90 - sun_el)\n    t = math.radians(tilt)\n    c = math.cos(zen) * math.cos(t) + math.sin(zen) * math.sin(t) * math.cos(math.radians(sun_az - pan_az))\n    c = max(-1.0, min(1.0, c))\n    aoi = math.degrees(math.acos(c))\n    side = 'front' if c >= 0 else 'back'\n    return [round(aoi, 3), round(max(c, 0.0), 4), side]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 135, 0, 10], [101.408, 0.0, 'back']],\n  ['regression: zenith from elevation (partial repair)', [10, 225, 60, 89],\n   [10.969, 0.9817, 'front']],\n  ['control 1', [0, 180, 225, -5], [None, 0.0, 'night']],\n  ['control 2', [0, 135, 150, 45], [45.0, 0.7071, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [20, 225, 270, 3], [73.101, 0.2907, 'front']],\n  ['regression: zenith from elevation (partial repair)', [0, 90, 225, 60], [30.0, 0.866, 'front']],\n  ['control 1', [25, 180, 60, 10], [92.907, 0.0, 'back']],\n  ['control 2', [60, 225, 270, 20], [41.716, 0.7465, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 270, 225, 10], [60.095, 0.4986, 'front']],\n  ['regression: zenith from elevation (partial repair)', [10, 135, 30, 45],\n   [48.35, 0.6646, 'front']],\n  ['control 1', [60, 90, 135, 30], [38.709, 0.7803, 'front']],\n  ['control 2', [45, 270, 60, 89], [45.868, 0.6963, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [30, 135, 100, 10], [56.376, 0.5537, 'front']],\n  ['regression: zenith from elevation (partial repair)', [20, 225, 270, 3],\n   [73.101, 0.2907, 'front']],\n  ['control 1', [45, 180, 315, 0], [None, 0.0, 'night']],\n  ['control 2', [30, 90, 225, 45], [68.754, 0.3624, 'front']]],\n [['boundary: sun on horizon', [30, 180, 180, 0], [None, 0.0, 'night']],\n  ['normal: sun normal to panel', [30, 180, 180, 60], [0.0, 1.0, 'front']],\n  ['boundary: sun behind vertical panel', [90, 180, 0, 20], [160.0, 0.0, 'back']],\n  ['regression: zenith from elevation', [10, 180, 100, 30], [58.767, 0.5185, 'front']],\n  ['regression: zenith from elevation (partial repair)', [30, 225, 270, 60],\n   [22.062, 0.9268, 'front']],\n  ['control 1', [45, 180, 0, 75], [60.0, 0.5, 'front']],\n  ['control 2', [45, 225, 270, -5], [None, 0.0, 'night']]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"Deterministic stipulated toy contract for teaching; no claim of conformance with any standard, vendor protocol or production controller. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-solar_tracker_geometry-fixed-panel-incidence-zenith-from-elevation","generated_at":"2026-09-29T14:51:54.871102+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Single-axis and dual-axis solar trackers turn a sun direction into actuator commands; a sign, frame or limit mistake points a whole plant away from the sun or into a mechanical stop.","repair":"Use zenith = 90 - elevation.","root_cause":"The elevation is used where the zenith angle is required.","sha256":"36bba88dcc9513295eb2732b01db7d3d348813daad09fa477fe72bf8458214c5","title":"Fixed panel angle of incidence: zenith from elevation · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":42.995,"exit_code":1,"observations":[{"actual":[null,0.0,"night"],"check":"boundary: sun on horizon","expected":[null,0.0,"night"],"passed":true},{"actual":[120.0,0.0,"back"],"check":"normal: sun normal to panel","expected":[0.0,1.0,"front"],"passed":false},{"actual":[160.0,0.0,"back"],"check":"boundary: sun behind vertical panel","expected":[160.0,0.0,"back"],"passed":true},{"actual":[119.905,0.0,"back"],"check":"regression: zenith from elevation","expected":[101.408,0.0,"back"],"passed":false},{"actual":[170.962,0.0,"back"],"check":"regression: zenith from elevation (partial repair)","expected":[10.969,0.9817,"front"],"passed":false},{"actual":[null,0.0,"night"],"check":"control 1","expected":[null,0.0,"night"],"passed":true},{"actual":[135.0,0.0,"back"],"check":"control 2","expected":[45.0,0.7071,"front"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"boundary: sun on horizon\", \"actual\": [null, 0.0, \"night\"], \"expected\": [null, 0.0, \"night\"], \"passed\": true}, {\"check\": \"normal: sun normal to panel\", \"actual\": [120.0, 0.0, \"back\"], \"expected\": [0.0, 1.0, \"front\"], \"passed\": false}, {\"check\": \"boundary: sun behind vertical panel\", \"actual\": [160.0, 0.0, \"back\"], \"expected\": [160.0, 0.0, \"back\"], \"passed\": true}, {\"check\": \"regression: zenith from elevation\", \"actual\": [119.905, 0.0, \"back\"], \"expected\": [101.408, 0.0, \"back\"], \"passed\": false}, {\"check\": \"regression: zenith from elevation (partial repair)\", \"actual\": [170.962, 0.0, \"back\"], \"expected\": [10.969, 0.9817, \"front\"], \"passed\": false}, {\"check\": \"control 1\", \"actual\": [null, 0.0, \"night\"], \"expected\": [null, 0.0, \"night\"], \"passed\": true}, {\"check\": \"control 2\", \"actual\": [135.0, 0.0, \"back\"], \"expected\": [45.0, 0.7071, \"front\"], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.97,"exit_code":1,"observations":[{"actual":[null,0.0,"night"],"check":"boundary: sun on horizon","expected":[null,0.0,"night"],"passed":true},{"actual":[30.0,0.866,"front"],"check":"normal: sun normal to panel","expected":[0.0,1.0,"front"],"passed":false},{"actual":[110.0,0.0,"back"],"check":"boundary: sun behind vertical panel","expected":[160.0,0.0,"back"],"passed":false},{"actual":[37.676,0.7915,"front"],"check":"regression: zenith from elevation","expected":[101.408,0.0,"back"],"passed":false},{"actual":[98.657,0.0,"back"],"check":"regression: zenith from elevation (partial repair)","expected":[10.969,0.9817,"front"],"passed":false},{"actual":[null,0.0,"night"],"check":"control 1","expected":[null,0.0,"night"],"passed":true},{"actual":[45.0,0.7071,"front"],"check":"control 2","expected":[45.0,0.7071,"front"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"boundary: sun on horizon\", \"actual\": [null, 0.0, \"night\"], \"expected\": [null, 0.0, \"night\"], \"passed\": true}, {\"check\": \"normal: sun normal to panel\", \"actual\": [30.0, 0.866, \"front\"], \"expected\": [0.0, 1.0, \"front\"], \"passed\": false}, {\"check\": \"boundary: sun behind vertical panel\", \"actual\": [110.0, 0.0, \"back\"], \"expected\": [160.0, 0.0, \"back\"], \"passed\": false}, {\"check\": \"regression: zenith from elevation\", \"actual\": [37.676, 0.7915, \"front\"], \"expected\": [101.408, 0.0, \"back\"], \"passed\": false}, {\"check\": \"regression: zenith from elevation (partial repair)\", \"actual\": [98.657, 0.0, \"back\"], \"expected\": [10.969, 0.9817, \"front\"], \"passed\": false}, {\"check\": \"control 1\", \"actual\": [null, 0.0, \"night\"], \"expected\": [null, 0.0, \"night\"], \"passed\": true}, {\"check\": \"control 2\", \"actual\": [45.0, 0.7071, \"front\"], \"expected\": [45.0, 0.7071, \"front\"], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.46,"exit_code":0,"observations":[{"actual":[null,0.0,"night"],"check":"boundary: sun on horizon","expected":[null,0.0,"night"],"passed":true},{"actual":[0.0,1.0,"front"],"check":"normal: sun normal to panel","expected":[0.0,1.0,"front"],"passed":true},{"actual":[160.0,0.0,"back"],"check":"boundary: sun behind vertical panel","expected":[160.0,0.0,"back"],"passed":true},{"actual":[101.408,0.0,"back"],"check":"regression: zenith from elevation","expected":[101.408,0.0,"back"],"passed":true},{"actual":[10.969,0.9817,"front"],"check":"regression: zenith from elevation (partial repair)","expected":[10.969,0.9817,"front"],"passed":true},{"actual":[null,0.0,"night"],"check":"control 1","expected":[null,0.0,"night"],"passed":true},{"actual":[45.0,0.7071,"front"],"check":"control 2","expected":[45.0,0.7071,"front"],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"boundary: sun on horizon\", \"actual\": [null, 0.0, \"night\"], \"expected\": [null, 0.0, \"night\"], \"passed\": true}, {\"check\": \"normal: sun normal to panel\", \"actual\": [0.0, 1.0, \"front\"], \"expected\": [0.0, 1.0, \"front\"], \"passed\": true}, {\"check\": \"boundary: sun behind vertical panel\", \"actual\": [160.0, 0.0, \"back\"], \"expected\": [160.0, 0.0, \"back\"], \"passed\": true}, {\"check\": \"regression: zenith from elevation\", \"actual\": [101.408, 0.0, \"back\"], \"expected\": [101.408, 0.0, \"back\"], \"passed\": true}, {\"check\": \"regression: zenith from elevation (partial repair)\", \"actual\": [10.969, 0.9817, \"front\"], \"expected\": [10.969, 0.9817, \"front\"], \"passed\": true}, {\"check\": \"control 1\", \"actual\": [null, 0.0, \"night\"], \"expected\": [null, 0.0, \"night\"], \"passed\": true}, {\"check\": \"control 2\", \"actual\": [45.0, 0.7071, \"front\"], \"expected\": [45.0, 0.7071, \"front\"], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}