Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

High airflow when damper is closed #612

Open
rsoo8 opened this issue Feb 2, 2024 · 2 comments
Open

High airflow when damper is closed #612

rsoo8 opened this issue Feb 2, 2024 · 2 comments
Assignees

Comments

@rsoo8
Copy link

rsoo8 commented Feb 2, 2024

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
Copy link
Collaborator

dhblum commented Feb 3, 2024

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
Copy link
Contributor

EttoreZ commented Mar 4, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants