"""Bounded browser adapter for the original synthetic climate-control model.""" import json,math,time from pathlib import Path import cooling_kernel as kernel CONTROLS = {'tau_s': {'type': 'number', 'min': 0, 'max': 1800, 'default': 900, 'step': 300, 'unit': 's'}, 'light_heat_w': {'type': 'number', 'min': 4000, 'max': 12000, 'default': 8000, 'step': 1000, 'unit': 'W'}, 'cooling_w': {'type': 'number', 'min': 8000, 'max': 16000, 'default': 12000, 'step': 1000, 'unit': 'W'}} UNITS = {'max_temp_c': '°C', 'min_temp_c': '°C', 'outside_band_h': 'h', 'iae_k_h': 'K·h', 'cooling_thermal_kwh': 'kWh thermal', 'command_actual_gap_h': 'h', 'command_total_variation': '1', 'heat_balance_residual_j': 'J', 'tau_s': 's', 'final_temp_c': '°C', 'final_rh_pct': '%', 'temp_violation_h': 'h', 'rh_violation_h': 'h', 'dehumidified_kg': 'kg', 'condensed_kg': 'kg', 'simultaneous_cooling_reheat_h': 'h', 'total_variation': '1', 'energy_residual_j': 'J', 'water_residual_kg': 'kg'} def run(name,p): if name!='cooling' or set(p)!=set(CONTROLS):raise ValueError('Unknown experiment or parameters') for k,c in CONTROLS.items(): v=p[k] if type(v) not in (int,float) or not math.isfinite(v) or not c['min']<=v<=c['max']:raise ValueError('Parameter out of range: '+k) ticks=(v-c['min'])/c['step'] if abs(ticks-round(ticks))>1e-8:raise ValueError('Parameter off step: '+k) start=time.perf_counter() config=json.loads(Path(__file__).with_name('config.json').read_text()) config.update({k:v for k,v in p.items() if k!='tau_s'}) series=[];metrics=[] if name=='cooling': values,rows=kernel.run(config,p['tau_s']) metrics=[dict(id=k,value=v,unit=UNITS[k]) for k,v in values.items()] # Keep every original 10-second point, including switching and final state. for key,unit in [('temp_c','°C'),('command','1'),('actual','1')]: series.append(dict(id=key,x=[r['time_s']/3600 for r in rows],y=[r[key] for r in rows],x_unit='h',y_unit=unit)) for key,value in [('band_low',23),('band_high',25)]:series.append(dict(id=key,x=[0,12],y=[value,value],x_unit='h',y_unit='°C')) else: values=kernel.compare(config) for mode in ('onoff','pi'): metrics.extend(dict(id=mode+'_'+k,value=v,unit=UNITS[k]) for k,v in values[mode].items() if k!='controller') for key in ('temp_violation_h','rh_violation_h','simultaneous_cooling_reheat_h','cooling_thermal_kwh','dehumidified_kg','total_variation'): series.append(dict(id=key,x=[0,1],y=[values[m][key] for m in ('onoff','pi')],x_unit='controller',y_unit=UNITS[key])) return dict(metrics=metrics,series=series,stdout='',provenance=dict(data_type='synthetic',compute_ms=(time.perf_counter()-start)*1000)) if __name__=='__main__': import argparse parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--parameters',default=json.dumps({k:c['default'] for k,c in CONTROLS.items()})) print(json.dumps(run('cooling',json.loads(parser.parse_args().parameters)),allow_nan=False))