def create_ramp_plan(err, ramp): """ Formulate and execute on a plan to slowly add heat or cooling to the system `err` initial error (PV - SP) `ramp` the size of the ramp A ramp plan might yield MVs in this order at every timestep: [5, 0, 4, 0, 3, 0, 2, 0, 1] where err == 5 + 4 + 3 + 2 + 1 """ if ramp == 1: # basecase yield int(err) while True: yield 0 # np.arange(n).sum() == err # --> solve for n # err = (n - 1) * (n // 2) == .5 * n**2 - .5 * n # 0 = n**2 - n --> solve for n n = np.abs(np.roots([.5, -.5, 0]).max()) niter = int(ramp // (2 * n)) # 2 means add all MV in first half of ramp MV = n log.info('Initializing a ramp plan', extra=dict(ramp_size=ramp, err=err, niter=niter)) for x in range(int(n)): budget = MV for x in range(niter): budget -= MV // niter yield int(np.sign(err) * (MV // niter)) yield int(budget * np.sign(err)) MV -= 1 while True: yield 0
def create_ramp_plan(err, ramp): """ Formulate and execute on a plan to slowly add heat or cooling to the system `err` initial error (PV - SP) `ramp` the size of the ramp A ramp plan might yield MVs in this order at every timestep: [5, 0, 4, 0, 3, 0, 2, 0, 1] where err == 5 + 4 + 3 + 2 + 1 """ if ramp == 1: # basecase yield int(err) while True: yield 0 # np.arange(n).sum() == err # --> solve for n # err = (n - 1) * (n // 2) == .5 * n**2 - .5 * n # 0 = n**2 - n --> solve for n n = np.abs(np.roots([0.5, -0.5, 0]).max()) niter = int(ramp // (2 * n)) # 2 means add all MV in first half of ramp MV = n log.info("Initializing a ramp plan", extra=dict(ramp_size=ramp, err=err, niter=niter)) for x in range(int(n)): budget = MV for x in range(niter): budget -= MV // niter yield int(np.sign(err) * (MV // niter)) yield int(budget * np.sign(err)) MV -= 1 while True: yield 0
def evaluate_stop_condition(errdata, stop_condition): """ Call the user-defined function: stop_condition(errdata) If the function returns -1, do nothing. Otherwise, sys.exit. """ if stop_condition: return_code = stop_condition(list(errdata)) if return_code != -1: log.info("Stop condition triggered! Relay is terminating.", extra=dict(return_code=return_code)) sys.exit(return_code)
def main(ns): validate_ns_or_sysexit(ns) configure_logging(True) if ns.sendstats: if ns.sendstats == 'webui': add_zmq_log_handler('ipc:///tmp/relaylog') start_webui() else: add_zmq_log_handler(ns.sendstats) log.info("Starting relay!", extra={k: str(v) for k, v in ns.__dict__.items()}) metric = ns.metric() target = ns.target() errhist = window(ns.lookback) ramp_index = 0 while True: SP = next(target) # set point PV = next(metric) # process variable err = (SP - PV) log.debug('got metric value', extra=dict(PV=PV, SP=SP)) if ramp_index < ns.ramp: if ramp_index == 0: plan = create_ramp_plan(err, ns.ramp) ramp_index += 1 MV = next(plan) errdata = errhist.send(0) else: errdata = errhist.send(err) weight = calc_weight(errdata) MV = int(round(err - weight * sum(errdata) / len(errdata))) log.info( 'data', extra=dict(data=[err, weight, sum(errdata) / len(errdata)])) if MV > 0: if ns.warmer: log.debug('adding heat', extra=dict(MV=MV, err=err)) threading.Thread(target=ns.warmer, args=(MV, )).start() else: log.warn('too cold') elif MV < 0: if ns.cooler: log.debug('removing heat', extra=dict(MV=MV, err=err)) threading.Thread(target=ns.cooler, args=(MV, )).start() else: log.warn('too hot') else: log.debug('stabilized PV at setpoint', extra=dict(MV=MV, PV=PV, SP=SP)) time.sleep(ns.delay) evaluate_stop_condition(list(errdata), ns.stop_condition)
def evaluate_stop_condition(errdata, stop_condition): """ Call the user-defined function: stop_condition(errdata) If the function returns -1, do nothing. Otherwise, sys.exit. """ if stop_condition: return_code = stop_condition(list(errdata)) if return_code != -1: log.info('Stop condition triggered! Relay is terminating.', extra=dict(return_code=return_code)) sys.exit(return_code)
def main(ns): validate_ns_or_sysexit(ns) configure_logging(True) if ns.sendstats: if ns.sendstats == "webui": add_zmq_log_handler("ipc:///tmp/relaylog") start_webui() else: add_zmq_log_handler(ns.sendstats) log.info("Starting relay!", extra={k: str(v) for k, v in ns.__dict__.items()}) metric = ns.metric() target = ns.target() errhist = window(ns.lookback) ramp_index = 0 while True: SP = next(target) # set point PV = next(metric) # process variable err = SP - PV log.debug("got metric value", extra=dict(PV=PV, SP=SP)) if ramp_index < ns.ramp: if ramp_index == 0: plan = create_ramp_plan(err, ns.ramp) ramp_index += 1 MV = next(plan) errdata = errhist.send(0) else: errdata = errhist.send(err) weight = calc_weight(errdata) MV = int(round(err - weight * sum(errdata) / len(errdata))) log.info("data", extra=dict(data=[err, weight, sum(errdata) / len(errdata)])) if MV > 0: if ns.warmer: log.debug("adding heat", extra=dict(MV=MV, err=err)) threading.Thread(target=ns.warmer, args=(MV,)).start() else: log.warn("too cold") elif MV < 0: if ns.cooler: log.debug("removing heat", extra=dict(MV=MV, err=err)) threading.Thread(target=ns.cooler, args=(MV,)).start() else: log.warn("too hot") else: log.debug("stabilized PV at setpoint", extra=dict(MV=MV, PV=PV, SP=SP)) time.sleep(ns.delay) evaluate_stop_condition(list(errdata), ns.stop_condition)
def start_webui(): cwd = join(dirname(dirname(abspath(__file__))), 'web/src') log.info("Starting node.js webui in a subshell") subprocess.Popen( 'cd %s ; node index.js' % cwd, shell=True, preexec_fn=os.setsid) # guarantee that the child process exits with me
def start_webui(): cwd = join(dirname(dirname(abspath(__file__))), "web/src") log.info("Starting node.js webui in a subshell") subprocess.Popen( "cd %s ; node index.js" % cwd, shell=True, preexec_fn=os.setsid ) # guarantee that the child process exits with me