ibpsa / project1-boptest

Building Optimization Performance Tests
Other
101 stars 66 forks source link

High airflow when damper is closed #612

Open rsoo8 opened 5 months ago

rsoo8 commented 5 months ago

In the multizone_office_simple_air test case, a closed damper reports an unusually high airflow. In the provided simulation output, the damper for the Core zone is overridden and set to 0 but the airflow still reports approximately 0.1 m3/s (360 m3/h or 210 CFM).

hvac_oveZonActCor_yDam_activate = 1
hvac_oveZonActCor_yDam_u = 0
hvac_reaZonCor_V_flow_y = ~0.1 m3/s
hvac_reaAhu_dp_sup_y = ~50 Pa

Typical case/damper leakage is under 10 CFM ( less than 0.005 m3/s) when using the standard1 inWC (250 Pa) of static pressure drop. This would be when tested in accordance to AHRI 880 - 2017 (SI) / AHRI 880 - 2017 (I-P)

My python script to generate the output.csv:

    simulator = api("https://api.boptest.net")
    test_id = requests.post(
        "https://api.boptest.net/testcases/multizone_office_simple_air/select"
    ).json()["testid"]
    print(test_id)

    try:
        name = requests.get(simulator.name + "/" + test_id).json()["payload"]["name"]
    except:
        pytest.skip("Unable to confirm the simulator is running.")
        raise

    if name != "multizone_office_simple_air":
        pytest.skip("Incorrect test case is loaded into the simulator.")

    print(name)

    # Configuration
    run_time = 60 * 60 * 1 * 1  # seconds
    time_step = 60  # seconds

    inputs = dict(
        hvac_oveZonActCor_yDam_activate=1,
        hvac_oveZonActCor_yDam_u=0,
    )
    data = {"time_period": "peak_cool_day"}

    # Set up
    measurements = dict()

    scenario = requests.get(simulator.scenario + "/" + test_id).json()["payload"]
    if (
        "time_period" not in scenario.keys()
        or scenario["time_period"] != data["time_period"]
    ):
        measurements = requests.put(simulator.scenario + "/" + test_id, data).json()[
            "payload"
        ]

    measurements = requests.post(simulator.advance + "/" + test_id, inputs).json()[
        "payload"
    ]

    seconds_after_midnight = measurements["time"] % 24 * 60 * 60

    if seconds_after_midnight < 8 * 60 * 60:
        requests.put(
            simulator.step + "/" + test_id,
            {"step": 8 * 60 * 60 - seconds_after_midnight},
        )
        measurements = requests.post(simulator.advance + "/" + test_id, inputs).json()[
            "payload"
        ]

    if requests.get(simulator.step + "/" + test_id).json()["payload"] != time_step:
        requests.put(simulator.step + "/" + test_id, {"step": time_step})

    sim_start_time = measurements["time"]

    # Start
    for _ in range(0, run_time, time_step):
        # Write rule outputs to BOPTEST inputs

        # Take a step and sleep the remainder of the time step
        measurements = requests.post(simulator.advance + "/" + test_id, inputs).json()[
            "payload"
        ]

    print(measurements)
    sim_end_time = measurements["time"]
    print("Start times: " + str(sim_start_time))
    print("End times: " + str(sim_end_time))

    # Get results
    measurements_subset = [
        "hvac_oveZonActCor_yDam_u",
        "hvac_oveZonActEas_yDam_u",
        "hvac_oveZonActNor_yDam_u",
        "hvac_oveZonActSou_yDam_u",
        "hvac_oveZonActWes_yDam_u",
    ]

    measurement_points: dict = requests.get(simulator.measurements+ "/" + test_id).json()["payload"]
    input_points: dict = requests.get(simulator.inputs+ "/" + test_id).json()["payload"]

    data = {
        #"point_names": [inputs.keys(), measurements_subset],
        "point_names": [input_points.keys(), measurement_points.keys()],
        "start_time": sim_start_time,
        "final_time": sim_end_time,
    }
    output = requests.put(simulator.results + "/" + test_id, data).json()["payload"]
    df = pd.DataFrame(output).set_index("time")

    df.to_csv("./output.csv")
dhblum commented 5 months ago

Thanks for reporting @rsoo8. We'll take a look. The damper in the box ultimately uses this damper model: https://simulationresearch.lbl.gov/modelica/releases/v10.0.0/help/Buildings_Fluid_Actuators_Dampers.html#Buildings.Fluid.Actuators.Dampers.Exponential, which has a leakage ratio parameter [ratio of flow coefficients k(y=0)/k(y=1)] = 0.0001. We could apply a smaller ratio to achieve a smaller leakage flow that's more order of magnitude with what you'd expect. But we'll have to do some testing to ensure robust simulation, as the problem will become more stiff and harder for the solver to integrate.

An additional example leakage rate reference: https://www.accutrolllc.com/wp-content/uploads/2022/03/AccuValve-Casing-Leakage-Graphs-RevB.pdf.

EttoreZ commented 4 months ago

As mentioned by @dhblum changing the leakage ratio causes the yearly simulation to increase runtime by 10x, from around 900s to around 9000s, using Dymola2024x. I have not tested with JModelica, but I assume the results will be equivalent or worse (simulation not converging). Furthermore to change the leakage parameter I had to update the Buildings model Buildings.Examples.VAVReheat.BaseClasses.VAVReheatBox, which would require an update to Buildings library . Therefore I think it would be a tricky change to implement until all models are updated to Modelica 4.0 and up to the latest library version, and compiled with different tools.