/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2013 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.FluidObjects;
import java.util.ArrayList;
import com.jaamsim.input.InputErrorException;
import com.jaamsim.input.Output;
/**
* FluidFlow tracks the flow rate between a source and a destination.
* @author Harry King
*
*/
public class FluidFlow extends FluidFlowCalculation {
private double flowAcceleration; // The rate of change of the volumetric flow rate with respect to time (m3/s2).
private ArrayList<FluidComponent> routeList; // A list of the hydraulic components in the flow, from source to destination.
private double totalFlowInertia; // The sum of Density x Length / FlowArea for the hydraulic components in the route.
private double destinationBaseInletPressure; // The base pressure at the destination's inlet.
private double destinationTargetInletPressure; // The desired inlet pressure at the destination's inlet.
{
sourceInput.setRequired(true);
destinationInput.setRequired(true);
}
public FluidFlow() {
routeList = new ArrayList<>();
}
@Override
public void earlyInit() {
super.earlyInit();
flowAcceleration = 0.0;
// Construct the list of hydraulic components in the flow path
routeList.clear();
routeList.add( this.getDestination() );
FluidComponent prev = routeList.get(0).getPrevious();
while( prev != null ) {
routeList.add(0, prev);
prev = prev.getPrevious();
}
// Confirm that the first component is the source
if( routeList.get(0) != this.getSource() ) {
throw new InputErrorException( "The source of the route is not connected to the destination by the 'Previous' keyword inputs for the individual components." );
}
// Set the Flow object for each component in the route
for( FluidComponent each : routeList ) {
each.setFluidFlow( this );
}
// Calculate the total flow inertia of the flow path
totalFlowInertia = 0.0;
for( FluidComponent each : routeList ) {
each.earlyInit(); // Needs to be called to set flowArea
totalFlowInertia += each.getLength() / each.getFlowArea();
}
totalFlowInertia *= this.getFluid().getDensity();
}
@Override
protected void calcFlowRate( FluidComponent source, FluidComponent destination, double dt ) {
// Update the flow rate
this.setFlowRate( this.getFlowRate() + flowAcceleration * dt );
// Update the flow velocity and base pressures in each component of the flow route
// (base pressure ignores the affect of acceleration)
for( FluidComponent each : routeList ) {
each.updateVelocity();
each.updateBaseInletPressure();
each.updateBaseOutletPressure();
}
// Update the flow acceleration
destinationBaseInletPressure = destination.getBaseInletPressure();
destinationTargetInletPressure = destination.getTargetInletPressure();
flowAcceleration = ( destinationBaseInletPressure
- destinationTargetInletPressure ) / totalFlowInertia;
// Update the pressure in each component of the flow route after allowing for acceleration
for( FluidComponent each : routeList ) {
each.updateInletPressure();
each.updateOutletPressure( flowAcceleration );
}
// Confirm that the pressure is now balanced
double diff = destination.getInletPressure() /
destination.getTargetInletPressure() - 1.0;
if( Math.abs( diff ) > 1.0e-4 ) {
error("Pressure did not balance correctly. Difference = %f", diff);
}
}
@Output(name = "FlowAcceleration",
description = "The time derivative of the volumetric flow rate.")
public double getFlowAcceleration( double simTime ) {
return flowAcceleration;
}
@Output(name = "FlowInertia",
description = "The sum of (density)(length)/(flow area) for the hydraulic components in the route.")
public double getFlowInertia( double simTime ) {
return totalFlowInertia;
}
}