Example #1
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([.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
Example #2
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
Example #3
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)
Example #4
0
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)
Example #5
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)
Example #6
0
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)
Example #7
0
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
Example #8
0
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