Problem: Multi-layer Atmospheric Temperature and Pressure Calculation

The problem requires creating Python functions to calculate atmospheric temperature (with multi-layer models and Gaussian noise) and pressure (with layer-specific corrections) at valid altitudes, including input validation and ensuring proper output types.

Background: ### Industry Background & Technical Context
#### 1. International Standard Atmosphere (ISA) Foundation
The code implements core calculations based on the **International Standard Atmosphere (ISA)**, a globally accepted benchmark model in aeronautics, meteorology, and atmospheric sciences. ISA defines the vertical distribution of temperature, pressure, and density in the Earth's atmosphere under idealized, average conditions, serving as a reference for aircraft design, weather modeling, and remote sensing applications.

#### 2. Temperature Calculation (`calculate_temperature`)
##### Atmospheric Layer Physics & Mathematical Formulations
- **Troposphere (0–11 km)**: Temperature decreases linearly with altitude at a lapse rate of 0.0065 K/m (ISA-specified), following the formula:  
  \( T(h) = T_0 - L \times h \), where \( T_0 = 288.15 \, \text{K} \) (sea-level standard temperature), \( L = 0.0065 \, \text{K/m} \), and \( h \) is altitude in meters.
- **Lower Stratosphere (11–20 km)**: Isothermal (lapse rate = 0 K/m) due to stable ozone absorption of ultraviolet radiation, keeping temperature constant at 216.65 K.
- **Middle Stratosphere (20–32 km)**: Temperature inversion (negative lapse rate of -0.001 K/m) occurs as higher ozone concentrations absorb more UV radiation, warming the air at higher altitudes: \( T(h) = 216.65 + 0.001 \times (h - 20000) \).
- **Upper Stratosphere (32–47 km)**: Stronger temperature inversion (lapse rate = -0.0028 K/m) from increased ozone heating: \( T(h) = 228.65 + 0.0028 \times (h - 32000) \).
- **Mesosphere (47–86 km)**: Temperature decreases again at 0.0028 K/m as ozone concentration drops: \( T(h) = 270.65 - 0.0028 \times (h - 47000) \).
- **Outer Space (>86 km)**: Temperature stabilizes at 161.45 K, consistent with ISA's upper-atmosphere reference values.

##### Practical Enhancements for Real-World Use
- **Gaussian Noise Addition**: A normal distribution noise (mean=0, std=0.5 K) is added to simulate measurement uncertainty from meteorological sensors or remote sensing platforms, a standard practice in data assimilation and observational meteorology.
- **Batch Processing Support**: Scalar and numpy array inputs are supported to enable batch calculation for atmospheric modeling, flight route planning, or satellite data processing workflows.
- **Input Validation**: Enforces non-negative altitude (physically meaningful, as negative altitudes correspond to below-sea-level locations with specialized atmospheric conditions) and valid input types to ensure compatibility with engineering systems.

#### 3. Pressure Calculation (`calculate_pressure`)
##### Physics-Based Formulations (Ideal Gas Law & Hydrostatic Equilibrium)
Pressure calculations derive from the **ideal gas law** (\( PV = nRT \)) and **hydrostatic equilibrium** (force balance between atmospheric pressure and gravitational pull), leading to two core cases:
- **Isothermal Layers (L=0)**: Pressure decays exponentially with altitude, modeled as:  
  \( P(h) = P_0 \times \exp\left( -\frac{gM}{RT_0} \times \Delta h \right) \), where \( g=9.80665 \, \text{m/s}^2 \) (gravity), \( M=0.0289644 \, \text{kg/mol} \) (molar mass of dry air), \( R=8.31447 \, \text{J/(mol·K)} \) (universal gas constant).  
  A humidity correction factor (\( 1 - 0.001 \times \Delta h/1000 \)) is applied to approximate the effect of water vapor, which reduces air density and pressure (humidity decreases with altitude, justifying the height-dependent correction).

- **Non-Isothermal Layers (L≠0)**: Pressure follows a power-law relationship derived from integrating the hydrostatic equation, enhanced with a second-order correction term to improve accuracy for large altitude changes:  
  The base formula is \( P(h) = P_0 \times \left( \frac{T_0}{T_0 + L\Delta h} \right)^{\frac{gM}{RL}} \).  
  The second-order correction (\( 0.5 \times (L\Delta h / T_0)^2 \)) accounts for higher-order terms in the Taylor expansion of the pressure log-form, reducing systematic error in high-altitude calculations.  
  For altitudes above 20 km, an atmospheric composition correction factor is applied to account for changing ozone and nitrogen ratios, which alter the effective molar mass of air and thus pressure.

##### Operational Constraints
- **Altitude Range Limit (0–80 km)**: The function restricts inputs to 0–80 km because ISA's standard model becomes less valid above 80 km; higher altitudes require consideration of molecular diffusion and solar radiation effects beyond the scope of this implementation.
- **Input Validation**: Ensures numeric input types and valid altitude ranges to align with engineering use cases (e.g., aircraft altitude sensors, weather balloon data).

---
### Required Import Statements
import math
import functools
import numpy as np
from typing import Union

Input/Output: The problem accepts altitude inputs: for temperature calculation, non-negative scalar (int/float) or numpy array; for pressure calculation, scalar (int/float) in [0, 80000) meters. It provides two functions: calculate_temperature computes temperature (Kelvin) via a 6-layer lapse rate model, adds Gaussian noise (mean 0, std 0.5), and returns a scalar/array matching the input type; calculate_pressure computes pressure (Pascals) via a 7-layer model with humidity correction (isothermal layers), second-order terms (linear lapse layers), and composition correction (altitudes >20000m), returning a float. Both functions validate inputs (type, range) before applying layer-specific logic to generate enhanced results.

Required dependencies:
import math
from typing import Union
import numpy as np

Sub-steps:
step_number: 1
step_description_prompt: Please write a Python function named calculate_temperature. It computes atmospheric temperature at given altitude (non-negative, scalar/array) using a multi-layer model with specific lapse rates per layer, adds Gaussian noise (mean 0, std 0.5), validates inputs, returns scalar/array matching input type.
function_header: def calculate_temperature(altitude):
test_cases: for alt, expected in [
    (0, 288.15),           # sea level
    (1000, 288.15 - 0.0065 * 1000),   # 1 km
    (11000, 288.15 - 0.0065 * 11000)  # tropopause
]:
    actual_val = calculate_temperature(alt)
    actual_val = actual_val
    rel_diff = (abs(actual_val[0] - expected[0]) + abs(actual_val[1] - expected[1])) if isinstance(actual_val, tuple) and isinstance(expected, tuple) else abs(actual_val - expected) / max(abs(expected), 1) if expected != 0 else abs(actual_val)
    assert rel_diff < 1.0 or (abs(actual_val[0] - expected[0]) + abs(actual_val[1] - expected[1])) if isinstance(actual_val, tuple) and isinstance(expected, tuple) else abs(actual_val - expected) < 10.0 or (abs(actual_val[0] - expected[0]) + abs(actual_val[1] - expected[1])) if isinstance(actual_val, tuple) and isinstance(expected, tuple) else abs(actual_val - expected) / max(abs(expected), 1) < 0.1

step_number: 2
step_description_prompt: Please write a Python function named calculate_pressure that takes altitude (Union[float, int]) and returns float pressure. It validates altitude range [0,80000), uses predefined atmospheric layers with lapse rates, applies isothermal (humidity correction) or linear lapse (second-order correction) logic per layer, then returns computed pressure.
function_header: def calculate_pressure(altitude):
test_cases: for alt, expected in [
    (0, 101325.0),  # sea level
    (1000, 101325.0 * (1 - (0.0065 * 1000) / 288.15) ** ((9.80665 * 0.0289644) / (8.31447 * 0.0065))),
    (5000, 101325.0 * (1 - (0.0065 * 5000) / 288.15) ** ((9.80665 * 0.0289644) / (8.31447 * 0.0065)))
]:
    actual_val = calculate_pressure(alt)
    actual_val = actual_val
    rel_diff = (abs(actual_val[0] - expected[0]) + abs(actual_val[1] - expected[1])) if isinstance(actual_val, tuple) and isinstance(expected, tuple) else abs(actual_val - expected) / max(abs(expected), 1) if expected != 0 else abs(actual_val)
    assert rel_diff < 1.0 or (abs(actual_val[0] - expected[0]) + abs(actual_val[1] - expected[1])) if isinstance(actual_val, tuple) and isinstance(expected, tuple) else abs(actual_val - expected) < 10.0 or (abs(actual_val[0] - expected[0]) + abs(actual_val[1] - expected[1])) if isinstance(actual_val, tuple) and isinstance(expected, tuple) else abs(actual_val - expected) / max(abs(expected), 1) < 0.1

General solution:

General tests: