diff --git a/ThermofluidStream/Boundaries/AccelerationBoundary.mo b/ThermofluidStream/Boundaries/AccelerationBoundary.mo new file mode 100644 index 00000000..6250b104 --- /dev/null +++ b/ThermofluidStream/Boundaries/AccelerationBoundary.mo @@ -0,0 +1,88 @@ +within ThermofluidStream.Boundaries; +model AccelerationBoundary "Sets and broadcasts acceleration vector, default is + fixed in negative z-direction with length of DropOfCommons.g" + Modelica.Units.SI.Acceleration a[3]; + parameter Boolean setFromInputs = false annotation (choices(checkBox=true), Evaluate=true); + Modelica.Units.SI.Acceleration ax = 0 + annotation(Dialog(group="Time varying output signal",enable=not setFromInputs)); + Modelica.Units.SI.Acceleration ay = 0 + annotation(Dialog(group="Time varying output signal",enable=not setFromInputs)); + Modelica.Units.SI.Acceleration az = -dropOfCommons.g + annotation(Dialog(group="Time varying output signal",enable=not setFromInputs)); + Modelica.Blocks.Interfaces.RealInput ux if setFromInputs + annotation (Placement(transformation(extent={{-120,40},{-80,80}}))); + Modelica.Blocks.Interfaces.RealInput uy if setFromInputs + annotation (Placement(transformation(extent={{-120,-20},{-80,20}}))); + Modelica.Blocks.Interfaces.RealInput uz if setFromInputs + annotation (Placement(transformation(extent={{-120,-80},{-80,-40}}))); +protected + outer ThermofluidStream.DropOfCommons dropOfCommons; +equation + connect(ux,a[1]); + connect(uy,a[2]); + connect(uz,a[3]); + if not setFromInputs then + a={ax,ay,az}; + end if; + annotation (defaultComponentName="acceleration", + defaultComponentPrefixes="inner", + missingInnerMessage=" +Your model is using an outer \"acceleration\" component but +an inner \"acceleration\" component is not defined. +Use SAABdefinedMedia.AccelerationBoundary in your model +to specify system wide accelerartion.",Icon(coordinateSystem(preserveAspectRatio=false), + graphics={ + Rectangle( + extent={{-100,100},{100,-98}}, + lineColor={206,103,0}, + lineThickness=1, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{20,98},{100,18}}, + textColor={206,103,0}, + textString="a"), + Line( + points={{80,-12},{30,-80}}, + color={206,103,0}, + thickness=1), + Line( + points={{40,20},{-10,-48}}, + color={206,103,0}, + thickness=1), + Line( + points={{0,48},{-50,-20}}, + color={206,103,0}, + thickness=1), + Line( + points={{-40,80},{-90,12}}, + color={206,103,0}, + thickness=1), + Line( + points={{-90,28},{-90,12},{-74,14}}, + color={206,103,0}, + thickness=1), + Line( + points={{-50,-4},{-50,-20},{-34,-18}}, + color={206,103,0}, + thickness=1), + Line( + points={{-10,-32},{-10,-48},{6,-46}}, + color={206,103,0}, + thickness=1), + Line( + points={{30,-64},{30,-80},{46,-78}}, + color={206,103,0}, + thickness=1)}), Diagram( + coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +


This component sets and broadcasts an acceleration vector. The default is fixed in negative z-direction with length of DropOfCommons.g. The acceleration can be set either by inputs or real expressions.

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions.

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end AccelerationBoundary; diff --git a/ThermofluidStream/Boundaries/Internal/PartialTank.mo b/ThermofluidStream/Boundaries/Internal/PartialTank.mo new file mode 100644 index 00000000..d98c7c65 --- /dev/null +++ b/ThermofluidStream/Boundaries/Internal/PartialTank.mo @@ -0,0 +1,326 @@ +within ThermofluidStream.Boundaries.Internal; +partial model PartialTank "Partial Tank model for media that are partial gas and incompressible liquid" + replaceable package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.PartialSingleGasAndIncompressible + "Medium model" annotation ( + choicesAllMatching=true, Documentation(info=" +

+Medium package used in the Volume. Make sure it is the same as the +inlets and outlets the volume is connected to. +

+")); + + parameter Boolean useHeatport = false "If true heatport is added"; + parameter Modelica.Units.SI.Area A = 1 "Contact area of volume with medium" + annotation(Dialog(enable=useHeatport)); + parameter Modelica.Units.SI.CoefficientOfHeatTransfer U = 200 "Heat transfer coefficient to medium" + annotation(Dialog(enable=useHeatport)); + parameter Boolean initialize_pressure = true "If true: initialize Pressure" + annotation(Dialog(tab= "Initialization")); + parameter Modelica.Units.SI.Pressure p_start = Medium.p_default "Initial Pressure" + annotation(Dialog(tab= "Initialization", enable=initialize_pressure)); + parameter Boolean initialize_energy = false "Initialize specific inner energy with temperature or specific enthalpy condition" + annotation(Dialog(tab= "Initialization")); + parameter Modelica.Units.SI.Temperature T_start = Medium.T_default "Initial Temperature" + annotation(Dialog(tab= "Initialization", enable=initialize_energy and (not use_hstart))); + parameter Boolean use_hstart = false "True: specific enthalpy condition instead of Temperature" + annotation(Dialog(tab= "Initialization", enable=initialize_energy)); + parameter Modelica.Units.SI.SpecificEnthalpy h_start = Medium.h_default "Initial specific enthalpy" + annotation(Dialog(tab= "Initialization", enable=initialize_energy and use_hstart)); + parameter Boolean initialize_Xi = false "If true: initialize mass fractions" + annotation(Dialog(tab= "Initialization")); + parameter Medium.MassFraction Xi_0[Medium.nXi] = Medium.X_default[1:Medium.nXi] "Initial mass fraction" + annotation(Dialog(tab= "Initialization", enable=initialize_Xi)); + parameter Boolean initialize_LiquidMass = true "If true: initialize with mass of the liquid medium component. Initialize_Xi must be false." + annotation(Dialog(tab= "Initialization", enable=not initialize_Xi)); + parameter Modelica.Units.SI.Mass M_liq_start=0 "Initial mass of the liquid" + annotation(Dialog(tab= "Initialization", enable=initialize_LiquidMass)); + + parameter Utilities.Units.Inertance L = dropOfCommons.L "Inertance at inlet and outlet" + annotation (Dialog(tab="Advanced")); + parameter Real k_volume_damping(unit="1") = dropOfCommons.k_volume_damping "Damping factor multiplicator" + annotation(Dialog(tab="Advanced", group="Damping")); + parameter Modelica.Units.SI.MassFlowRate m_flow_assert(max=0) = -dropOfCommons.m_flow_reg "Assertion threshold for negative massflows" + annotation(Dialog(tab="Advanced")); + parameter Boolean usePreferredMediumStates=false "Use medium states instead of the ones differentiated in this component" + annotation(Dialog(tab="Advanced")); + parameter Modelica.Units.SI.Length outletTransition=0.01 "Width of band for smooth transition between gas and liquid at outlet" + annotation(Dialog(tab="Advanced")); + + + Interfaces.Inlet inlet[N_inlets](redeclare package Medium=Medium) + annotation (Placement(transformation(extent={{-120,-20},{-80,20}}))); + Interfaces.Outlet outlet[M_outlets](redeclare package Medium=Medium) + annotation (Placement(transformation(extent={{80,-20},{120,20}}))); + Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(Q_flow=Q_flow, T=T_heatPort) if useHeatport + annotation (Placement(transformation(extent={{-10,-90},{10,-70}}))); + + Medium.BaseProperties medium(preferredMediumStates=usePreferredMediumStates); + + Modelica.Units.SI.Volume V; + Modelica.Units.SI.Volume V_liquid; + parameter SI.Pressure p_ref = 1e5 "Reference pressure of tank when volume is measured"; + //The tank gets a bulk modulus to handle the stiffness of incompressible media better + SI.Volume V_ref(displayUnit="l") "Volume of the tank at p_ref"; + parameter SI.BulkModulus K = 5e7 "Bulk modulus of tank (used also for stiffness modulation)"; + + //Modelica.Units.SI.Volume V_gas "Gas volume in Tank"; + + //setting the state is to prohibit dynamic state selection e.g. in VolumesDirectCoupling + Modelica.Units.SI.Mass M(stateSelect=if usePreferredMediumStates then StateSelect.default else StateSelect.always) = V*medium.d; + Modelica.Units.SI.Mass MXi[Medium.nXi](each stateSelect=if usePreferredMediumStates then StateSelect.default else StateSelect.always) = M*medium.Xi; + Modelica.Units.SI.Energy U_med(stateSelect=if usePreferredMediumStates then StateSelect.default else StateSelect.always) = M*medium.u; + + Modelica.Units.SI.HeatFlowRate Q_flow; + Modelica.Units.SI.Power W_v; + parameter Modelica.Units.SI.Length tankCenter[3]={0,0,0} "Position of the tank center" annotation(Dialog(tab="General",group="Geometry")); + parameter Integer N_inlets = 2 "Number of inlets" + annotation(Dialog(tab="General",group="Geometry")); + parameter Integer M_outlets = 2 "Number of outlets" + annotation(Dialog(tab="General",group="Geometry")); + + parameter Modelica.Units.SI.Length inletPositions[N_inlets,3]={{0,0,0},{0,0,0}} "Positions of all inlets" annotation(Dialog(tab="General",group="Geometry")); + parameter Modelica.Units.SI.Length outletPositions[M_outlets,3]={{0,0,0},{0,0,0}} "Positions of all outlets" annotation(Dialog(tab="General",group="Geometry")); + Modelica.Units.SI.Length centerOfMass[3]; + + Modelica.Units.SI.Length staticHeadInlets[N_inlets] "distance perpendicular to liquid surface, 0 if above surface"; + Modelica.Units.SI.Length staticHeadOutlets[M_outlets] "distance perpendicular to liquid surface, 0 if above surface"; + Medium.AbsolutePressure staticHeadInlets_Pa_relative[N_inlets] "relative pressure to liquid surface, 0 if above surface"; + Medium.AbsolutePressure staticHeadOutlets_Pa_relative[M_outlets] "relative pressure to liquid surface, 0 if above surface"; + +Real normAcc[3]=Modelica.Math.Vectors.normalize(acceleration.a); + + + +protected + outer DropOfCommons dropOfCommons; + outer ThermofluidStream.Boundaries.AccelerationBoundary acceleration; + + Medium.AbsolutePressure p_in[N_inlets] = Medium.pressure(inlet.state); + Medium.SpecificEnthalpy h_in[N_inlets]; + Medium.MassFraction Xi_in[Medium.nXi,N_inlets]; + + Medium.ThermodynamicState state_out[M_outlets]; + Medium.SpecificEnthalpy h_out[M_outlets]; + Medium.MassFraction Xi_out[Medium.nXi,M_outlets]; + + Real d(unit="1/(m.s)") = k_volume_damping*sqrt(abs(2*L/(V*max(density_derp_h, 1e-10)))) "Friction factor for coupled boundaries"; + //Modelica.Units.SI.DerDensityByPressure density_derp_h=1e-5 "Partial derivative of density by pressure"; + Medium.DerDensityByPressure density_derp_h=(V_ref*medium.d)/(V*K) "Partial derivative of density by pressure"; + + Medium.AbsolutePressure r_damping = d*der(M); + + Medium.AbsolutePressure r[N_inlets]; + + Medium.Temperature T_heatPort; + + Medium.MassFlowRate m_flow_in[N_inlets] = inlet.m_flow; + Medium.MassFlowRate m_flow_out[M_outlets] = outlet.m_flow; + + final parameter Real ThresholdFull = 0.995 "threshold value near 1 to indicate when full"; + final parameter Real ThresholdEmpty = 0.003 "threshold value near 0 to indicate when empty"; + + Boolean fFull; + Boolean fEmpty; + Real shiftOutlet[M_outlets]; + Medium.Density liquidDensity=Medium.Incompressible.density(Medium.Incompressible.setState_pTX(medium.state.p,medium.state.T)) + "density of the liquid in the tank"; + Medium.Density gasDensity=Medium.SingleGas.density(Medium.SingleGas.setState_pTX(medium.state.p,medium.state.T)) + "density of the gas in the tank"; +initial equation + if initialize_pressure then + medium.p=p_start; + end if; + + if initialize_energy then + if use_hstart then + medium.h = h_start; + else + medium.T=T_start; + end if; + end if; + + if initialize_Xi then + medium.Xi = Xi_0; + elseif initialize_LiquidMass then + assert(V-M_liq_start/liquidDensity > 0,"Initial liquid mass is larger then the tank can contain",level = AssertionLevel.error); + medium.Xi={(V-M_liq_start/liquidDensity)*gasDensity/((V-M_liq_start/liquidDensity)*gasDensity+M_liq_start),M_liq_start/((V-M_liq_start/liquidDensity)*gasDensity+M_liq_start)}; + end if; + +equation + for i in 1:N_inlets loop + assert(m_flow_in[i] > m_flow_assert, "Negative massflow at tank inlet", dropOfCommons.assertionLevel); + end for; + for i in 1:M_outlets loop + assert(-m_flow_out[i] > m_flow_assert, "Positive massflow at tank outlet", dropOfCommons.assertionLevel); + end for; + + assert(M > 0, "Tanks might not become empty"); + + der(inlet.m_flow)*L = inlet.r - r - r_damping*ones(N_inlets); + der(outlet.m_flow)*L = outlet.r - r_damping*ones(M_outlets); + + for i in 1:N_inlets loop + staticHeadInlets_Pa_relative[i]=liquidDensity*acceleration.a*normAcc*staticHeadInlets[i]; + r[i] + p_in[i] = medium.p + max(0,staticHeadInlets_Pa_relative[i]); + + // fix potential instabilities by setting the outgoing enthalpy and mass fraction to the medium state + h_in[i] = if noEvent(m_flow_in[i] >= 0) then Medium.specificEnthalpy(inlet[i].state) else medium.h; + Xi_in[:,i] = if noEvent(m_flow_in[i] >= 0) then Medium.massFraction(inlet[i].state) else medium.Xi; + end for; + //indication on tank nearly filled with liquid + fFull = if V_liquid > ThresholdFull*V_ref then true else false; + //indication on tank nearly emptied of liquid + fEmpty = if V_liquid < ThresholdEmpty*V_ref then true else false; + + + for i in 1:M_outlets loop + // fix potential instabilities by setting the outgoing enthalpy and mass fraction to the medium state + + h_out[i] = if noEvent(-m_flow_out[i] >= 0) then Medium.specificEnthalpy( + state_out[i]) else medium.h; + Xi_out[:, i] = if noEvent(-m_flow_out[i] >= 0) then Medium.massFraction( + state_out[i]) else medium.Xi; + + staticHeadOutlets_Pa_relative[i] = liquidDensity*acceleration.a*normAcc* + staticHeadOutlets[i]; + + //due to the transition interval of the reg_step, connectors must be shifted inside the tank + //perimeters when the tank is nearly filled with liquid and there is an outlet on the surface + //or when the tank is nearly empty and there is an outlet on the surface + //The full case is moved further down to get better numeric performance with more gas remaining + if fFull and abs(staticHeadOutlets[i]) < 4*outletTransition then + shiftOutlet[i] = 3; + elseif fEmpty and abs(staticHeadOutlets[i]) < 3*outletTransition then + shiftOutlet[i] = -1; + else + shiftOutlet[i] = 0; + end if; + //liquid at outlet if static head >0, else gas, with smooth transition + state_out[i] = Medium.setState_pTX( + medium.p + max(0, staticHeadOutlets_Pa_relative[i]), + medium.T, + {ThermofluidStream.Undirected.Internal.regStep( + staticHeadOutlets[i] +shiftOutlet[i]*outletTransition, + 0, + 1, + outletTransition),ThermofluidStream.Undirected.Internal.regStep( + staticHeadOutlets[i] + shiftOutlet[i]*outletTransition, + 1, + 0, + outletTransition)}); + end for; + + + V_liquid= MXi[end]/liquidDensity; + + medium.p = p_ref + K*(V/V_ref-1); + + der(M) = sum(inlet.m_flow) + sum(outlet.m_flow); + der(U_med) = W_v + Q_flow + sum(inlet.m_flow.*h_in) + sum(outlet.m_flow.*h_out); + der(MXi) = Xi_in*inlet.m_flow + Xi_out*outlet.m_flow; + + Q_flow = U*A*(T_heatPort - medium.T); + W_v = 0; + + outlet.state = state_out; + + if not useHeatport then + T_heatPort = medium.T; + end if; + + annotation (Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse( + extent={{-56,76},{64,16}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-56,46},{64,-56}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Ellipse( + extent={{-56,-28},{64,-88}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Line( + points={{-100,0},{100,0}}, + color={28,108,200}, + thickness=0.5), + Ellipse( + extent={{-60,-20},{60,-80}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={170,213,255}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-60,50},{60,-50}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={170,213,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Ellipse( + extent={{-60,80},{60,20}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={170,213,255}, + fillPattern=FillPattern.Solid), + Line( + points={{-60,50},{-60,-52}}, + color={28,108,200}, + thickness=0.5), + Line( + points={{60,50},{60,-52}}, + color={28,108,200}, + thickness=0.5), + Ellipse(extent={{-60,24},{60,-32}}, lineColor={28,108,200}), + Line( + points={{20,100},{-24,42}}, + color={206,103,0}, + arrow={Arrow.None,Arrow.Filled}, + thickness=1), + Line( + points={{52,78},{8,20}}, + color={206,103,0}, + arrow={Arrow.None,Arrow.Filled}, + thickness=1), + Line( + points={{84,56},{40,-2}}, + color={206,103,0}, + arrow={Arrow.None,Arrow.Filled}, + thickness=1), + Text( + extent={{-120,48},{-94,6}}, + textColor={116,116,116}, + textString="%N_inlets"), + Text( + extent={{68,48},{94,6}}, + textColor={116,116,116}, + textString="%M_outlets"), + Text( + extent={{40,102},{84,70}}, + textColor={206,103,0}, + textString="a")}),Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

This Volume is the parent class for Accumulator and Receiver models that separate the two phases and are able to output gas, liquid or two-phase medium, depending on its liquid level and the height of the outlet. Numerical stiffness is handled the same way as in the VolumeFlex.

+

To complete the partialTank, equations for total tank volume V, centreOfMass, staticHeadInlets and staticHeadOutlets needs to be provided. This separation is made to make it easy to implement arbitrary geometries. In this component, medium.p is interpreted as the pressure at the liquid surface.

+

Since there is no formula to compute density_derp_h for this volume, an upper bound has to be set in the parameter density_derp_h_set. Alternativeley the derivative can be taken from the media model for all the media that implement the corresponding formula by setting density_derp_h_from_media=true (default:false)

+

The fundamental idea of the model is based on work by Hans Ellstroem (https://www.researchgate.net/profile/Soeren-Steinkellner/publication/312590863_MODELLING_AND_SIMULATION_OF_FUEL_SYSTEMS_IN_MILITARY_AIRCRAFTS/links/5884927e4585150dde47b6aa/MODELLING-AND-SIMULATION-OF-FUEL-SYSTEMS-IN-MILITARY-AIRCRAFTS.pdf).

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions.

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end PartialTank; diff --git a/ThermofluidStream/Boundaries/Internal/package.order b/ThermofluidStream/Boundaries/Internal/package.order index 9bc398bb..2dfbec49 100644 --- a/ThermofluidStream/Boundaries/Internal/package.order +++ b/ThermofluidStream/Boundaries/Internal/package.order @@ -2,3 +2,4 @@ PartialVolume PartialVolumeN PartialVolumeM InitializationMethodsPhaseSeperator +PartialTank diff --git a/ThermofluidStream/Boundaries/TankCuboid.mo b/ThermofluidStream/Boundaries/TankCuboid.mo new file mode 100644 index 00000000..c74423ce --- /dev/null +++ b/ThermofluidStream/Boundaries/TankCuboid.mo @@ -0,0 +1,137 @@ +within ThermofluidStream.Boundaries; +model TankCuboid + "This is a cuboid tank in an acceleration field for the special case of the liquid surface normal to xz-plane. " + extends Internal.PartialTank; + //Everything media related is located in the partialTank. Below is only geometry + //dependent equations for the computation of static head and, for now, a + // constant centre of mass. To complete the partialTank equations for total tank volume V, + //centreOfMass, staticHeadInlets and staticHeadOutlets needs to be provided. + //The division is made to easily implement any geometry, regardless of complexity. + + parameter Modelica.Units.SI.Length xLength "Length in x-direction" annotation(Dialog(tab="General",group="Geometry")); + parameter Modelica.Units.SI.Length yLength "Length in y-direction" annotation(Dialog(tab="General",group="Geometry")); + parameter Modelica.Units.SI.Length zLength "Length in z-direction" annotation(Dialog(tab="General",group="Geometry")); + Modelica.Units.SI.Length D; + +protected + final parameter Real eps_geometry = 0.0000001 "numerical epsilon for geometric considerations"; + + Modelica.Units.SI.Length D1; + Modelica.Units.SI.Length D2; + Modelica.Units.SI.Length D3; + Modelica.Units.SI.Length D4; + Real nx=normAcc[1]; + Real nz=normAcc[3]; + Modelica.Units.SI.Area Area = V_liquid/yLength; + Modelica.Units.SI.Area AxLimit; + Modelica.Units.SI.Area AzLimit; + +initial equation + + //check that all inlet and outlet positions are within the tank geometry + for i in 1:N_inlets loop + assert(tankCenter[1]-xLength/2<=inletPositions[i,1] and inletPositions[i,1] <= tankCenter[1]+xLength/2, "Inlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[2]-yLength/2<=inletPositions[i,2] and inletPositions[i,2] <= tankCenter[2]+yLength/2,"Inlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[3]-zLength/2<=inletPositions[i,3] and inletPositions[i,3] <= tankCenter[3]+zLength/2,"Inlet outside tank geometry",level = AssertionLevel.error); + end for; + for i in 1:M_outlets loop + assert(tankCenter[1]-xLength/2<=outletPositions[i,1] and outletPositions[i,1] <= tankCenter[1]+xLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[2]-yLength/2<=outletPositions[i,2] and outletPositions[i,2] <= tankCenter[2]+yLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[3]-zLength/2<=outletPositions[i,3] and outletPositions[i,3] <= tankCenter[3]+zLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + end for; +equation + V_ref =xLength*yLength*zLength; + + assert((Modelica.Math.Vectors.length(normAcc)>0.99 and Modelica.Math.Vectors.length(normAcc)<1.01),"Acceleration vector is not normalized",level = AssertionLevel.error); + assert(-eps_geometry <= normAcc[2] and normAcc[2] <= eps_geometry,"Acceleration in y-direction not supported by tankCuboid",level=AssertionLevel.warning); + assert(V_liquid<=V_ref,"Trying to fit more liquid into tank than it holds",level=AssertionLevel.warning); + + centerOfMass =tankCenter;//constant in first implementation + + // where is the liquid surface? The possible solutions D1 to D4 goes from small liquid volume to large liquid volume. + if nz<0 then + if nx<0 then + //small triangle of liquid + D1 =sqrt(2*abs(nx*nz)*Area); + //rectangle plus triangle of liquid, bottom mostly in z-direction + D2 =-nz*Area/xLength - nx*xLength/2; + //rectangle plus triangle of liquid, bottom mostly in x-direction + D3 =-nx*Area/zLength - nz*zLength/2; + // Full apart from small triangle of gas + D4 =-(nx*xLength + nz*zLength) - sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + else + //nx >=0 + D1 =-nx*xLength + sqrt(2*abs(nx*nz)*Area); + D2 =-nz*Area/xLength - nx*xLength/2; + D3 =nx*Area/zLength - nx*xLength - nz*zLength/2; + D4 =-nz*zLength - sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + end if; + else + //nz >=0 + if nx < 0 then + D1 =-nz*zLength + sqrt(2*abs(nx*nz)*Area); + D2 =nz*Area/xLength - nx*xLength/2 - nz*zLength; + D3 =-nx*Area/zLength - nz*zLength/2; + D4 =-nx*xLength - sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + else + //nx>=0 + D1 =-(nx*xLength + nz*zLength) + sqrt(2*abs(nx*nz)*Area); + D2 =nz*Area/xLength - nx*xLength/2 - nz*zLength; + D3 =nx*Area/zLength - nx*xLength - nz*zLength/2; + D4 =-sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + end if; + end if; + + if abs(nx) <= eps_geometry then + D =D2; + AzLimit =0; + AxLimit =0; + elseif abs(nz) <= eps_geometry then + D =D3; + AzLimit =0; + AxLimit =0; + else + AxLimit =abs(nx/nz)*xLength^2/2; + AzLimit =abs(nz/nx)*zLength^2/2; + if (Area <= AzLimit) and (Area <= AxLimit) then + D =D1; + elseif (AxLimit <= Area) and (Area <= xLength*zLength - AxLimit) then + D =D2; + elseif (AzLimit <= Area) and (Area <= xLength*zLength - AzLimit) then + D =D3; + else + D =D4; + end if; + end if; + //D is relative to origo in the tank corner chosen such that all coordinates within the tank are positive + //The distance from a point p to the surface is given by p*normAcc+D +for i in 1:N_inlets loop +// staticHeadInlets[i] =max((inletPositions[i] - (tankCenter - {xLength/2, +// yLength/2,zLength/2}))*normAcc + D, 0); + staticHeadInlets[i] =(inletPositions[i] - (tankCenter - {xLength/2, + yLength/2,zLength/2}))*normAcc + D; +end for; +for i in 1:M_outlets loop +// staticHeadOutlets[i]=max((outletPositions[i] - (tankCenter - {xLength/2, +// yLength/2,zLength/2}))*normAcc + D, 0); + staticHeadOutlets[i]=(outletPositions[i] - (tankCenter - {xLength/2, + yLength/2,zLength/2}))*normAcc + D; +end for; + + annotation (Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+", info=" +

In order to ensure that the surface is level is perpendicular to the xz-plane, the acceleration in y-direction is neglected.

+

To specify the acceleration vector, please use the AccelerationBoundary component.

+

The tank works only with media that have gas and incompressible parts contained in them.

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions

+")); +end TankCuboid; diff --git a/ThermofluidStream/Boundaries/Tests/TankFillingClosedTank.mo b/ThermofluidStream/Boundaries/Tests/TankFillingClosedTank.mo new file mode 100644 index 00000000..9ea451cd --- /dev/null +++ b/ThermofluidStream/Boundaries/Tests/TankFillingClosedTank.mo @@ -0,0 +1,143 @@ +within ThermofluidStream.Boundaries.Tests; +model TankFillingClosedTank + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=2, + M_outlets=1, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.01,0.99}, + M_liq_start=750, + outletTransition=0.001, + inletPositions={{0,0,1},{0,1,0}}, + outletPositions={{0,1,0}}, + tankCenter={0.5,0.5,0.5}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{-30,20},{-10,40}}))); + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-100,20},{-80,40}}))); + inner AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + ThermofluidStream.Processes.FlowResistance flowResistance( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-72,20},{-52,40}}))); + ThermofluidStream.Processes.FlowResistance flowResistance2( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{0,20},{20,40}}))); + TankCuboid tank1( + redeclare package Medium = Medium, + N_inlets=1, + M_outlets=1, + useHeatport=false, + initialize_pressure=true, + p_start=100000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=500, + outletTransition=0.001, + inletPositions={{0,0,-0.7}}, + outletPositions={{0,0,-0.7}}, + tankCenter={-0.5,-0.5,-0.5}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{60,-40},{40,-20}}))); + Processes.StaticHead staticHead( + redeclare package Medium = Medium, + fromPosition={0,1,0}, + toPosition={0,0,-0.7}) + annotation (Placement(transformation(extent={{40,20},{60,40}}))); + Processes.FlowResistance flowResistance1( + redeclare package Medium = Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{20,-40},{0,-20}}))); + Processes.StaticHead staticHead1( + redeclare package Medium = Medium, + fromPosition={0,0,-0.7}, + toPosition={0,1,0}) + annotation (Placement(transformation(extent={{-10,-40},{-30,-20}}))); +equation + connect(source.outlet, flowResistance.inlet) annotation (Line( + points={{-80,30},{-72,30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.outlet, tank.inlet[1]) annotation (Line( + points={{-52,30},{-50,29.5},{-30,29.5}}, + color={28,108,200}, + thickness=0.5)); + connect(tank.outlet[1], flowResistance2.inlet) annotation (Line( + points={{-10,30},{0,30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance2.outlet, staticHead.inlet) annotation (Line( + points={{20,30},{40,30}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead.outlet, tank1.inlet[1]) annotation (Line( + points={{60,30},{70,30},{70,-30},{60,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, staticHead1.inlet) annotation (Line( + points={{0,-30},{-10,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(tank1.outlet[1], flowResistance1.inlet) annotation (Line( + points={{40,-30},{20,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead1.outlet, tank.inlet[2]) annotation (Line( + points={{-30,-30},{-38,-30},{-38,30.5},{-30,30.5}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=20, __Dymola_Algorithm="Dassl"), + Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TankFillingClosedTank; diff --git a/ThermofluidStream/Boundaries/Tests/TankHeating.mo b/ThermofluidStream/Boundaries/Tests/TankHeating.mo new file mode 100644 index 00000000..ca699d5a --- /dev/null +++ b/ThermofluidStream/Boundaries/Tests/TankHeating.mo @@ -0,0 +1,174 @@ +within ThermofluidStream.Boundaries.Tests; +model TankHeating + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=2, + M_outlets=1, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.01,0.99}, + M_liq_start=750, + outletTransition=0.00001, + inletPositions={{0,0,1},{0,0,0.5}}, + outletPositions={{0,1,0}}, + tankCenter={0.5,0.5,0.5}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{-10,30},{10,50}}))); + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-100,50},{-80,70}}))); + inner AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-92,-80},{-72,-60}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + ThermofluidStream.Boundaries.Source source1( + redeclare package Medium = + Medium, + T0_par=293.15, + p0_par=103000, + Xi0_par={0,1}) + annotation (Placement(transformation(extent={{-100,10},{-80,30}}))); + ThermofluidStream.Processes.FlowResistance flowResistance( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-60,50},{-40,70}}))); + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-60,10},{-40,30}}))); + ThermofluidStream.Processes.FlowResistance flowResistance2( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{20,30},{40,50}}))); + TankCuboid tank1( + redeclare package Medium = Medium, + A=10, + U=1000, + N_inlets=1, + M_outlets=1, + useHeatport=true, + initialize_energy=true, + T_start=293.15, + initialize_Xi=true, + Xi_0={0.001,0.999}, + outletTransition=0.00001, + inletPositions={{0,0,-0.5}}, + outletPositions={{-0.5,0,-1.3}}, + tankCenter={-0.5,-0.5,-1}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{10,-40},{-10,-20}}))); + ThermofluidStream.Boundaries.Sink sink1(redeclare package Medium = + Medium, p0_par=100000) + annotation (Placement(transformation(extent={{-80,-40},{-100,-20}}))); + ThermofluidStream.Processes.FlowResistance flowResistance3( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-40,-40},{-60,-20}}))); + ThermofluidStream.Processes.StaticHead staticHead( + redeclare package Medium = Medium, + fromPosition={0,1,0}, + toPosition={0,0,-0.5}, + displayPositions=true) annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=270, + origin={62,0}))); + Modelica.Thermal.HeatTransfer.Sources.FixedHeatFlow fixedHeatFlow( + Q_flow=12000, + T_ref=318.15, + alpha=1) + annotation (Placement(transformation(extent={{-30,-78},{-10,-58}}))); +equation + connect(source.outlet, flowResistance.inlet) annotation (Line( + points={{-80,60},{-60,60}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.outlet, tank.inlet[1]) annotation (Line( + points={{-40,60},{-20,60},{-20,39.5},{-10,39.5}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet, flowResistance1.inlet) annotation (Line( + points={{-80,20},{-60,20}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, tank.inlet[2]) annotation (Line( + points={{-40,20},{-20,20},{-20,40.5},{-10,40.5}}, + color={28,108,200}, + thickness=0.5)); + connect(tank.outlet[1], flowResistance2.inlet) annotation (Line( + points={{10,40},{20,40}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance3.outlet, sink1.inlet) annotation (Line( + points={{-60,-30},{-80,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(tank1.outlet[1], flowResistance3.inlet) annotation (Line( + points={{-10,-30},{-40,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance2.outlet, staticHead.inlet) annotation (Line( + points={{40,40},{62,40},{62,10}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead.outlet, tank1.inlet[1]) annotation (Line( + points={{62,-10},{62,-30},{10,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(tank1.heatPort, fixedHeatFlow.port) + annotation (Line(points={{0,-38},{0,-68},{-10,-68}}, color={191,0,0})); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=2000, __Dymola_Algorithm="Dassl"), + Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TankHeating; diff --git a/ThermofluidStream/Boundaries/Tests/TankOverfilling.mo b/ThermofluidStream/Boundaries/Tests/TankOverfilling.mo new file mode 100644 index 00000000..fcc07a80 --- /dev/null +++ b/ThermofluidStream/Boundaries/Tests/TankOverfilling.mo @@ -0,0 +1,131 @@ +within ThermofluidStream.Boundaries.Tests; +model TankOverfilling +extends Modelica.Icons.Example; + import ThermofluidStream; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{100,-80},{80,-60}}))); + inner AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-40,0},{-20,20}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-80,0},{-60,20}}))); + ThermofluidStream.Processes.FlowResistance flowResistance( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=true, + A=0.00005)) + annotation (Placement(transformation(extent={{60,-80},{40,-60}}))); + ThermofluidStream.Processes.FlowResistance flowResistance2( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=true, + A=0.00005)) + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=-90, + origin={50,10}))); + ThermofluidStream.Boundaries.TankCuboid tank1( + redeclare package Medium = Medium, + K=30000000, + N_inlets=2, + M_outlets=1, + useHeatport=false, + initialize_pressure=true, + p_start=100000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=750, + outletTransition=0.0001, + inletPositions={{-0.1,0,0},{0,0,0}}, + outletPositions={{0,0,0}}, + tankCenter={-0.5,-0.5,-0.5}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{12,-40},{-8,-20}}))); + Processes.FlowResistance flowResistance3( + redeclare package Medium = Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=true, + A=0.00005)) + annotation (Placement(transformation(extent={{-20,-40},{-40,-20}}))); + Sink sink(redeclare package Medium = + Medium,p0_par=100000) + annotation (Placement(transformation(extent={{-58,-40},{-78,-20}}))); + ThermofluidStream.Boundaries.Source source1( + redeclare package Medium = Medium, + T0_par=295.15, + p0_par=101000, + Xi0_par={0,1}) + annotation (Placement(transformation(extent={{10,-10},{-10,10}}, + rotation=90, + origin={50,58}))); + ThermofluidStream.FlowControl.CheckValve checkValve(redeclare package Medium = Medium) + annotation (Placement(transformation(extent={{10,-10},{-10,10}}, + rotation=270, + origin={30,-50}))); +equation + connect(source.outlet, flowResistance.inlet) annotation (Line( + points={{80,-70},{60,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance3.outlet, sink.inlet) annotation (Line( + points={{-40,-30},{-58,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance2.outlet, tank1.inlet[1]) annotation (Line( + points={{50,0},{50,-30.5},{12,-30.5}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet, flowResistance2.inlet) annotation (Line( + points={{50,48},{50,20}}, + color={28,108,200}, + thickness=0.5)); + connect(tank1.outlet[1], flowResistance3.inlet) annotation (Line( + points={{-8,-30},{-20,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.outlet, checkValve.inlet) annotation (Line( + points={{40,-70},{30,-70},{30,-60}}, + color={28,108,200}, + thickness=0.5)); + connect(checkValve.outlet, tank1.inlet[2]) annotation (Line( + points={{30,-40},{30,-29.5},{12,-29.5}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=1000, __Dymola_Algorithm="Dassl"), + Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TankOverfilling; diff --git a/ThermofluidStream/Boundaries/Tests/TankSelfDraining.mo b/ThermofluidStream/Boundaries/Tests/TankSelfDraining.mo new file mode 100644 index 00000000..807511d7 --- /dev/null +++ b/ThermofluidStream/Boundaries/Tests/TankSelfDraining.mo @@ -0,0 +1,114 @@ +within ThermofluidStream.Boundaries.Tests; +model TankSelfDraining + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=2, + M_outlets=1, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=600, + outletTransition=0.001, + inletPositions={{0,0,1},{0,0,1}}, + outletPositions={{0,1,0}}, + tankCenter={0.5,0.5,0.5}, + xLength=1, + yLength=1, + zLength=1) annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-80,20},{-60,40}}))); + ThermofluidStream.Boundaries.Sink sink(redeclare package Medium = + Medium, p0_par=100000) + annotation (Placement(transformation(extent={{60,-10},{80,10}}))); + inner AccelerationBoundary acceleration( + az=-dropOfCommons.g*10) + annotation (Placement(transformation(extent={{-90,-80},{-70,-60}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-58,-82},{-38,-62}}))); + ThermofluidStream.Boundaries.Source source1( + redeclare package Medium = + Medium, + T0_par=293.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-80,-40},{-60,-20}}))); + ThermofluidStream.Processes.FlowResistance flowResistance( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-40,20},{-20,40}}))); + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-40,-40},{-20,-20}}))); + ThermofluidStream.Processes.FlowResistance flowResistance2( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03/10, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{30,-10},{50,10}}))); +equation + connect(source.outlet, flowResistance.inlet) annotation (Line( + points={{-60,30},{-40,30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.outlet, tank.inlet[1]) annotation (Line( + points={{-20,30},{-10,30},{-10,-0.5},{0,-0.5}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet, flowResistance1.inlet) annotation (Line( + points={{-60,-30},{-40,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, tank.inlet[2]) annotation (Line( + points={{-20,-30},{-10,-30},{-10,0.5},{0,0.5}}, + color={28,108,200}, + thickness=0.5)); + connect(tank.outlet[1], flowResistance2.inlet) annotation (Line( + points={{20,0},{30,0}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance2.outlet, sink.inlet) annotation (Line( + points={{50,0},{60,0}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=5000, __Dymola_Algorithm="Dassl"), + Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TankSelfDraining; diff --git a/ThermofluidStream/Boundaries/Tests/TankSelfDraining2.mo b/ThermofluidStream/Boundaries/Tests/TankSelfDraining2.mo new file mode 100644 index 00000000..c88c8fec --- /dev/null +++ b/ThermofluidStream/Boundaries/Tests/TankSelfDraining2.mo @@ -0,0 +1,144 @@ +within ThermofluidStream.Boundaries.Tests; +model TankSelfDraining2 + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-100,10},{-80,30}}))); + inner AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-20,-80},{0,-60}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-60,-80},{-40,-60}}))); + ThermofluidStream.Processes.FlowResistance flowResistance2( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-58,10},{-38,30}}))); + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=2, + M_outlets=2, + p_start=90000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=700, + outletTransition=0.001, + inletPositions={{0,0,0},{0,0,0}}, + outletPositions={{-0.5,0,-1},{0,0,-0.5}}, + tankCenter={-0.5,-0.5,-0.5}, + xLength=1, + yLength=1, + zLength=1) annotation (Placement(transformation(extent={{-8,10},{12,30}}))); + ThermofluidStream.Boundaries.Sink sink1(redeclare package Medium = + Medium, p0_par=100000) + annotation (Placement(transformation(extent={{90,30},{110,50}}))); + ThermofluidStream.Processes.FlowResistance flowResistance3( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{50,30},{70,50}}))); + ThermofluidStream.Processes.FlowResistance flowResistance4( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{32,-10},{52,10}}))); + ThermofluidStream.Boundaries.Sink sink2(redeclare package Medium = + Medium, p0_par=100000) + annotation (Placement(transformation(extent={{90,-10},{110,10}}))); + FlowControl.CheckValve checkValve(redeclare package Medium = + Medium) + annotation (Placement(transformation(extent={{62,-10},{82,10}}))); + Source source1( + redeclare package Medium = Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-102,-30},{-82,-10}}))); + Processes.FlowResistance flowResistance1( + redeclare package Medium = Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-58,-30},{-38,-10}}))); +equation + connect(flowResistance3.outlet, sink1.inlet) annotation (Line( + points={{70,40},{90,40}}, + color={28,108,200}, + thickness=0.5)); + connect(tank.outlet[1], flowResistance3.inlet) annotation (Line( + points={{12,19.5},{20,19.5},{20,40},{50,40}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance4.inlet, tank.outlet[2]) annotation (Line( + points={{32,0},{20,0},{20,20.5},{12,20.5}}, + color={28,108,200}, + thickness=0.5)); + connect(source.outlet, flowResistance2.inlet) annotation (Line( + points={{-80,20},{-58,20}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance2.outlet, tank.inlet[1]) annotation (Line( + points={{-38,20},{-36,19.5},{-8,19.5}}, + color={28,108,200}, + thickness=0.5)); + connect(sink2.inlet, checkValve.outlet) annotation (Line( + points={{90,0},{82,0}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance4.outlet, checkValve.inlet) annotation (Line( + points={{52,0},{62,0}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet, flowResistance1.inlet) annotation (Line( + points={{-82,-20},{-58,-20}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, tank.inlet[2]) annotation (Line( + points={{-38,-20},{-22,-20},{-22,20.5},{-8,20.5}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=150, __Dymola_Algorithm="Dassl"), + Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TankSelfDraining2; diff --git a/ThermofluidStream/Boundaries/Tests/package.order b/ThermofluidStream/Boundaries/Tests/package.order index d68829aa..f2806b61 100644 --- a/ThermofluidStream/Boundaries/Tests/package.order +++ b/ThermofluidStream/Boundaries/Tests/package.order @@ -5,3 +5,8 @@ TerminalSourceSink VolumesDirectCoupling DynamicBoundaries PhaseSeperator +TankFillingClosedTank +TankHeating +TankOverfilling +TankSelfDraining +TankSelfDraining2 diff --git a/ThermofluidStream/Boundaries/package.order b/ThermofluidStream/Boundaries/package.order index f58afbf6..5c9b3273 100644 --- a/ThermofluidStream/Boundaries/package.order +++ b/ThermofluidStream/Boundaries/package.order @@ -13,3 +13,5 @@ Reservoir CreateState Tests Internal +TankCuboid +AccelerationBoundary diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100/package.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100/package.mo new file mode 100644 index 00000000..377f1f1f --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100/package.mo @@ -0,0 +1,257 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +package Dowcal100 "Concentration 60 volume%, ethylene glycol-based mixed with water" + extends ThermofluidStream.Media.myMedia.Incompressible.TableBased( + mediumName="Dowcal100_60%", + T_min=Modelica.Units.Conversions.from_degC(-50), + T_max=Modelica.Units.Conversions.from_degC(175), + TinK=false, + T0=273.15, + tableConductivity = + [-50, 0.393; + -45, 0.394; + -40, 0.395; + -35, 0.395; + -30, 0.396; + -25, 0.396; + -20, 0.396; + -15, 0.396; + -10, 0.397; + -5, 0.397; + 0, 0.396; + 5, 0.396; + 10, 0.396; + 15, 0.396; + 20, 0.395; + 25, 0.395; + 30, 0.394; + 35, 0.393; + 40, 0.392; + 45, 0.391; + 50, 0.39; + 55, 0.389; + 60, 0.388; + 65, 0.387; + 70, 0.385; + 75, 0.384; + 80, 0.383; + 85, 0.381; + 90, 0.379; + 95, 0.377; + 100, 0.375; + 105, 0.373; + 110, 0.371; + 115, 0.369; + 120, 0.367; + 125, 0.365; + 130, 0.362; + 135, 0.36; + 140, 0.357; + 145, 0.354; + 150, 0.352; + 155, 0.349; + 160, 0.346; + 165, 0.343; + 170, 0.34; + 175, 0.336], + tableDensity = + [-50, 1143; + -45, 1139.1; + -40, 1135.3; + -35, 1131.5; + -30, 1127.8; + -25, 1124.2; + -20, 1120.6; + -15, 1117.1; + -10, 1113.6; + -5, 1110.2; + 0, 1106.9; + 5, 1103.6; + 10, 1100.3; + 15, 1097.1; + 20, 1094; + 25, 1090.9; + 30, 1087.9; + 35, 1084.9; + 40, 1081.9; + 45, 1079; + 50, 1076.1; + 55, 1073.3; + 60, 1070.5; + 65, 1067.7; + 70, 1065; + 75, 1062.4; + 80, 1059.7; + 85, 1057.1; + 90, 1054.6; + 95, 1052; + 100, 1049.5; + 105, 1047.1; + 110, 1044.7; + 115, 1042.3; + 120, 1039.9; + 125, 1037.6; + 130, 1035.3; + 135, 1033; + 140, 1030.8; + 145, 1028.6; + 150, 1026.4; + 155, 1024.2; + 160, 1022.1; + 165, 1020; + 170, 1017.9; + 175, 1015.9], + tableHeatCapacity = + [-50, 2900; + -45, 2920; + -40, 2940; + -35, 2960; + -30, 2980; + -25, 3000; + -20, 3020; + -15, 3040; + -10, 3060; + -5, 3080; + 0, 3100; + 5, 3120; + 10, 3140; + 15, 3160; + 20, 3180; + 25, 3210; + 30, 3230; + 35, 3250; + 40, 3270; + 45, 3290; + 50, 3310; + 55, 3330; + 60, 3350; + 65, 3370; + 70, 3390; + 75, 3410; + 80, 3430; + 85, 3450; + 90, 3470; + 95, 3490; + 100, 3510; + 105, 3530; + 110, 3550; + 115, 3580; + 120, 3600; + 125, 3620; + 130, 3640; + 135, 3660; + 140, 3680; + 145, 3700; + 150, 3720; + 155, 3740; + 160, 3760; + 165, 3780; + 170, 3800; + 175, 3820], + tableVaporPressure = + [-50, 0; + -45, 0; + -40, 0; + -35, 0; + -30, 0; + -25, 0; + -20, 100; + -15, 100; + -10, 200; + -5, 200; + 0, 400; + 5, 500; + 10, 800; + 15, 1100; + 20, 1500; + 25, 2100; + 30, 2900; + 35, 3900; + 40, 5100; + 45, 6700; + 50, 8800; + 55, 11300; + 60, 14400; + 65, 18200; + 70, 22900; + 75, 28400; + 80, 35100; + 85, 43000; + 90, 52300; + 95, 63200; + 100, 76000; + 105, 90800; + 110, 108000; + 115, 127000; + 120, 150000; + 125, 175000; + 130, 204000; + 135, 236000; + 140, 273000; + 145, 314000; + 150, 359000; + 155, 410000; + 160, 466000; + 165, 527000; + 170, 595000; + 175, 670000], + tableViscosity = + [-50, 1.5; + -45, 0.692; + -40, 0.357; + -35, 0.202; + -30, 0.122; + -25, 0.0787; + -20, 0.0532; + -15, 0.0374; + -10, 0.0273; + -5, 0.0205; + 0, 0.0158; + 5, 0.0125; + 10, 0.0101; + 15, 0.00823; + 20, 0.00684; + 25, 0.00576; + 30, 0.00491; + 35, 0.00423; + 40, 0.00369; + 45, 0.00324; + 50, 0.00286; + 55, 0.00255; + 60, 0.00229; + 65, 0.00207; + 70, 0.00188; + 75, 0.00172; + 80, 0.00157; + 85, 0.00145; + 90, 0.00134; + 95, 0.00124; + 100, 0.00116; + 105, 0.00108; + 110, 0.00101; + 115, 0.000952; + 120, 0.000897; + 125, 0.000847; + 130, 0.000802; + 135, 0.00076; + 140, 0.000723; + 145, 0.000688; + 150, 0.000657; + 155, 0.000628; + 160, 0.000601; + 165, 0.000576; + 170, 0.000553; + 175, 0.000532]); + + annotation (Documentation(info=" +

The data in the Dowcal100 media is taken from https://www.dow.com/en-us/market/mkt-building-construction/sub-build-heating-cooling-refrigeration/heat-transfer-fluid-selection-calculator.html in Jan 2024.

+

"An ethylene glycol-based heat transfer fluid used in various industrial applications, highly recommended for heating applications"

+

Density

+

+

Heat capacity

+

+

Dynamic viscosity (double the viscosity od Dowcal100E)

+

+

Thermal conductivity

+


+")); +end Dowcal100; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100/package.order b/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100/package.order new file mode 100644 index 00000000..e69de29b diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100E/package.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100E/package.mo new file mode 100644 index 00000000..2a5a7fa7 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100E/package.mo @@ -0,0 +1,257 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +package Dowcal100E "Concentration 60 volume%, ethylene glycol-based mixed with water" + extends ThermofluidStream.Media.myMedia.Incompressible.TableBased( + mediumName="Dowcal100E_60%", + T_min=Modelica.Units.Conversions.from_degC(-50), + T_max=Modelica.Units.Conversions.from_degC(175), + TinK=false, + T0=273.15, + tableConductivity = + [-50, 0.393; + -45, 0.393; + -40, 0.394; + -35, 0.394; + -30, 0.394; + -25, 0.395; + -20, 0.395; + -15, 0.395; + -10, 0.395; + -5, 0.395; + 0, 0.394; + 5, 0.394; + 10, 0.394; + 15, 0.393; + 20, 0.393; + 25, 0.392; + 30, 0.391; + 35, 0.39; + 40, 0.389; + 45, 0.388; + 50, 0.387; + 55, 0.386; + 60, 0.385; + 65, 0.384; + 70, 0.382; + 75, 0.381; + 80, 0.379; + 85, 0.377; + 90, 0.376; + 95, 0.374; + 100, 0.372; + 105, 0.37; + 110, 0.368; + 115, 0.366; + 120, 0.363; + 125, 0.361; + 130, 0.359; + 135, 0.356; + 140, 0.353; + 145, 0.351; + 150, 0.348; + 155, 0.345; + 160, 0.342; + 165, 0.339; + 170, 0.336; + 175, 0.333], + tableDensity = + [-50, 1115.3; + -45, 1113.3; + -40, 1111.1; + -35, 1108.9; + -30, 1106.5; + -25, 1104.2; + -20, 1101.7; + -15, 1099.1; + -10, 1096.5; + -5, 1093.9; + 0, 1091.1; + 5, 1088.3; + 10, 1085.5; + 15, 1082.6; + 20, 1079.6; + 25, 1076.6; + 30, 1073.5; + 35, 1070.4; + 40, 1067.3; + 45, 1064; + 50, 1060.8; + 55, 1057.5; + 60, 1054.2; + 65, 1050.8; + 70, 1047.4; + 75, 1043.9; + 80, 1040.5; + 85, 1037; + 90, 1033.4; + 95, 1029.8; + 100, 1026.2; + 105, 1022.6; + 110, 1018.9; + 115, 1015.2; + 120, 1011.5; + 125, 1007.7; + 130, 1003.9; + 135, 1000.1; + 140, 996.3; + 145, 992.4; + 150, 988.5; + 155, 984.6; + 160, 980.7; + 165, 976.8; + 170, 972.8; + 175, 968.8], + tableHeatCapacity = + [-50, 2880; + -45, 2900; + -40, 2920; + -35, 2940; + -30, 2960; + -25, 2980; + -20, 3000; + -15, 3020; + -10, 3040; + -5, 3060; + 0, 3080; + 5, 3110; + 10, 3130; + 15, 3150; + 20, 3170; + 25, 3190; + 30, 3210; + 35, 3230; + 40, 3250; + 45, 3270; + 50, 3290; + 55, 3310; + 60, 3330; + 65, 3350; + 70, 3380; + 75, 3400; + 80, 3420; + 85, 3440; + 90, 3460; + 95, 3480; + 100, 3500; + 105, 3520; + 110, 3540; + 115, 3560; + 120, 3580; + 125, 3600; + 130, 3620; + 135, 3650; + 140, 3670; + 145, 3690; + 150, 3710; + 155, 3730; + 160, 3750; + 165, 3770; + 170, 3790; + 175, 3810], + tableVaporPressure = + [-50, 0; + -45, 0; + -40, 0; + -35, 0; + -30, 0; + -25, 0; + -20, 100; + -15, 100; + -10, 200; + -5, 200; + 0, 400; + 5, 500; + 10, 800; + 15, 1100; + 20, 1500; + 25, 2100; + 30, 2800; + 35, 3800; + 40, 5100; + 45, 6700; + 50, 8700; + 55, 11200; + 60, 14300; + 65, 18100; + 70, 22700; + 75, 28200; + 80, 34800; + 85, 42600; + 90, 51900; + 95, 62700; + 100, 75400; + 105, 90100; + 110, 107000; + 115, 126000; + 120, 149000; + 125, 174000; + 130, 202000; + 135, 235000; + 140, 271000; + 145, 311000; + 150, 356000; + 155, 407000; + 160, 462000; + 165, 523000; + 170, 591000; + 175, 665000], + tableViscosity = + [-50, 0.636; + -45, 0.352; + -40, 0.208; + -35, 0.13; + -30, 0.0847; + -25, 0.0576; + -20, 0.0406; + -15, 0.0295; + -10, 0.022; + -5, 0.0168; + 0, 0.0131; + 5, 0.0104; + 10, 0.0084; + 15, 0.00689; + 20, 0.00572; + 25, 0.00481; + 30, 0.00409; + 35, 0.00351; + 40, 0.00304; + 45, 0.00266; + 50, 0.00234; + 55, 0.00208; + 60, 0.00186; + 65, 0.00167; + 70, 0.00151; + 75, 0.00137; + 80, 0.00125; + 85, 0.00114; + 90, 0.00105; + 95, 0.000971; + 100, 0.000900; + 105, 0.000838; + 110, 0.000782; + 115, 0.000732; + 120, 0.000687; + 125, 0.000647; + 130, 0.00061; + 135, 0.000577; + 140, 0.000547; + 145, 0.000520; + 150, 0.000495; + 155, 0.000472; + 160, 0.000451; + 165, 0.000432; + 170, 0.000414; + 175, 0.000397]); + + annotation (Documentation(info=" +

The data in the Dowcal100E media is taken from https://www.dow.com/en-us/market/mkt-building-construction/sub-build-heating-cooling-refrigeration/heat-transfer-fluid-selection-calculator.html in Jan 2024.

+


"An ethylene glycol-based heat transfer fluid used in various industrial applications, highly recommended for heating applications"

+

Density

+

+

Heat capacity

+

+

Dynamic viscosity (about half of Dowcal100)

+

+

Thermal conductivity

+

+")); +end Dowcal100E; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100E/package.order b/ThermofluidStream/Media/additionalMedia/Incompressible/Dowcal100E/package.order new file mode 100644 index 00000000..e69de29b diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/JP8/package.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/JP8/package.mo new file mode 100644 index 00000000..1fe316fe --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/JP8/package.mo @@ -0,0 +1,51 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +package JP8 "Jet propulsion 8, JetA with additives, typical density" + // Data from Handbook of Aviation Fuel properties, Coordinating Research Council Inc., 1983 + //Density data between -40 degC and 90 degC, linear in T, relative density data linear up to 120 degC + //density could vary with 30 % between batches, the typical density used here is an average of measured data + //Heat capacity data between 30 degC and 180 degC, linear in T + //Thermal conductivity data between -8 degC and 220 degC, linear in T + //Kinematic viscosity data between -50 and 145 degC, log(viscosity) is linear in T + //True vapor pressure data between 50 degC and 140 degC, log(VaporPressure) is linear in 1/T(in Kelvin) + extends ThermofluidStream.Media.myMedia.Incompressible.TableBased( + mediumName="Jet propulsion 8 (JetA with additives)", + T_min=Modelica.Units.Conversions.from_degC(-40), + T_max=Modelica.Units.Conversions.from_degC(120), + enthalpyOfT=true, + TinK=false, + T0=273.15, + npolDensity=1, + tableDensity=[-40,852; 90,758], + npolHeatCapacity=1, + tableHeatCapacity=[30,2000; 180,2650], + npolConductivity =1, + tableConductivity=[-8,0.12; 220,0.08], + npolViscosity = 4, + tableViscosity=[-50,0.016; -40,0.0095; -30,0.006; -20,0.0042; -10,0.0032; 30,0.0014; 70,0.0008;110,0.00053; 144,0.0004], + npolVaporPressure= 4, + tableVaporPressure=[50,1300; 72,3200; 112,12500; 143,32000]); + annotation (Documentation(info=" +

JP8

+

JP8 is a jet propulsion fuel often used in military aircraft. It is essentially the same as JetA, but with some additives that e.g. allows for higher mass flows without static electricity build up. The data of this implementation comes from Handbook of Aviation Fuel properties, Coordinating Research Council Inc.(USA), 1983. There are both more detailed property models available, for example in REFPROP, or with more attention to computational robustness, for example in Modelon´s Fuel library. The data used in this model does not take into account properties important for combustion of the fuel, only those important for transportation and heat storage.

+

 The main source of the density gives data between -40 degC and 90 degC, linear in T, but complemetary relative density data is given as linear up to 120 degC, which implies that linear extraploation can be possible above 90 degC. Observe that the density can vary with 30% between batches or over time as the ligther fractions tend to evaporate depending on manner of storage. The typical density used here is an average of measured data.

+


The heat capacity data is given between 30 degC and 180 degC, linear in T.

+


The thermal conductivity data is given between -8 degC and 220 degC, linear in T.

+


The kinematic viscosity data is given between -50 and 145 degC, with log(viscosity) linear in T.

+


The true vapor pressure data is given between 50 degC and 140 degC, with log(VaporPressure) linear in 1/T(in Kelvin).

+

Density

+

+

Heat capacity

+

+

Dynamic viscosity

+

+

Thermal conductivity

+

+", + revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end JP8; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/JP8/package.order b/ThermofluidStream/Media/additionalMedia/Incompressible/JP8/package.order new file mode 100644 index 00000000..e69de29b diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/TestDowcal100.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/TestDowcal100.mo new file mode 100644 index 00000000..9d533814 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/TestDowcal100.mo @@ -0,0 +1,34 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +model TestDowcal100 "Test Dowcal Medium model" + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.Incompressible.Dowcal100 + "Medium model (Dowcal100)"; + Medium.BaseProperties medium; + + Medium.DynamicViscosity eta=Medium.dynamicViscosity(medium.state); + Medium.ThermalConductivity lambda=Medium.thermalConductivity(medium.state); + Medium.SpecificEntropy s=Medium.specificEntropy(medium.state); + Medium.SpecificHeatCapacity cv=Medium.specificHeatCapacityCv(medium.state); + Medium.SpecificInternalEnergy u=Medium.specificInternalEnergy(medium.state); + Medium.SpecificInternalEnergy h=Medium.specificEnthalpy(medium.state); + Medium.SpecificInternalEnergy d=Medium.density(medium.state); +protected + constant Modelica.Units.SI.Time timeUnit=1; + constant Modelica.Units.SI.Temperature Ta=1; +equation + medium.p = 1.013e5; + medium.T = Medium.T_min + time/timeUnit*Ta; + annotation (__DLR_experiment(StopTime=1.01), + experiment(StopTime=225, __Dymola_Algorithm="Dassl"), + Documentation(info=" +

Density

+

+

Heat capacity

+

+

Dynamic viscosity

+

+

Thermal conductivity

+

+")); +end TestDowcal100; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/TestDowcal100E.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/TestDowcal100E.mo new file mode 100644 index 00000000..cd322350 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/TestDowcal100E.mo @@ -0,0 +1,34 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +model TestDowcal100E "Test Dowcal100E Medium model" + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.Incompressible.Dowcal100E + "Medium model (Dowcal100E)"; + Medium.BaseProperties medium; + + Medium.DynamicViscosity eta=Medium.dynamicViscosity(medium.state); + Medium.ThermalConductivity lambda=Medium.thermalConductivity(medium.state); + Medium.SpecificEntropy s=Medium.specificEntropy(medium.state); + Medium.SpecificHeatCapacity cv=Medium.specificHeatCapacityCv(medium.state); + Medium.SpecificInternalEnergy u=Medium.specificInternalEnergy(medium.state); + Medium.SpecificInternalEnergy h=Medium.specificEnthalpy(medium.state); + Medium.SpecificInternalEnergy d=Medium.density(medium.state); +protected + constant Modelica.Units.SI.Time timeUnit=1; + constant Modelica.Units.SI.Temperature Ta=1; +equation + medium.p = 1.013e5; + medium.T = Medium.T_min + time/timeUnit*Ta; + annotation (__DLR_experiment(StopTime=1.01), + experiment(StopTime=225, __Dymola_Algorithm="Dassl"), + Documentation(info=" +

Density

+

+

Heat capacity

+

+

Dynamic viscosity (about half of Dowcal100)

+

+

Thermal conductivity

+

+")); +end TestDowcal100E; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/TestJP8.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/TestJP8.mo new file mode 100644 index 00000000..278739d8 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/TestJP8.mo @@ -0,0 +1,41 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +model TestJP8 "Test JP8 Medium model" + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.Incompressible.JP8 + "Jet fuel medium model"; + Medium.BaseProperties medium; + + Medium.DynamicViscosity eta=Medium.dynamicViscosity(medium.state); + Medium.ThermalConductivity lambda=Medium.thermalConductivity(medium.state); + Medium.SpecificEntropy s=Medium.specificEntropy(medium.state); + Medium.SpecificHeatCapacity cv=Medium.specificHeatCapacityCv(medium.state); + Medium.SpecificInternalEnergy u=Medium.specificInternalEnergy(medium.state); + Medium.SpecificInternalEnergy h=Medium.specificEnthalpy(medium.state); + Medium.SpecificInternalEnergy d=Medium.density(medium.state); + Real n=Medium.nS; +protected + constant Modelica.Units.SI.Time timeUnit=1; + constant Modelica.Units.SI.Temperature Ta=1; +equation + medium.p = 1.013e5; + medium.T = Medium.T_min + time/timeUnit*Ta; + annotation ( + experiment(StopTime=225, __Dymola_Algorithm="Dassl"), + Documentation(info=" +

Density

+

+

Heat capacity

+

+

Dynamic viscosity

+

+

Thermal conductivity

+

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TestJP8; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/TestLiqLoopDowcal100.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/TestLiqLoopDowcal100.mo new file mode 100644 index 00000000..0d914880 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/TestLiqLoopDowcal100.mo @@ -0,0 +1,246 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +model TestLiqLoopDowcal100 + + replaceable package SecondaryMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package RefrigerantMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package TertiaryMedium = + ThermofluidStream.Media.additionalMedia.Incompressible.Dowcal100 + constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm1( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-12,6},{-40,-24}}))); + ThermofluidStream.HeatExchangers.DiscretizedCounterFlowHEX evaporator( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = SecondaryMedium, + redeclare model ConductionElementA = + ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX, + redeclare model ConductionElementB = + ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX_twoPhase, + initializeMassFlow=false, + nCells=10, + A=15, + V_Hex(displayUnit="m3"), + k_wall=50) annotation (Placement(transformation( + extent={{10,10},{-10,-10}}, + rotation=180, + origin={14,14}))); + + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = TertiaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{114,-4},{94,16}}))); + + ThermofluidStream.Processes.Pump pump(redeclare package Medium = + TertiaryMedium, + omega_from_input=true, + redeclare function dp_tau_pump = + ThermofluidStream.Processes.Internal.TurboComponent.dp_tau_centrifugal) + annotation (Placement(transformation(extent={{92,-82},{112,-62}}))); + + ThermofluidStream.Processes.ConductionElement conductionElement(redeclare + package Medium = TertiaryMedium) + annotation (Placement(transformation(extent={{4,-84},{24,-64}}))); + Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heating_element + annotation (Placement(transformation(extent={{-6,-58},{14,-38}}))); + Modelica.Blocks.Sources.RealExpression heat(y=40000) + annotation (Placement(transformation(extent={{-46,-60},{-26,-40}}))); + ThermofluidStream.Boundaries.Reservoir reservoir(redeclare package + Medium = + TertiaryMedium) + annotation (Placement(transformation(extent={{-52,-86},{-32,-66}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm2( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{82,6},{36,-18}}))); + ThermofluidStream.Boundaries.Source + source1(redeclare package Medium = SecondaryMedium, + temperatureFromInput=false, + T0_par=283.15, + p0_par(displayUnit="Pa") = (SecondaryMedium.saturationPressure(263.15))) + annotation (Placement(transformation(extent={{-132,34},{-112,54}}))); + ThermofluidStream.Boundaries.Sink + sink1(redeclare package Medium = SecondaryMedium, + pressureFromInput=true) + annotation (Placement(transformation(extent={{76,16},{96,36}}))); + ThermofluidStream.Processes.FlowResistance + flowResistance2( + redeclare package Medium = SecondaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{-84,34},{-64,54}}))); + + ThermofluidStream.Sensors.MultiSensor_Tpm + multiSensor_Tpm3( + redeclare package Medium = SecondaryMedium, + outputTemperature=true, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{44,26},{64,46}}))); + Modelica.Blocks.Nonlinear.Limiter limiter1(uMax=7e5, uMin=100) + annotation (Placement(transformation(extent={{144,34},{132,46}}))); + Modelica.Blocks.Continuous.PI PI1( + k=1000, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=1e5) + annotation (Placement(transformation(extent={{170,30},{150,50}}))); + Modelica.Blocks.Math.Feedback feedback1 + annotation (Placement(transformation(extent={{198,30},{178,50}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint1(y=30) + annotation (Placement(transformation(extent={{224,30},{204,50}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm + multiSensor_Tpm4( + redeclare package Medium = SecondaryMedium, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-48,42},{-24,20}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons + annotation (Placement(transformation(extent={{-102,-60},{-82,-40}}))); + Modelica.Blocks.Nonlinear.Limiter limiter2(uMax=600, uMin=50) + annotation (Placement(transformation(extent={{38,-140},{50,-128}}))); + Modelica.Blocks.Continuous.PI PI2( + k=-5, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=300) + annotation (Placement(transformation(extent={{4,-144},{24,-124}}))); + Modelica.Blocks.Math.Feedback feedback2 + annotation (Placement(transformation(extent={{-32,-124},{-12,-144}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint2(y=15) + annotation (Placement(transformation(extent={{-66,-144},{-46,-124}}))); + ThermofluidStream.Sensors.DifferenceSensor_Tp differenceSensor_Tp( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = TertiaryMedium, + outputTemperature=true) + annotation (Placement(transformation(extent={{28,-80},{48,-100}}))); + Modelica.Blocks.Math.Gain gain(k=-1) + annotation (Placement(transformation(extent={{-4,-116},{-14,-106}}))); + Modelica.Blocks.Sources.RealExpression inlet_temp(y=283.15) + annotation (Placement(transformation(extent={{-164,34},{-144,54}}))); +equation + connect(pump.outlet,flowResistance1. inlet) annotation (Line( + points={{112,-72},{142,-72},{142,6},{114,6}}, + color={28,108,200}, + thickness=0.5)); + connect(conductionElement.outlet,pump. inlet) annotation (Line( + points={{24,-74},{84,-74},{84,-88},{92,-88},{92,-72}}, + color={28,108,200}, + thickness=0.5)); + connect(heating_element.port,conductionElement. heatPort) annotation (Line( + points={{14,-48},{14,-84}}, color={191, + 0,0})); + connect(heat.y,heating_element. Q_flow) annotation (Line(points={{-25,-50},{-25, + -48},{-6,-48}}, color={0,0,127})); + connect(reservoir.outlet,conductionElement. inlet) annotation (Line( + points={{-32,-76},{-4,-76},{-4,-74},{4,-74}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm1.outlet,reservoir. inlet) annotation (Line( + points={{-40,6},{-40,14},{-54,14},{-54,-60},{-62,-60},{-62,-76},{-52,-76}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, multiSensor_Tpm2.inlet) annotation (Line( + points={{94,6},{82,6}}, + color={28,108,200}, + thickness=0.5)); + connect(evaporator.outletA, multiSensor_Tpm1.inlet) annotation (Line( + points={{4,8},{-12,8},{-12,6}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm2.outlet, evaporator.inletA) annotation (Line( + points={{36,6},{28,6},{28,8},{24,8}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet,flowResistance2. inlet) annotation (Line( + points={{-112,44},{-84,44}}, + color={28,108,200}, + thickness=0.5)); + connect(sink1.inlet,multiSensor_Tpm3. outlet) annotation (Line( + points={{76,26},{64,26}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter1.y,sink1. p0_var) + annotation (Line(points={{131.4,40},{88,40},{88,26}}, + color={0,0,127})); + connect(limiter1.u,PI1. y) + annotation (Line(points={{145.2,40},{149,40}}, color={0,0,127})); + connect(PI1.u,feedback1. y) + annotation (Line(points={{172,40},{179,40}}, color={0,0,127})); + connect(feedback1.u1,refFlow_setPoint1. y) + annotation (Line(points={{196,40},{203,40}}, color={0,0,127})); + connect(flowResistance2.outlet,multiSensor_Tpm4. inlet) annotation (Line( + points={{-64,44},{-56,44},{-56,42},{-48,42}}, + color={28,108,200}, + thickness=0.5)); + connect(evaporator.outletB, multiSensor_Tpm3.inlet) annotation (Line( + points={{24,20},{32,20},{32,26},{44,26}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm4.outlet, evaporator.inletB) annotation (Line( + points={{-24,42},{-20,42},{-20,40},{-14,40},{-14,20},{4,20}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter2.u,PI2. y) + annotation (Line(points={{36.8,-134},{25,-134}}, color={0,0,127})); + connect(limiter2.y, pump.omega_input) annotation (Line(points={{50.6,-134}, + {78,-134},{78,-138},{102,-138},{102,-84}},color={0,0,127})); + connect(multiSensor_Tpm1.T_out, feedback1.u2) annotation (Line(points={{-37.48, + -18},{-48,-18},{-48,-30},{188,-30},{188,32}}, + color={0,0,127})); + connect(feedback2.y, PI2.u) + annotation (Line(points={{-13,-134},{2,-134}}, color={0,0,127})); + connect(feedback2.u1, refFlow_setPoint2.y) + annotation (Line(points={{-30,-134},{-45,-134}}, color={0,0,127})); + connect(differenceSensor_Tp.inletA, conductionElement.inlet) annotation (Line( + points={{28,-96},{-4,-96},{-4,-74},{4,-74}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.inletB, conductionElement.outlet) annotation ( + Line( + points={{28,-84},{26,-84},{26,-74},{24,-74}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.T_out, gain.u) annotation (Line(points={{46,-94}, + {56,-94},{56,-111},{-3,-111}}, color={0,0,127})); + connect(feedback2.u2, gain.y) annotation (Line(points={{-22,-126},{-22,-111}, + {-14.5,-111}}, color={0,0,127})); + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent={{-82,-178},{192,98}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points={{-18,74},{170,-46},{-18,-158},{-18,74}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260, + 100}}))); +end TestLiqLoopDowcal100; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/TestLiqLoopJP8.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/TestLiqLoopJP8.mo new file mode 100644 index 00000000..d081525f --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/TestLiqLoopJP8.mo @@ -0,0 +1,252 @@ +within ThermofluidStream.Media.additionalMedia.Incompressible; +model TestLiqLoopJP8 + + replaceable package SecondaryMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package RefrigerantMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package TertiaryMedium = + ThermofluidStream.Media.additionalMedia.Incompressible.JP8 + constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm1( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-12,6},{-40,-24}}))); + ThermofluidStream.HeatExchangers.DiscretizedCounterFlowHEX evaporator( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = SecondaryMedium, + redeclare model ConductionElementA = + ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX, + redeclare model ConductionElementB = + ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX_twoPhase, + initializeMassFlow=false, + nCells=10, + A=15, + V_Hex(displayUnit="m3"), + k_wall=50) annotation (Placement(transformation( + extent={{10,10},{-10,-10}}, + rotation=180, + origin={14,14}))); + + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = TertiaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{114,-4},{94,16}}))); + + ThermofluidStream.Processes.Pump pump(redeclare package Medium = + TertiaryMedium, + omega_from_input=true, + redeclare function dp_tau_pump = + ThermofluidStream.Processes.Internal.TurboComponent.dp_tau_centrifugal) + annotation (Placement(transformation(extent={{92,-82},{112,-62}}))); + + ThermofluidStream.Processes.ConductionElement conductionElement(redeclare + package Medium = TertiaryMedium) + annotation (Placement(transformation(extent={{4,-84},{24,-64}}))); + Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heating_element + annotation (Placement(transformation(extent={{-6,-58},{14,-38}}))); + Modelica.Blocks.Sources.RealExpression heat(y=40000) + annotation (Placement(transformation(extent={{-46,-60},{-26,-40}}))); + ThermofluidStream.Boundaries.Reservoir reservoir(redeclare package + Medium = + TertiaryMedium) + annotation (Placement(transformation(extent={{-52,-86},{-32,-66}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm2( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{82,6},{36,-18}}))); + ThermofluidStream.Boundaries.Source + source1(redeclare package Medium = SecondaryMedium, + temperatureFromInput=false, + T0_par=283.15, + p0_par(displayUnit="Pa") = (SecondaryMedium.saturationPressure(263.15))) + annotation (Placement(transformation(extent={{-132,34},{-112,54}}))); + ThermofluidStream.Boundaries.Sink + sink1(redeclare package Medium = SecondaryMedium, + pressureFromInput=true) + annotation (Placement(transformation(extent={{76,16},{96,36}}))); + ThermofluidStream.Processes.FlowResistance + flowResistance2( + redeclare package Medium = SecondaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{-84,34},{-64,54}}))); + + ThermofluidStream.Sensors.MultiSensor_Tpm + multiSensor_Tpm3( + redeclare package Medium = SecondaryMedium, + outputTemperature=true, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{44,26},{64,46}}))); + Modelica.Blocks.Nonlinear.Limiter limiter1(uMax=7e5, uMin=100) + annotation (Placement(transformation(extent={{144,34},{132,46}}))); + Modelica.Blocks.Continuous.PI PI1( + k=1000, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=1e5) + annotation (Placement(transformation(extent={{170,30},{150,50}}))); + Modelica.Blocks.Math.Feedback feedback1 + annotation (Placement(transformation(extent={{198,30},{178,50}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint1(y=30) + annotation (Placement(transformation(extent={{224,30},{204,50}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm + multiSensor_Tpm4( + redeclare package Medium = SecondaryMedium, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-48,42},{-24,20}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons + annotation (Placement(transformation(extent={{-102,-60},{-82,-40}}))); + Modelica.Blocks.Nonlinear.Limiter limiter2(uMax=600, uMin=50) + annotation (Placement(transformation(extent={{38,-140},{50,-128}}))); + Modelica.Blocks.Continuous.PI PI2( + k=-5, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=300) + annotation (Placement(transformation(extent={{4,-144},{24,-124}}))); + Modelica.Blocks.Math.Feedback feedback2 + annotation (Placement(transformation(extent={{-32,-124},{-12,-144}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint2(y=15) + annotation (Placement(transformation(extent={{-66,-144},{-46,-124}}))); + ThermofluidStream.Sensors.DifferenceSensor_Tp differenceSensor_Tp( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = TertiaryMedium, + outputTemperature=true) + annotation (Placement(transformation(extent={{28,-80},{48,-100}}))); + Modelica.Blocks.Math.Gain gain(k=-1) + annotation (Placement(transformation(extent={{-4,-116},{-14,-106}}))); + Modelica.Blocks.Sources.RealExpression inlet_temp(y=283.15) + annotation (Placement(transformation(extent={{-164,34},{-144,54}}))); +equation + connect(pump.outlet,flowResistance1. inlet) annotation (Line( + points={{112,-72},{142,-72},{142,6},{114,6}}, + color={28,108,200}, + thickness=0.5)); + connect(conductionElement.outlet,pump. inlet) annotation (Line( + points={{24,-74},{84,-74},{84,-88},{92,-88},{92,-72}}, + color={28,108,200}, + thickness=0.5)); + connect(heating_element.port,conductionElement. heatPort) annotation (Line( + points={{14,-48},{14,-84}}, color={191, + 0,0})); + connect(heat.y,heating_element. Q_flow) annotation (Line(points={{-25,-50},{-25, + -48},{-6,-48}}, color={0,0,127})); + connect(reservoir.outlet,conductionElement. inlet) annotation (Line( + points={{-32,-76},{-4,-76},{-4,-74},{4,-74}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm1.outlet,reservoir. inlet) annotation (Line( + points={{-40,6},{-40,14},{-54,14},{-54,-60},{-62,-60},{-62,-76},{-52,-76}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, multiSensor_Tpm2.inlet) annotation (Line( + points={{94,6},{82,6}}, + color={28,108,200}, + thickness=0.5)); + connect(evaporator.outletA, multiSensor_Tpm1.inlet) annotation (Line( + points={{4,8},{-12,8},{-12,6}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm2.outlet, evaporator.inletA) annotation (Line( + points={{36,6},{28,6},{28,8},{24,8}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet,flowResistance2. inlet) annotation (Line( + points={{-112,44},{-84,44}}, + color={28,108,200}, + thickness=0.5)); + connect(sink1.inlet,multiSensor_Tpm3. outlet) annotation (Line( + points={{76,26},{64,26}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter1.y,sink1. p0_var) + annotation (Line(points={{131.4,40},{88,40},{88,26}}, + color={0,0,127})); + connect(limiter1.u,PI1. y) + annotation (Line(points={{145.2,40},{149,40}}, color={0,0,127})); + connect(PI1.u,feedback1. y) + annotation (Line(points={{172,40},{179,40}}, color={0,0,127})); + connect(feedback1.u1,refFlow_setPoint1. y) + annotation (Line(points={{196,40},{203,40}}, color={0,0,127})); + connect(flowResistance2.outlet,multiSensor_Tpm4. inlet) annotation (Line( + points={{-64,44},{-56,44},{-56,42},{-48,42}}, + color={28,108,200}, + thickness=0.5)); + connect(evaporator.outletB, multiSensor_Tpm3.inlet) annotation (Line( + points={{24,20},{32,20},{32,26},{44,26}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm4.outlet, evaporator.inletB) annotation (Line( + points={{-24,42},{-20,42},{-20,40},{-14,40},{-14,20},{4,20}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter2.u,PI2. y) + annotation (Line(points={{36.8,-134},{25,-134}}, color={0,0,127})); + connect(limiter2.y, pump.omega_input) annotation (Line(points={{50.6,-134},{78, + -134},{78,-138},{102,-138},{102,-84}}, color={0,0,127})); + connect(multiSensor_Tpm1.T_out, feedback1.u2) annotation (Line(points={{-37.48, + -18},{-48,-18},{-48,-30},{188,-30},{188,32}}, + color={0,0,127})); + connect(feedback2.y, PI2.u) + annotation (Line(points={{-13,-134},{2,-134}}, color={0,0,127})); + connect(feedback2.u1, refFlow_setPoint2.y) + annotation (Line(points={{-30,-134},{-45,-134}}, color={0,0,127})); + connect(differenceSensor_Tp.inletA, conductionElement.inlet) annotation (Line( + points={{28,-96},{-4,-96},{-4,-74},{4,-74}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.inletB, conductionElement.outlet) annotation ( + Line( + points={{28,-84},{26,-84},{26,-74},{24,-74}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.T_out, gain.u) annotation (Line(points={{46,-94},{ + 56,-94},{56,-111},{-3,-111}}, color={0,0,127})); + connect(feedback2.u2, gain.y) annotation (Line(points={{-22,-126},{-22,-111}, + {-14.5,-111}}, color={0,0,127})); + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent={{-82,-178},{192,98}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points={{-18,74},{170,-46},{-18,-158},{-18,74}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260, + 100}})),Documentation( revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TestLiqLoopJP8; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/package.mo b/ThermofluidStream/Media/additionalMedia/Incompressible/package.mo new file mode 100644 index 00000000..56feae61 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/package.mo @@ -0,0 +1,4 @@ +within ThermofluidStream.Media.additionalMedia; +package Incompressible + extends Modelica.Icons.VariantsPackage; +end Incompressible; diff --git a/ThermofluidStream/Media/additionalMedia/Incompressible/package.order b/ThermofluidStream/Media/additionalMedia/Incompressible/package.order new file mode 100644 index 00000000..13098926 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/Incompressible/package.order @@ -0,0 +1,8 @@ +Dowcal100 +TestDowcal100 +TestLiqLoopDowcal100 +Dowcal100E +JP8 +TestJP8 +TestLiqLoopJP8 +TestDowcal100E diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_density_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_density_T.png new file mode 100644 index 00000000..d83315fc Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_density_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_dynVis_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_dynVis_T.png new file mode 100644 index 00000000..43266565 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_dynVis_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_specHeat_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_specHeat_T.png new file mode 100644 index 00000000..d9e91d77 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_specHeat_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_thermCond.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_thermCond.png new file mode 100644 index 00000000..74e43517 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100E_thermCond.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_density_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_density_T.png new file mode 100644 index 00000000..9b402906 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_density_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_dynVis_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_dynVis_T.png new file mode 100644 index 00000000..1651cb4b Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_dynVis_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_specHeat_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_specHeat_T.png new file mode 100644 index 00000000..13107542 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_specHeat_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_thermCond_T.png b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_thermCond_T.png new file mode 100644 index 00000000..73b82bca Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestDowcal100_thermCond_T.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_density.png b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_density.png new file mode 100644 index 00000000..c246ca9b Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_density.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_dynVis.png b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_dynVis.png new file mode 100644 index 00000000..d7c5a38d Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_dynVis.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_specHeat.png b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_specHeat.png new file mode 100644 index 00000000..9f1910b8 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_specHeat.png differ diff --git a/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_thermCond.png b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_thermCond.png new file mode 100644 index 00000000..74b0b7b1 Binary files /dev/null and b/ThermofluidStream/Media/additionalMedia/Resources/TestJP8_thermCond.png differ diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestJP8DryAir.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestJP8DryAir.mo new file mode 100644 index 00000000..e7804d30 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestJP8DryAir.mo @@ -0,0 +1,50 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.Examples; +model TestJP8DryAir "Test JP8DryAir Medium model" + extends Modelica.Icons.Example; + package Medium = + + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir + "Jet fuel medium model"; + Medium.BaseProperties medium; + Medium.ThermodynamicState state2; + String[:] name = Medium.substanceNames; + Medium.DynamicViscosity eta=Medium.dynamicViscosity(medium.state); + Medium.ThermalConductivity lambda=Medium.thermalConductivity(medium.state); + Medium.SpecificEntropy s=Medium.specificEntropy(medium.state); + Medium.SpecificHeatCapacity cv=Medium.specificHeatCapacityCv(medium.state); + Medium.SpecificInternalEnergy u=Medium.specificInternalEnergy(medium.state); + Medium.SpecificInternalEnergy h=Medium.specificEnthalpy(medium.state); + Medium.Density d=Medium.density(medium.state); + Medium.Density dG=Medium.SingleGas.density(medium.state); + Medium.Density dL=Medium.Incompressible.density(medium.state); + Real n=Medium.nS; + Real nXi=Medium.nXi; + +protected + constant Modelica.Units.SI.Time timeUnit=1; + constant Modelica.Units.SI.Temperature Ta=1; +equation + medium.p = 1.013e5; + medium.T = 233.15 + time/timeUnit*Ta; + medium.X={0.001,0.999}; + state2=Medium.setState_phX(medium.p,medium.h,medium.X); + + annotation ( + experiment(StopTime=159, __Dymola_Algorithm="Dassl"), + Documentation(info=" +

Density

+

+

Heat capacity

+

+

Dynamic viscosity

+

+

Thermal conductivity

+

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TestJP8DryAir; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestLiqLoopJP8DryAir.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestLiqLoopJP8DryAir.mo new file mode 100644 index 00000000..33a51088 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestLiqLoopJP8DryAir.mo @@ -0,0 +1,251 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.Examples; +model TestLiqLoopJP8DryAir + + replaceable package SecondaryMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package RefrigerantMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package TertiaryMedium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir + constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm1( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-14,8},{-38,-16}}))); + ThermofluidStream.HeatExchangers.DiscretizedCounterFlowHEX evaporator( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = SecondaryMedium, + redeclare model ConductionElementA = + ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX, + redeclare model ConductionElementB = + ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX_twoPhase, + initializeMassFlow=false, + nCells=10, + A=15, + V_Hex(displayUnit="m3"), + k_wall=50) annotation (Placement(transformation( + extent={{10,10},{-10,-10}}, + rotation=180, + origin={14,14}))); + + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = TertiaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{114,-4},{94,16}}))); + + ThermofluidStream.Processes.Pump pump(redeclare package Medium = + TertiaryMedium, + omega_from_input=true, + redeclare function dp_tau_pump = + ThermofluidStream.Processes.Internal.TurboComponent.dp_tau_centrifugal) + annotation (Placement(transformation(extent={{100,-80},{120,-60}}))); + + ThermofluidStream.Processes.ConductionElement conductionElement(redeclare + package Medium = TertiaryMedium) + annotation (Placement(transformation(extent={{0,-80},{20,-60}}))); + Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heating_element + annotation (Placement(transformation(extent={{-6,-58},{14,-38}}))); + Modelica.Blocks.Sources.RealExpression heat(y=40000) + annotation (Placement(transformation(extent={{-46,-60},{-26,-40}}))); + ThermofluidStream.Boundaries.Reservoir reservoir(redeclare package Medium + = TertiaryMedium) + annotation (Placement(transformation(extent={{-52,-80},{-32,-60}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm2( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{74,6},{50,-18}}))); + ThermofluidStream.Boundaries.Source + source1(redeclare package Medium = SecondaryMedium, + temperatureFromInput=false, + T0_par=283.15, + p0_par(displayUnit="Pa") = (SecondaryMedium.saturationPressure(263.15))) + annotation (Placement(transformation(extent={{-132,34},{-112,54}}))); + ThermofluidStream.Boundaries.Sink + sink1(redeclare package Medium = SecondaryMedium, + pressureFromInput=true) + annotation (Placement(transformation(extent={{76,16},{96,36}}))); + ThermofluidStream.Processes.FlowResistance + flowResistance2( + redeclare package Medium = SecondaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{-84,34},{-64,54}}))); + + ThermofluidStream.Sensors.MultiSensor_Tpm + multiSensor_Tpm3( + redeclare package Medium = SecondaryMedium, + outputTemperature=true, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{44,26},{64,46}}))); + Modelica.Blocks.Nonlinear.Limiter limiter1(uMax=7e5, uMin=100) + annotation (Placement(transformation(extent={{144,20},{132,32}}))); + Modelica.Blocks.Continuous.PI PI1( + k=1000, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=1e5) + annotation (Placement(transformation(extent={{170,16},{150,36}}))); + Modelica.Blocks.Math.Feedback feedback1 + annotation (Placement(transformation(extent={{198,16},{178,36}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint1(y=30) + annotation (Placement(transformation(extent={{224,16},{204,36}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm + multiSensor_Tpm4( + redeclare package Medium = SecondaryMedium, + outputMassFlowRate=true, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-46,44},{-22,22}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons + annotation (Placement(transformation(extent={{-102,-60},{-82,-40}}))); + Modelica.Blocks.Nonlinear.Limiter limiter2(uMax=600, uMin=50) + annotation (Placement(transformation(extent={{38,-140},{50,-128}}))); + Modelica.Blocks.Continuous.PI PI2( + k=-5, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=300) + annotation (Placement(transformation(extent={{4,-144},{24,-124}}))); + Modelica.Blocks.Math.Feedback feedback2 + annotation (Placement(transformation(extent={{-32,-124},{-12,-144}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint2(y=15) + annotation (Placement(transformation(extent={{-66,-144},{-46,-124}}))); + ThermofluidStream.Sensors.DifferenceSensor_Tp differenceSensor_Tp( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = TertiaryMedium, + outputTemperature=true) + annotation (Placement(transformation(extent={{34,-80},{54,-100}}))); + Modelica.Blocks.Math.Gain gain(k=-1) + annotation (Placement(transformation(extent={{-4,-116},{-14,-106}}))); + Modelica.Blocks.Sources.RealExpression inlet_temp(y=283.15) + annotation (Placement(transformation(extent={{-164,34},{-144,54}}))); +equation + + connect(pump.outlet,flowResistance1. inlet) annotation (Line( + points={{120,-70},{142,-70},{142,6},{114,6}}, + color={28,108,200}, + thickness=0.5)); + connect(conductionElement.outlet,pump. inlet) annotation (Line( + points={{20,-70},{100,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(heating_element.port,conductionElement. heatPort) annotation (Line( + points={{14,-48},{14,-80},{10,-80}}, color={191, + 0,0})); + connect(heat.y,heating_element. Q_flow) annotation (Line(points={{-25,-50},{-25, + -48},{-6,-48}}, color={0,0,127})); + connect(reservoir.outlet,conductionElement. inlet) annotation (Line( + points={{-32,-70},{0,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm1.outlet,reservoir. inlet) annotation (Line( + points={{-38,8},{-68,8},{-68,-70},{-52,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, multiSensor_Tpm2.inlet) annotation (Line( + points={{94,6},{74,6}}, + color={28,108,200}, + thickness=0.5)); + connect(evaporator.outletA, multiSensor_Tpm1.inlet) annotation (Line( + points={{4,8},{-14,8}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm2.outlet, evaporator.inletA) annotation (Line( + points={{50,6},{28,6},{28,8},{24,8}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet,flowResistance2. inlet) annotation (Line( + points={{-112,44},{-84,44}}, + color={28,108,200}, + thickness=0.5)); + connect(sink1.inlet,multiSensor_Tpm3. outlet) annotation (Line( + points={{76,26},{64,26}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter1.y,sink1. p0_var) + annotation (Line(points={{131.4,26},{88,26}}, color={0,0,127})); + connect(limiter1.u,PI1. y) + annotation (Line(points={{145.2,26},{149,26}}, color={0,0,127})); + connect(PI1.u,feedback1. y) + annotation (Line(points={{172,26},{179,26}}, color={0,0,127})); + connect(feedback1.u1,refFlow_setPoint1. y) + annotation (Line(points={{196,26},{203,26}}, color={0,0,127})); + connect(flowResistance2.outlet,multiSensor_Tpm4. inlet) annotation (Line( + points={{-64,44},{-46,44}}, + color={28,108,200}, + thickness=0.5)); + connect(evaporator.outletB, multiSensor_Tpm3.inlet) annotation (Line( + points={{24,20},{32,20},{32,26},{44,26}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm4.outlet, evaporator.inletB) annotation (Line( + points={{-22,44},{-14,44},{-14,20},{4,20}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter2.u,PI2. y) + annotation (Line(points={{36.8,-134},{25,-134}}, color={0,0,127})); + connect(limiter2.y, pump.omega_input) annotation (Line(points={{50.6,-134},{ + 110,-134},{110,-82}}, color={0,0,127})); + connect(multiSensor_Tpm1.T_out, feedback1.u2) annotation (Line(points={{-35.84, + -11.2},{-44,-11.2},{-44,-26},{188,-26},{188,18}}, + color={0,0,127})); + connect(feedback2.y, PI2.u) + annotation (Line(points={{-13,-134},{2,-134}}, color={0,0,127})); + connect(feedback2.u1, refFlow_setPoint2.y) + annotation (Line(points={{-30,-134},{-45,-134}}, color={0,0,127})); + connect(differenceSensor_Tp.inletA, conductionElement.inlet) annotation (Line( + points={{34,-96},{-4,-96},{-4,-70},{0,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.inletB, conductionElement.outlet) annotation ( + Line( + points={{34,-84},{26,-84},{26,-70},{20,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.T_out, gain.u) annotation (Line(points={{52,-94}, + {56,-94},{56,-111},{-3,-111}}, color={0,0,127})); + connect(feedback2.u2, gain.y) annotation (Line(points={{-22,-126},{-22,-111}, + {-14.5,-111}}, color={0,0,127})); + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent={{-82,-178},{192,98}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points={{-18,74},{170,-46},{-18,-158},{-18,74}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260, + 100}})),Documentation( revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TestLiqLoopJP8DryAir; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestSimpleLoopJP8DryAir.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestSimpleLoopJP8DryAir.mo new file mode 100644 index 00000000..06807e64 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestSimpleLoopJP8DryAir.mo @@ -0,0 +1,143 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.Examples; +model TestSimpleLoopJP8DryAir + + replaceable package SecondaryMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package RefrigerantMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package TertiaryMedium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir + constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + // TertiaryMedium.BaseProperties terMedium; + + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = TertiaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{110,-10},{90,10}}))); + + ThermofluidStream.Processes.Pump pump(redeclare package Medium = + TertiaryMedium, + omega_from_input=true, + redeclare function dp_tau_pump = + ThermofluidStream.Processes.Internal.TurboComponent.dp_tau_centrifugal) + annotation (Placement(transformation(extent={{88,-80},{108,-60}}))); + + ThermofluidStream.Processes.ConductionElement conductionElement(redeclare + package Medium = TertiaryMedium) + annotation (Placement(transformation(extent={{0,-80},{20,-60}}))); + Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heating_element + annotation (Placement(transformation(extent={{-6,-58},{14,-38}}))); + Modelica.Blocks.Sources.RealExpression heat(y=40) + annotation (Placement(transformation(extent={{-46,-60},{-26,-40}}))); + ThermofluidStream.Boundaries.Reservoir reservoir(redeclare package Medium + = TertiaryMedium) + annotation (Placement(transformation(extent={{-50,-80},{-30,-60}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm2( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{62,0},{36,-26}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons + annotation (Placement(transformation(extent={{-102,-60},{-82,-40}}))); + Modelica.Blocks.Nonlinear.Limiter limiter2(uMax=600, uMin=50) + annotation (Placement(transformation(extent={{38,-146},{50,-134}}))); + Modelica.Blocks.Continuous.PI PI2( + k=-5, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=300) + annotation (Placement(transformation(extent={{4,-150},{24,-130}}))); + Modelica.Blocks.Math.Feedback feedback2 + annotation (Placement(transformation(extent={{-32,-130},{-12,-150}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint2(y=15) + annotation (Placement(transformation(extent={{-66,-150},{-46,-130}}))); + ThermofluidStream.Sensors.DifferenceSensor_Tp differenceSensor_Tp( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = TertiaryMedium, + outputTemperature=true) + annotation (Placement(transformation(extent={{28,-80},{48,-100}}))); + Modelica.Blocks.Math.Gain gain(k=-1) + annotation (Placement(transformation(extent={{-4,-116},{-14,-106}}))); +equation + // terMedium.X[2]=0.9999; + connect(pump.outlet,flowResistance1. inlet) annotation (Line( + points={{108,-70},{142,-70},{142,0},{110,0}}, + color={28,108,200}, + thickness=0.5)); + connect(conductionElement.outlet,pump. inlet) annotation (Line( + points={{20,-70},{88,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(heating_element.port,conductionElement. heatPort) annotation (Line( + points={{14,-48},{14,-80},{10,-80}}, color={191, + 0,0})); + connect(heat.y,heating_element. Q_flow) annotation (Line(points={{-25,-50},{-25, + -48},{-6,-48}}, color={0,0,127})); + connect(reservoir.outlet,conductionElement. inlet) annotation (Line( + points={{-30,-70},{0,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance1.outlet, multiSensor_Tpm2.inlet) annotation (Line( + points={{90,0},{62,0}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter2.u,PI2. y) + annotation (Line(points={{36.8,-140},{25,-140}}, color={0,0,127})); + connect(limiter2.y, pump.omega_input) annotation (Line(points={{50.6,-140},{ + 98,-140},{98,-82}}, color={0,0,127})); + connect(feedback2.y, PI2.u) + annotation (Line(points={{-13,-140},{2,-140}}, color={0,0,127})); + connect(feedback2.u1, refFlow_setPoint2.y) + annotation (Line(points={{-30,-140},{-45,-140}}, color={0,0,127})); + connect(differenceSensor_Tp.inletA, conductionElement.inlet) annotation (Line( + points={{28,-96},{-4,-96},{-4,-70},{0,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.inletB, conductionElement.outlet) annotation ( + Line( + points={{28,-84},{26,-84},{26,-70},{20,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.T_out, gain.u) annotation (Line(points={{46,-94}, + {56,-94},{56,-111},{-3,-111}}, color={0,0,127})); + connect(feedback2.u2, gain.y) annotation (Line(points={{-22,-132},{-22,-111}, + {-14.5,-111}}, color={0,0,127})); + connect(multiSensor_Tpm2.outlet, reservoir.inlet) annotation (Line( + points={{36,0},{-60,0},{-60,-70},{-50,-70}}, + color={28,108,200}, + thickness=0.5)); + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent={{-82,-178},{192,98}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points={{-18,74},{170,-46},{-18,-158},{-18,74}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260, + 100}})),Documentation( revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TestSimpleLoopJP8DryAir; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestSimpleLoopWithStaticHeadJP8DryAir.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestSimpleLoopWithStaticHeadJP8DryAir.mo new file mode 100644 index 00000000..7d3b2ee3 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/TestSimpleLoopWithStaticHeadJP8DryAir.mo @@ -0,0 +1,226 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.Examples; +model TestSimpleLoopWithStaticHeadJP8DryAir + + replaceable package SecondaryMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package RefrigerantMedium = + ThermofluidStream.Media.XRGMedia.CO2_ph constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + + replaceable package TertiaryMedium = + + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir + constrainedby + ThermofluidStream.Media.myMedia.Interfaces.PartialMedium + annotation(choicesAllMatching=true); + // TertiaryMedium.BaseProperties terMedium; + + ThermofluidStream.Processes.FlowResistance flowResistance1( + redeclare package Medium = TertiaryMedium, + initM_flow=ThermofluidStream.Utilities.Types.InitializationMethods.state, + r=0.05, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.linearQuadraticPressureLoss + ( k=1e4)) + annotation (Placement(transformation(extent={{20,0},{0,20}}))); + + ThermofluidStream.Processes.Pump pump(redeclare package Medium = + TertiaryMedium, + omega_from_input=true, + redeclare function dp_tau_pump = + ThermofluidStream.Processes.Internal.TurboComponent.dp_tau_centrifugal) + annotation (Placement(transformation(extent={{92,-90},{112,-70}}))); + + ThermofluidStream.Processes.ConductionElement conductionElement(redeclare + package Medium = TertiaryMedium) + annotation (Placement(transformation(extent={{40,-90},{60,-70}}))); + Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heating_element + annotation (Placement(transformation(extent={{32,-56},{52,-36}}))); + Modelica.Blocks.Sources.RealExpression heat(y=40) + annotation (Placement(transformation(extent={{-8,-58},{12,-38}}))); + ThermofluidStream.Boundaries.Reservoir reservoir(redeclare package Medium + = TertiaryMedium) + annotation (Placement(transformation(extent={{-112,-90},{-92,-70}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm3( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-28,10},{-52,-14}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons + annotation (Placement(transformation(extent={{-174,-50},{-154,-30}}))); + Modelica.Blocks.Nonlinear.Limiter limiter2(uMax=600, uMin=50) + annotation (Placement(transformation(extent={{34,-156},{46,-144}}))); + Modelica.Blocks.Continuous.PI PI2( + k=-5, + T=0.1, + initType=Modelica.Blocks.Types.Init.InitialOutput, + y_start=300) + annotation (Placement(transformation(extent={{0,-160},{20,-140}}))); + Modelica.Blocks.Math.Feedback feedback2 + annotation (Placement(transformation(extent={{-36,-140},{-16,-160}}))); + Modelica.Blocks.Sources.RealExpression refFlow_setPoint2(y=15) + annotation (Placement(transformation(extent={{-70,-160},{-50,-140}}))); + ThermofluidStream.Sensors.DifferenceSensor_Tp differenceSensor_Tp( + redeclare package MediumA = TertiaryMedium, + redeclare package MediumB = TertiaryMedium, + outputTemperature=true) + annotation (Placement(transformation(extent={{66,-104},{86,-124}}))); + Modelica.Blocks.Math.Gain gain(k=-1) + annotation (Placement(transformation(extent={{-8,-132},{-18,-122}}))); + inner ThermofluidStream.Boundaries.AccelerationBoundary acceleration( + setFromInputs=false, + ax=9*sin(0.1*time), + ay=0) annotation (Placement(transformation(extent={{-180,-22},{-160,-2}}))); + ThermofluidStream.Processes.StaticHead staticHead( + redeclare package Medium = TertiaryMedium, + fromPosition={0,0,0}, + toPosition={3,0,2}) annotation (Placement(transformation( + extent={{-11,-11},{11,11}}, + rotation=90, + origin={181,-21}))); + ThermofluidStream.Processes.StaticHead staticHead1( + redeclare package Medium = TertiaryMedium, + fromPosition={3,0,2}, + toPosition={1,0,1}) annotation (Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=90, + origin={-120,-10}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm1( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{140,-80},{162,-102}}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm4( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-10.5,10.5},{10.5,-10.5}}, + rotation=-90, + origin={-129.5,-49.5}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm2( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{90,10},{70,-10}}))); + ThermofluidStream.Processes.StaticHead staticHead2( + redeclare package Medium = TertiaryMedium, + fromPosition={1,0,1}, + toPosition={0,0,0}, + displayPositions=false) annotation (Placement(transformation( + extent={{10.5,12.5},{-10.5,-12.5}}, + rotation=180, + origin={-67.5,-79.5}))); + ThermofluidStream.Sensors.MultiSensor_Tpm multiSensor_Tpm5( + redeclare package Medium = TertiaryMedium, + outputTemperature=true, + outputMassFlowRate=false, + temperatureUnit="degC") + annotation (Placement(transformation(extent={{-34,-80},{-10,-104}}))); +equation + + connect(heating_element.port,conductionElement. heatPort) annotation (Line( + points={{52,-46},{52,-90},{50,-90}}, color={191, + 0,0})); + connect(heat.y,heating_element. Q_flow) annotation (Line(points={{13,-48},{ + 13,-46},{32,-46}}, color={0,0,127})); + connect(flowResistance1.outlet,multiSensor_Tpm3. inlet) annotation (Line( + points={{0,10},{-28,10}}, + color={28,108,200}, + thickness=0.5)); + connect(limiter2.u,PI2. y) + annotation (Line(points={{32.8,-150},{21,-150}}, color={0,0,127})); + connect(limiter2.y, pump.omega_input) annotation (Line(points={{46.6,-150},{ + 102,-150},{102,-92}}, color={0,0,127})); + connect(feedback2.y, PI2.u) + annotation (Line(points={{-17,-150},{-2,-150}},color={0,0,127})); + connect(feedback2.u1, refFlow_setPoint2.y) + annotation (Line(points={{-34,-150},{-49,-150}}, color={0,0,127})); + connect(differenceSensor_Tp.inletA, conductionElement.inlet) annotation (Line( + points={{66,-120},{32,-120},{32,-80},{40,-80}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.inletB, conductionElement.outlet) annotation ( + Line( + points={{66,-108},{66,-88},{72,-88},{72,-80},{60,-80}}, + color={28,108,200}, + thickness=0.5)); + connect(differenceSensor_Tp.T_out, gain.u) annotation (Line(points={{84,-118}, + {94,-118},{94,-128},{-7,-128},{-7,-127}}, + color={0,0,127})); + connect(feedback2.u2, gain.y) annotation (Line(points={{-26,-142},{-26,-127}, + {-18.5,-127}}, color={0,0,127})); + connect(multiSensor_Tpm3.outlet, staticHead1.inlet) annotation (Line( + points={{-52,10},{-120,10},{-120,0}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead.outlet, multiSensor_Tpm2.inlet) annotation (Line( + points={{181,-10},{181,10},{90,10}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm2.outlet, flowResistance1.inlet) annotation (Line( + points={{70,10},{20,10}}, + color={28,108,200}, + thickness=0.5)); + connect(pump.outlet, multiSensor_Tpm1.inlet) annotation (Line( + points={{112,-80},{140,-80}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm1.outlet, staticHead.inlet) annotation (Line( + points={{162,-80},{181,-80},{181,-32}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead1.outlet, multiSensor_Tpm4.inlet) annotation (Line( + points={{-120,-20},{-120,-39},{-119,-39}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm4.outlet, reservoir.inlet) annotation (Line( + points={{-119,-60},{-119.5,-60},{-119.5,-80},{-112,-80}}, + color={28,108,200}, + thickness=0.5)); + connect(reservoir.outlet, staticHead2.inlet) annotation (Line( + points={{-92,-80},{-80,-80},{-80,-79.5},{-78,-79.5}}, + color={28,108,200}, + thickness=0.5)); + connect(conductionElement.outlet, pump.inlet) annotation (Line( + points={{60,-80},{92,-80}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead2.outlet, multiSensor_Tpm5.inlet) annotation (Line( + points={{-57,-79.5},{-34,-79.5},{-34,-80}}, + color={28,108,200}, + thickness=0.5)); + connect(multiSensor_Tpm5.outlet, conductionElement.inlet) annotation (Line( + points={{-10,-80},{40,-80}}, + color={28,108,200}, + thickness=0.5)); + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260,100}}), + graphics={ + Ellipse(lineColor = {75,138,73}, + fillColor={255,255,255}, + fillPattern = FillPattern.Solid, + extent={{-82,-178},{192,98}}), + Polygon(lineColor = {0,0,255}, + fillColor = {75,138,73}, + pattern = LinePattern.None, + fillPattern = FillPattern.Solid, + points={{-18,74},{170,-46},{-18,-158},{-18,74}})}), + Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-180,-180},{260, + 100}})), + experiment(StopTime=30, __Dymola_Algorithm="Dassl"),Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TestSimpleLoopWithStaticHeadJP8DryAir; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/package.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/package.mo new file mode 100644 index 00000000..8be57bdd --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/package.mo @@ -0,0 +1,4 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible; +package Examples + +end Examples; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/package.order b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/package.order new file mode 100644 index 00000000..67b4d2dc --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/Examples/package.order @@ -0,0 +1,4 @@ +TestJP8DryAir +TestLiqLoopJP8DryAir +TestSimpleLoopJP8DryAir +TestSimpleLoopWithStaticHeadJP8DryAir diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/JP8DryAir/package.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/JP8DryAir/package.mo new file mode 100644 index 00000000..ec1a9772 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/JP8DryAir/package.mo @@ -0,0 +1,32 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible; +package JP8DryAir "Jet propulsion JP8 combined with dry air" + extends + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.PartialSingleGasAndIncompressible( + mediumName="JP8 and DryAir", + substanceNames=cat( + 1, + SingleGas.substanceNames, + Incompressible.substanceNames), + reference_X={0.0001,0.9999}, + reference_p=1e5, + reference_T=273.15 + 15, + reducedX=false, + AbsolutePressure(displayUnit="kPa")); + redeclare package SingleGas = + ThermofluidStream.Media.myMedia.Air.DryAirNasa; + redeclare package Incompressible = + ThermofluidStream.Media.additionalMedia.Incompressible.JP8; + annotation (Documentation(info=" +

JP8DryAir

+

A combination of the DryAirNASA medium and the JP8 medium.

+

The reference blend is 0.01% Air at reference pressure 100000 Pa and 15 deg C.

+

A discussion of the approximation by linear combination of fuel and air flowing in a pipe can be found in

+

https://www.diva-portal.org/smash/record.jsf?pid=diva2%3A17182&dswid=6825.

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end JP8DryAir; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/JP8DryAir/package.order b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/JP8DryAir/package.order new file mode 100644 index 00000000..5c51e7a6 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/JP8DryAir/package.order @@ -0,0 +1,2 @@ +SingleGas +Incompressible diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/PartialSingleGasAndIncompressible.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/PartialSingleGasAndIncompressible.mo new file mode 100644 index 00000000..2de93982 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/PartialSingleGasAndIncompressible.mo @@ -0,0 +1,259 @@ +within ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible; +partial package PartialSingleGasAndIncompressible + "SingleGases medium combined with Incompressible medium" + + // Set the parameters to PartialMedium and select SingleGas and Incompressible. Observe that this implementation + // only works for Incompressible media with one substance." + extends ThermofluidStream.Media.myMedia.Interfaces.PartialMedium( + mediumName="incomplete combination of SingleGas and Incompressible", + substanceNames=cat( + 1, + SingleGas.substanceNames, + Incompressible.substanceNames), + reference_X={0.0001,0.9999}, + reference_p =1e5, + reference_T= 273.15, + reducedX=false, + AbsolutePressure(displayUnit="kPa")); + replaceable package SingleGas = + ThermofluidStream.Media.myMedia.IdealGases.Common.SingleGasNasa + "SingleGas choice" annotation(choicesAllMatching=true); + replaceable package Incompressible = + ThermofluidStream.Media.myMedia.Incompressible.TableBased "Incompressible choice" annotation(choicesAllMatching=true); + redeclare record ThermodynamicState + Modelica.Units.SI.AbsolutePressure p "Pressure"; + Modelica.Units.SI.Temperature T "Temperature"; + ThermofluidStream.Media.myMedia.Interfaces.Types.MassFraction[nS] X + "MassFractions"; + end ThermodynamicState; + + redeclare replaceable model extends BaseProperties( + T(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default), + p(stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default), + Xi(each stateSelect=if preferredMediumStates then StateSelect.prefer else StateSelect.default), + final standardOrderComponents=true) + "Base properties (p, d, T, h, u, R_s, MM, and X of Incompressible mixed with SingleGases" + import Modelica.Math.Polynomials; + + equation + MM = molarMass(state); + h = h_TX(T, X); + R_s = {SingleGas.data.R_s, Modelica.Constants.R/Incompressible.MM_const}*X; + u = h -reference_p/d; + d = density_pTX(p,T,X); + // connect state with BaseProperties + state.T = T; + state.p = p; + state.X = X; + end BaseProperties; + + redeclare function extends setState_pTX + "set the thermodynamic state record from p, T, X" + algorithm + state.p := p; + state.T := T; + state.X := X; + annotation (smoothOrder=5); + end setState_pTX; + + redeclare function setState_phX + input Modelica.Units.SI.AbsolutePressure p; + input Modelica.Units.SI.SpecificEnthalpy h; + input Modelica.Units.SI.MassFraction[:] X; + output ThermodynamicState state; + algorithm + state := ThermodynamicState( + p=p, + T=T_hX( + h, + X), + X=X); + annotation (smoothOrder=2); + end setState_phX; + + function T_hX + input SpecificEnthalpy h; + input MassFraction[:] X; + output Temperature T; + //------------------------------------------------- + protected + function f_nonlinear "Solve h_TX(T,X) for T with given h" + extends Modelica.Math.Nonlinear.Interfaces.partialScalarFunction; + input SpecificEnthalpy h "Specific enthalpy"; + input MassFraction[nX] X "Mass fractions of composition"; + + algorithm + y := h_TX( + T=u, + X=X) - h; + end f_nonlinear; + + algorithm + T := Modelica.Math.Nonlinear.solveOneNonlinearEquation( + function f_nonlinear( + h=h, + X=X), + 200, + 6000); + // from .myMedia.IdealGases.Common.SingleGasNasa + annotation (inverse(h=h_TX( + T, + X))); + end T_hX; + + function h_TX + input Temperature T; + input MassFraction[:] X; + output SpecificEnthalpy h; + algorithm + h := X*{ThermofluidStream.Media.myMedia.IdealGases.Common.Functions.h_T(SingleGas.data,T),Incompressible.h_T(T)}; + end h_TX; + + redeclare function extends pressure + "Return the pressure from the thermodynamic state" + algorithm + p := state.p; + end pressure; + + redeclare function extends isentropicExponent + "Return the isentropic exponent" + algorithm + gamma := specificHeatCapacityCp(state)/specificHeatCapacityCv(state); + end isentropicExponent; + + redeclare function extends temperature + "Return the temperature from the thermodynamicstate" + algorithm + T := state.T; + end temperature; + + redeclare function extends massFraction + "Return the massfraction from the thermodynamic state" + algorithm + Xi:= state.X; + end massFraction; + + redeclare function density + "Return the density from the thermodynamic state" + input ThermodynamicState state; + output Density d; + protected + Density d_SG= SingleGas.density(SingleGas.setState_pTX(state.p,state.T)); + Density d_I = Incompressible.density(Incompressible.setState_pTX(state.p,state.T)); + algorithm + d:= d_SG*d_I/(state.X*{d_I, d_SG}); + annotation (smoothOrder=5); + end density; + + function d_pT_Incompressible + input AbsolutePressure p; + input Temperature T; + output Density d; + algorithm + d:= Incompressible.density(Incompressible.setState_pTX(p,T)); + end d_pT_Incompressible; + + redeclare function specificEnthalpy + "Return the specific enthalpy from the thermodynamic state" + input ThermodynamicState state "thermodynamic state record"; + output SpecificEnthalpy h "specific enthalpy"; + protected + SpecificEnthalpy h_SG = SingleGas.specificEnthalpy(SingleGas.setState_pTX(state.p, state.T)); + SpecificEnthalpy h_I = Incompressible.specificEnthalpy(Incompressible.setState_pTX(state.p, state.T)); + algorithm + h := {h_SG, h_I}*state.X; + annotation(smoothOrder=5); + end specificEnthalpy; + + redeclare function extends specificEntropy + "Return the specific entropy from the thermodynamic state, total mixing assumed" + protected + SpecificEntropy s_SG = SingleGas.specificEntropy(SingleGas.setState_pTX(state.p,state.T)); + SpecificEntropy s_I = Incompressible.specificEntropy(Incompressible.setState_pTX(state.p,state.T)); + algorithm + s := {s_SG,s_I}*state.X; + + end specificEntropy; + + redeclare function extends specificInternalEnergy + "Return the specific internal energy from the thermodynamic state" + algorithm + u := specificEnthalpy(state)-state.p/density(state); + end specificInternalEnergy; + + redeclare function extends specificGibbsEnergy + "Return specific Gibbs energy from the thermodynamic state" + algorithm + g := specificEnthalpy(state) - temperature(state)*specificEntropy(state); + end specificGibbsEnergy; + + redeclare function extends specificHelmholtzEnergy + "Return specific Helmholtz energy from thermodynamic state" + algorithm + f := specificInternalEnergy(state)- temperature(state)*specificEntropy(state); + end specificHelmholtzEnergy; + + redeclare function extends specificHeatCapacityCp + "Return specific heat capacity at constant pressure" + protected + SpecificHeatCapacity Cp_SG = SingleGas.specificHeatCapacityCp(SingleGas.setState_pTX(state.p, state.T)); + SpecificHeatCapacity Cp_I = Incompressible.specificHeatCapacityCp(Incompressible.setState_pTX(state.p, state.T)); + algorithm + cp := {Cp_SG, Cp_I}*state.X; + annotation(smoothOrder = 2); + end specificHeatCapacityCp; + + redeclare function extends specificHeatCapacityCv + "Return specific heat capacity at constant volume" + protected + SpecificHeatCapacity Cv_SG = SingleGas.specificHeatCapacityCv(SingleGas.setState_pTX(state.p, state.T)); + SpecificHeatCapacity Cv_I = Incompressible.specificHeatCapacityCv(Incompressible.setState_pTX(state.p, state.T)); + algorithm + cv := {Cv_SG, Cv_I}*state.X; + annotation(smoothOrder = 2); + end specificHeatCapacityCv; + + redeclare function extends dynamicViscosity + "Return dynamic viscosity from the thermodynamic state" + protected + DynamicViscosity eta_SG = SingleGas.dynamicViscosity(SingleGas.setState_pTX(state.p,state.T)); + DynamicViscosity eta_I = Incompressible.dynamicViscosity(Incompressible.setState_pTX(state.p, state.T)); + algorithm + eta := {eta_SG, eta_I}*state.X; + annotation(smoothOrder=2); + end dynamicViscosity; + + redeclare function extends thermalConductivity + "Return thermal conductivity from thermodynamic state" + protected + ThermalConductivity lambda_SG = SingleGas.thermalConductivity(SingleGas.setState_pTX(state.p,state.T)); + ThermalConductivity lambda_I = Incompressible.thermalConductivity(Incompressible.setState_pTX(state.p, state.T)); + algorithm + lambda :={lambda_SG, lambda_I}*state.X; + end thermalConductivity; + + redeclare function extends molarMass + "Return molar mass from the thermodynamic state" + protected + MolarMass MM_SG = SingleGas.molarMass(SingleGas.setState_pTX(state.p,state.T)); + MolarMass MM_I = Incompressible.molarMass(Incompressible.setState_pTX(state.p, state.T)); + algorithm + MM := MM_SG*MM_I /(state.X*{MM_I, MM_SG}); + end molarMass; + annotation (Documentation(info=" +

Gas medium combined with incompressible medium. Only the parameters to PartialMedium  and selection of SingleGases and Incompressible are incomplete. 

+

Observe that this implementation only works for Incompressible with one substance .

+

It is assumed that the gas and the liquid do not interact. This is a simplification since many substances mix , e. g. water and air where there is air molecules mixed into the liquid water and water steam mixed in the air.

+

To calculate the media properties a linear interpolation based on the mass-fractions between the gas and liquid is performed. Depending on the chosen property this may be more or less meaningful. Whenever possible,

+

one shall therefore use the properties of gas and liquid directly. Compare e.g. with a typical refrigerant, where many of the properties are only defined in the one-phase regions.

+

The intended use for this media is in systems where the properties of the mix of the media is not very important to get absolutely correct, but where both of the substances of the mix can occur at any physical location

+

in the system, but then mostly in pure or nearly pure form.

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+"), Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false))); +end PartialSingleGasAndIncompressible; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/package.mo b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/package.mo new file mode 100644 index 00000000..8c43c8b2 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/package.mo @@ -0,0 +1,5 @@ +within ThermofluidStream.Media.additionalMedia; +package SingleGasAndIncompressible + extends Modelica.Icons.VariantsPackage; + +end SingleGasAndIncompressible; diff --git a/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/package.order b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/package.order new file mode 100644 index 00000000..acf3093a --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/SingleGasAndIncompressible/package.order @@ -0,0 +1,3 @@ +PartialSingleGasAndIncompressible +JP8DryAir +Examples diff --git a/ThermofluidStream/Media/additionalMedia/package.mo b/ThermofluidStream/Media/additionalMedia/package.mo new file mode 100644 index 00000000..105041e7 --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/package.mo @@ -0,0 +1,4 @@ +within ThermofluidStream.Media; +package additionalMedia + extends Modelica.Icons.VariantsPackage; +end additionalMedia; diff --git a/ThermofluidStream/Media/additionalMedia/package.order b/ThermofluidStream/Media/additionalMedia/package.order new file mode 100644 index 00000000..cdd8e19a --- /dev/null +++ b/ThermofluidStream/Media/additionalMedia/package.order @@ -0,0 +1,2 @@ +Incompressible +SingleGasAndIncompressible diff --git a/ThermofluidStream/Media/package.order b/ThermofluidStream/Media/package.order index a72520b5..126aa080 100644 --- a/ThermofluidStream/Media/package.order +++ b/ThermofluidStream/Media/package.order @@ -1,3 +1,4 @@ myMedia XRGMedia Tests +additionalMedia diff --git a/ThermofluidStream/Processes/StaticHead.mo b/ThermofluidStream/Processes/StaticHead.mo new file mode 100644 index 00000000..144cf025 --- /dev/null +++ b/ThermofluidStream/Processes/StaticHead.mo @@ -0,0 +1,120 @@ +within ThermofluidStream.Processes; +model StaticHead "Static head model" + extends ThermofluidStream.Interfaces.SISOFlow(final L=L_value, final clip_p_out=true); + + parameter Modelica.Units.SI.Length fromPosition[3] + "Coordinates for the position the static head is computed from" annotation (Dialog(group="Geometry", + enable=true)); + parameter Modelica.Units.SI.Length toPosition[3] + "Coordinates for the position the static head is computed to" annotation (Dialog(group="Geometry", + enable=true)); + + parameter ThermofluidStream.Utilities.Units.Inertance L_value=dropOfCommons.L + "Inertance of pipe" annotation (Dialog(tab="Advanced", enable=not computeL)); + + parameter Modelica.Units.SI.Density rho_min=dropOfCommons.rho_min + "Minimal input density" annotation (Dialog(tab="Advanced")); + + Modelica.Units.SI.Length staticHead "static head in m"; + Modelica.Units.SI.Pressure staticHead_Pa_relative "static head measured i Pa, taking current acceleration and limitations into account"; + parameter Boolean displayPositions=true "show positions in icon"; +protected + Modelica.Units.SI.Density rho_in=max(rho_min, Medium.density(inlet.state)) + "Density of medium entering"; + outer ThermofluidStream.Boundaries.AccelerationBoundary acceleration; +equation + dp = -(fromPosition - toPosition)*acceleration.a*rho_in; + h_out = h_in; + Xi_out = Xi_in; + // If the inlet pressure is not sufficient to overcome the acceleration field + // between the pipe ends the static head is less than the length given by + // the position difference in the direction of the acceleration field. + // The outlet pressure is set to >= p_min automatically when clip_p_out = true + + staticHead= sign(dp)*(p_out-p_in)/max(abs(dp),1e-12)*(fromPosition - toPosition)*Modelica.Math.Vectors.normalize(acceleration.a); + staticHead_Pa_relative=p_out-p_in; + + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse( + extent={{-56,54},{64,-66}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Line( + points={{-100,0},{100,0}}, + color={28,108,200}, + thickness=0.5), + Ellipse( + extent={{-60,60},{60,-60}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(visible=displayPositions, + extent={{-164,118},{0,18}}, + textColor={28,108,200}, + textString="%fromPosition"), + Text( + visible=displayPositions, + extent={{0,-20},{162,-118}}, + textColor={28,108,200}, +textString="%toPosition"), + Line( + points={{28,72},{-16,14}}, + color={206,103,0}, + thickness=1), + Text( + extent={{-46,4},{8,-38}}, + textColor={206,103,0}, + textString="a"), + Line( + points={{-18,12},{-16,28}}, + color={206,103,0}, + thickness=1), + Line( + points={{-18,12},{-4,16}}, + color={206,103,0}, + thickness=1), + Line( + points={{-2,0},{0,16}}, + color={206,103,0}, + thickness=1), + Line( + points={{44,60},{0,2}}, + color={206,103,0}, + thickness=1), + Line( + points={{-2,0},{12,4}}, + color={206,103,0}, + thickness=1), + Line( + points={{14,-12},{16,4}}, + color={206,103,0}, + thickness=1), + Line( + points={{60,48},{16,-10}}, + color={206,103,0}, + thickness=1), + Line( + points={{14,-12},{28,-8}}, + color={206,103,0}, + thickness=1)}), Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

Implementation of static head in a pipe.

+

To specify the acceleration vector, please use the AccelerationBoundary component.

+

Default is pure graviation in the negative z-direction.

+

Energy is moved between potential energy in an acceleration field and internal energy (pressure).

+

The main assumption is that the density is constant for the pressure change along the pipe. That would be the case for non-compressible fluids and many gases at low Mach numbers. For more insight in this look into the difference between the simplified and generalised forms of the Bernoulli equation.

+

Note that it is only the position difference that influence the pressure difference, not the absolute positions. If the inlet pressure is not sufficient to overcome the acceleration field between the pipe ends the static head is less than the length given by the position difference in the acceleration direction.

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end StaticHead; diff --git a/ThermofluidStream/Processes/package.order b/ThermofluidStream/Processes/package.order index 4fd283f0..2d25da18 100644 --- a/ThermofluidStream/Processes/package.order +++ b/ThermofluidStream/Processes/package.order @@ -10,3 +10,4 @@ ConductionElement Nozzle Internal Tests +StaticHead diff --git a/ThermofluidStream/Resources/saab_logo.png b/ThermofluidStream/Resources/saab_logo.png new file mode 100644 index 00000000..40bc2fb3 Binary files /dev/null and b/ThermofluidStream/Resources/saab_logo.png differ diff --git a/ThermofluidStream/Undirected/Boundaries/Internal/PartialTankUndirected.mo b/ThermofluidStream/Undirected/Boundaries/Internal/PartialTankUndirected.mo new file mode 100644 index 00000000..b7979c29 --- /dev/null +++ b/ThermofluidStream/Undirected/Boundaries/Internal/PartialTankUndirected.mo @@ -0,0 +1,521 @@ +within ThermofluidStream.Undirected.Boundaries.Internal; +partial model PartialTankUndirected "Partial Tank model for media that are partial gas and incompressible liquid. Supports undirected flows" + replaceable package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.PartialSingleGasAndIncompressible + "Medium model" annotation (choicesAllMatching=true, Documentation(info=" +

+Medium package used in the Volume. Make sure it is the same as the +inlets and outlets the volume is connected to. +

+")); + + parameter Boolean useHeatport=false "If true heatport is added"; + parameter Modelica.Units.SI.Area A=1 "Contact area of volume with medium" + annotation (Dialog(enable=useHeatport)); + parameter Modelica.Units.SI.CoefficientOfHeatTransfer U=200 + "Heat transfer coefficient to medium" + annotation (Dialog(enable=useHeatport)); + parameter Boolean initialize_pressure=true "If true: initialize Pressure" + annotation (Dialog(tab="Initialization")); + parameter Medium.AbsolutePressure p_start=Medium.p_default + "Initial Pressure" + annotation (Dialog(tab="Initialization", enable=initialize_pressure)); + parameter Boolean initialize_energy=false + "Initialize specific inner energy with temperature or specific enthalpy condition" + annotation (Dialog(tab="Initialization")); + parameter Medium.Temperature T_start=Medium.T_default + "Initial Temperature" annotation (Dialog(tab="Initialization", enable= + initialize_energy and (not use_hstart))); + parameter Boolean use_hstart=false + "True: specific enthalpy condition instead of Temperature" + annotation (Dialog(tab="Initialization", enable=initialize_energy)); + parameter Medium.SpecificEnthalpy h_start=Medium.h_default + "Initial specific enthalpy" annotation (Dialog(tab="Initialization", enable + =initialize_energy and use_hstart)); + parameter Boolean initialize_Xi=false "If true: initialize mass fractions" + annotation (Dialog(tab="Initialization")); + parameter Medium.MassFraction Xi_0[Medium.nXi]=Medium.X_default[1:Medium.nXi] + "Initial mass fraction" + annotation (Dialog(tab="Initialization", enable=initialize_Xi)); + parameter Boolean initialize_LiquidMass=true + "If true: initialize with mass of the liquid medium component. Initialize_Xi must be false." + annotation (Dialog(tab="Initialization", enable=not initialize_Xi)); + parameter Modelica.Units.SI.Mass M_liq_start=0 "Initial mass of the liquid" + annotation (Dialog(tab="Initialization", enable=initialize_LiquidMass)); + + parameter Utilities.Units.Inertance L=dropOfCommons.L + "Inertance at inlet and outlet" annotation (Dialog(tab="Advanced")); + parameter Real k_volume_damping(unit="1") = dropOfCommons.k_volume_damping + "Damping factor multiplicator" + annotation (Dialog(tab="Advanced", group="Damping")); + parameter Medium.MassFlowRate m_flow_assert(max=0) = - + dropOfCommons.m_flow_reg "Assertion threshold for negative massflows" + annotation (Dialog(tab="Advanced")); + parameter Boolean usePreferredMediumStates=false + "Use medium states instead of the ones differentiated in this component" + annotation (Dialog(tab="Advanced")); + parameter Medium.MassFlowRate m_flow_reg=dropOfCommons.m_flow_reg + "Regularization threshold of mass flow rate" + annotation (Dialog(tab="Advanced")); + + parameter Modelica.Units.SI.Length outletTransition=0.01 + "Width of band for smooth transition between gas and liquid at outlet" + annotation (Dialog(tab="Advanced")); + parameter Boolean chaoticLife=false + "Allows small gas bubbles to go from inlet through liquid even if staticHead is positive, experimental. Large increase in simulation time." + annotation (Dialog(tab="Advanced")); + parameter Modelica.Units.SI.Volume gasBubbleVolume=0.0001 + "Tuning parameter for size of gas bubbles" + annotation (Dialog(tab="Advanced", enable=chaoticLife)); + + ThermofluidStream.Interfaces.Inlet inlet[N_inlets](redeclare package Medium = + Medium) + annotation (Placement(transformation(extent={{-118,20},{-78,60}}))); + ThermofluidStream.Interfaces.Outlet outlet[N_outlets](redeclare package + Medium = Medium) + annotation (Placement(transformation(extent={{80,20},{120,60}}))); + Undirected.Interfaces.Rear rear[N_rears](redeclare package Medium = Medium) + annotation (Placement(transformation(extent={{-120,-66},{-80,-26}}), + iconTransformation(extent={{-120,-66},{-80,-26}}))); + Undirected.Interfaces.Fore fore[N_fores](redeclare package Medium = Medium) + annotation (Placement(transformation(extent={{78,-66},{118,-26}}), + iconTransformation(extent={{78,-66},{118,-26}}))); + Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(Q_flow=Q_flow, T + =T_heatPort) if useHeatport + annotation (Placement(transformation(extent={{-10,-90},{10,-70}}))); + + Medium.BaseProperties medium(preferredMediumStates=usePreferredMediumStates); + + Modelica.Units.SI.Volume V; + Modelica.Units.SI.Volume V_liquid; + parameter Medium.AbsolutePressure p_ref=1e5 + "Reference pressure of tank when volume is measured"; + //The tank gets a bulk modulus to handle the stiffness of incompressible media better + SI.Volume V_ref(displayUnit="l") "Volume of the tank at p_ref"; + parameter SI.BulkModulus K=5e7 + "Bulk modulus of tank (used also for stiffness modulation)"; + + //setting the state is to prohibit dynamic state selection e.g. in VolumesDirectCoupling + Modelica.Units.SI.Mass M(stateSelect=if usePreferredMediumStates then + StateSelect.default else StateSelect.always) = V*medium.d; + Modelica.Units.SI.Mass MXi[Medium.nXi](each stateSelect=if + usePreferredMediumStates then StateSelect.default else StateSelect.always) + = M*medium.Xi; + Modelica.Units.SI.Energy U_med(stateSelect=if usePreferredMediumStates then + StateSelect.default else StateSelect.always) = M*medium.u; + + Modelica.Units.SI.HeatFlowRate Q_flow; + Modelica.Units.SI.Power W_v; + parameter Modelica.Units.SI.Length tankCenter[3]={0,0,0} + "Position of the tank center" + annotation (Dialog(tab="General", group="Geometry")); + parameter Integer N_inlets=2 "Number of inlets" + annotation (Dialog(tab="General", group="Geometry")); + parameter Integer N_outlets=2 "Number of outlets" + annotation (Dialog(tab="General", group="Geometry")); + parameter Integer N_rears=2 "Number of rears" + annotation (Dialog(tab="General", group="Geometry")); + parameter Integer N_fores=2 "Number of fores" + annotation (Dialog(tab="General", group="Geometry")); + parameter Modelica.Units.SI.Length inletPositions[N_inlets,3]={{0,0,0} for i in + 1:N_inlets} "Positions of all inlets" + annotation (Dialog(tab="General", group="Geometry")); + parameter Modelica.Units.SI.Length outletPositions[N_outlets,3]={{0,0,0} for + i in 1:N_outlets} "Positions of all outlets" + annotation (Dialog(tab="General", group="Geometry")); + parameter Modelica.Units.SI.Length rearPositions[N_rears,3]={{0,0,0} for i in + 1:N_rears} "Positions of all rears" + annotation (Dialog(tab="General", group="Geometry")); + parameter Modelica.Units.SI.Length forePositions[N_fores,3]={{0,0,0} for i in + 1:N_fores} "Positions of all fores" + annotation (Dialog(tab="General", group="Geometry")); + Modelica.Units.SI.Length centreOfMass[3]; + + Modelica.Units.SI.Length staticHeadInlets[N_inlets] + "distance perpendicular to liquid surface"; + Modelica.Units.SI.Length staticHeadOutlets[N_outlets] + "distance perpendicular to liquid surface"; + Modelica.Units.SI.Length staticHeadRears[N_rears] + "distance perpendicular to liquid surface"; + Modelica.Units.SI.Length staticHeadFores[N_fores] + "distance perpendicular to liquid surface"; + Medium.AbsolutePressure staticHeadInlets_Pa_relative[N_inlets] + "relative pressure to liquid surface"; + Medium.AbsolutePressure staticHeadOutlets_Pa_relative[N_outlets] + "relative pressure to liquid surface"; + Medium.AbsolutePressure staticHeadRears_Pa_relative[N_rears] + "relative pressure to liquid surface"; + Medium.AbsolutePressure staticHeadFores_Pa_relative[N_fores] + "relative pressure to liquid surface"; + + Real normAcc[3]=Modelica.Math.Vectors.normalize(acceleration.a); + +protected + outer DropOfCommons dropOfCommons; + outer ThermofluidStream.Boundaries.AccelerationBoundary acceleration; + Medium.AbsolutePressure p_in[N_inlets]=Medium.pressure(inlet.state); + Medium.SpecificEnthalpy h_in[N_inlets]; + Medium.MassFraction Xi_in[Medium.nXi,N_inlets]; + + Medium.ThermodynamicState state_out[N_outlets]; + Medium.SpecificEnthalpy h_out[N_outlets]; + Medium.MassFraction Xi_out[Medium.nXi,N_outlets]; + + Medium.ThermodynamicState state_out_rear[N_rears]; + Medium.ThermodynamicState state_out_fore[N_fores]; + + Medium.AbsolutePressure r_rear[N_rears]; + Medium.AbsolutePressure r_fore[N_fores]; + Medium.SpecificEnthalpy h_rear[N_rears]; + Medium.SpecificEnthalpy h_fore[N_fores]; + Medium.MassFraction Xi_rear[Medium.nXi,N_rears]; + Medium.MassFraction Xi_fore[Medium.nXi,N_fores]; + + Real d(unit="1/(m.s)") = k_volume_damping*sqrt(abs(2*L/(V*max(density_derp_h, + 1e-10)))) "Friction factor for coupled boundaries"; + //Modelica.Units.SI.DerDensityByPressure density_derp_h=1e-5 "Partial derivative of density by pressure"; + Medium.DerDensityByPressure density_derp_h=(V_ref*medium.d)/(V*K) + "Partial derivative of density by pressure"; + + Medium.AbsolutePressure r_damping=d*der(M); + + Medium.AbsolutePressure r[N_inlets]; + + Medium.Temperature T_heatPort; + + Medium.MassFlowRate m_flow_in[N_inlets]=inlet.m_flow; + Medium.MassFlowRate m_flow_out[N_outlets]=outlet.m_flow; + + final parameter Real ThresholdFull = 0.995 "threshold value near 1 to indicate when full"; + final parameter Real ThresholdEmpty = 0.003 "threshold value near 0 to indicate when empty"; + + Boolean fFull; + Boolean fEmpty; + Real shiftOutlet[N_outlets]; + //Real shiftOutletUp[N_outlets]; + Real shiftRear[N_rears]; + //Real shiftRearUp[N_rears]; + Real shiftFore[N_fores]; + //Real shiftForeUp[N_fores]; + Medium.Density liquidDensity=Medium.Incompressible.density(Medium.Incompressible.setState_pTX(medium.state.p,medium.state.T)) + "density of the liquid in the tank"; + Medium.Density gasDensity=Medium.SingleGas.density(Medium.SingleGas.setState_pTX(medium.state.p,medium.state.T)) + "density of the gas in the tank"; + Real fChaoticLife[N_inlets]; +initial equation + if initialize_pressure then + medium.p = p_start; + end if; + + if initialize_energy then + if use_hstart then + medium.h = h_start; + else + medium.T = T_start; + end if; + end if; + + if initialize_Xi then + medium.Xi = Xi_0; + elseif initialize_LiquidMass then + assert( + V - M_liq_start/liquidDensity > 0, + "Initial liquid mass is larger then the tank can contain", + level=AssertionLevel.error); + medium.Xi = {(V - M_liq_start/liquidDensity)*gasDensity/((V - M_liq_start/ + liquidDensity)*gasDensity + M_liq_start),M_liq_start/((V - M_liq_start/ + liquidDensity)*gasDensity + M_liq_start)}; + end if; + +equation + for i in 1:N_inlets loop + assert( + m_flow_in[i] > m_flow_assert, + "Negative massflow at tank inlet", + dropOfCommons.assertionLevel); + end for; + for i in 1:N_outlets loop + assert( + -m_flow_out[i] > m_flow_assert, + "Positive massflow at tank outlet", + dropOfCommons.assertionLevel); + end for; + + assert(M > 0, "Tanks might not become empty"); + + der(inlet.m_flow)*L = inlet.r - r - r_damping*ones(N_inlets); + der(outlet.m_flow)*L = outlet.r - r_damping*ones(N_outlets); + der(rear.m_flow)*L = rear.r - r_rear - r_damping*ones(N_rears); + der(fore.m_flow)*L = fore.r - r_fore - r_damping*ones(N_fores); + + for i in 1:N_inlets loop + staticHeadInlets_Pa_relative[i] = liquidDensity*acceleration.a*normAcc* + staticHeadInlets[i]; + + if chaoticLife and abs(der(M)) < 1e-1 and Xi_in[1, i] > 0.8 then + fChaoticLife[i] = abs(inlet[i].r)/sqrt((inlet[i].r)^2 + 1e-4^2); + else + fChaoticLife[i] = 0; + end if; + //if ChaoticLife and a "static" state, lower the static head temporarily to allow gas to bubble in + r[i] + p_in[i] = medium.p + (1 - gasBubbleVolume/V_ref*fChaoticLife[i])*max( + 0, staticHeadInlets_Pa_relative[i]); + + // fix potential instabilities by setting the outgoing enthalpy and mass fraction to the medium state + h_in[i] = if noEvent(m_flow_in[i] >= 0) then Medium.specificEnthalpy(inlet[ + i].state) else medium.h; + Xi_in[:, i] = if noEvent(m_flow_in[i] >= 0) then Medium.massFraction(inlet[ + i].state) else medium.Xi; + end for; + + //indication on tank nearly filled with liquid + fFull = if V_liquid > ThresholdFull*V_ref then true else false; + //indication on tank nearly emptied of liquid + fEmpty = if V_liquid < ThresholdEmpty*V_ref then true else false; + + for i in 1:N_outlets loop + // fix potential instabilities by setting the outgoing enthalpy and mass fraction to the medium state + + h_out[i] = if noEvent(-m_flow_out[i] >= 0) then Medium.specificEnthalpy( + state_out[i]) else medium.h; + Xi_out[:, i] = if noEvent(-m_flow_out[i] >= 0) then Medium.massFraction( + state_out[i]) else medium.Xi; + + staticHeadOutlets_Pa_relative[i] = liquidDensity*acceleration.a*normAcc* + staticHeadOutlets[i]; + + //due to the transition interval of the reg_step, connectors must be shifted inside the tank + //perimeters when the tank is nearly filled with liquid and there is an outlet on the surface + //or when the tank is nearly empty and there is an outlet on the surface + //The full case is moved further down to get better numeric performance with more gas remaining + if fFull and abs(staticHeadOutlets[i]) < 4*outletTransition then + shiftOutlet[i] = 3; + elseif fEmpty and abs(staticHeadOutlets[i]) < 3*outletTransition then + shiftOutlet[i] = -1; + else + shiftOutlet[i] = 0; + end if; + //liquid at outlet if static head >0, else gas, with smooth transition + state_out[i] = Medium.setState_pTX( + medium.p + max(0, staticHeadOutlets_Pa_relative[i]), + medium.T, + {ThermofluidStream.Undirected.Internal.regStep( + staticHeadOutlets[i] +shiftOutlet[i]*outletTransition, + 0, + 1, + outletTransition),ThermofluidStream.Undirected.Internal.regStep( + staticHeadOutlets[i] + shiftOutlet[i]*outletTransition, + 1, + 0, + outletTransition)}); + end for; + + for i in 1:N_rears loop + staticHeadRears_Pa_relative[i] = liquidDensity*acceleration.a*normAcc* + staticHeadRears[i]; + //due to the transition interval of the reg_step, connectors must be shifted inside the tank + //perimeters when the tank is nearly filled with liquid and there is an outlet on the surface + //or when the tank is nearly empty and there is an outlet on the surface + //The full case is moved further down to get better numeric performance with more gas remaining + if fFull and abs(staticHeadRears[i]) < 4*outletTransition then + shiftRear[i] = 3; + elseif fEmpty and abs(staticHeadRears[i]) < 3*outletTransition then + shiftRear[i] = -1; + else + shiftRear[i] = 0; + end if; + + r_rear[i] = ThermofluidStream.Undirected.Internal.regStep( + rear[i].m_flow, + medium.p + max(0, staticHeadRears_Pa_relative[i]) - Medium.pressure(rear[ + i].state_forwards), + 0, + m_flow_reg); + // dont regstep variables that are only in der(state), to increase accuracy + h_rear[i] = if rear[i].m_flow >= 0 then Medium.specificEnthalpy(rear[i].state_forwards) + else Medium.specificEnthalpy(state_out_rear[i]); + Xi_rear[:, i] = if rear[i].m_flow >= 0 then Medium.massFraction(rear[i].state_forwards) + else Medium.massFraction(state_out_rear[i]); + + state_out_rear[i] = Medium.setState_pTX( + medium.p + max(0, staticHeadRears_Pa_relative[i]), + medium.T, + {ThermofluidStream.Undirected.Internal.regStep( + staticHeadRears[i] + shiftRear[i]*outletTransition, + 0, + 1, + outletTransition),ThermofluidStream.Undirected.Internal.regStep( + staticHeadRears[i] + shiftRear[i]*outletTransition, + 1, + 0, + outletTransition)}); + + rear[i].state_rearwards = state_out_rear[i]; + end for; + + for i in 1:N_fores loop + staticHeadFores_Pa_relative[i] = liquidDensity*acceleration.a*normAcc* + staticHeadFores[i]; + //due to the transition interval of the reg_step, connectors must be shifted inside the tank + //perimeters when the tank is nearly filled with liquid and there is an outlet on the surface + //or when the tank is nearly empty and there is an outlet on the surface + //The full case is moved further down to get better numeric performance with more gas remaining + if fFull and abs(staticHeadFores[i]) < 4*outletTransition then + shiftFore[i] = 3; + elseif fEmpty and abs(staticHeadFores[i]) < 3*outletTransition then + shiftFore[i] = -1; + else + shiftFore[i] = 0; + end if; + r_fore[i] = ThermofluidStream.Undirected.Internal.regStep( + fore[i].m_flow, + medium.p + max(0, staticHeadFores_Pa_relative[i]) - Medium.pressure(fore[ + i].state_rearwards), + 0, + m_flow_reg); + // dont regstep variables that are only in der(state), to increase accuracy + h_fore[i] = if fore[i].m_flow >= 0 then Medium.specificEnthalpy(fore[i].state_rearwards) + else Medium.specificEnthalpy(state_out_fore[i]); + Xi_fore[:, i] = if fore[i].m_flow >= 0 then Medium.massFraction(fore[i].state_rearwards) + else Medium.massFraction(state_out_fore[i]); + + state_out_fore[i] = Medium.setState_pTX( + medium.p + max(0, staticHeadFores_Pa_relative[i]), + medium.T, + {ThermofluidStream.Undirected.Internal.regStep( + staticHeadFores[i] + shiftFore[i]*outletTransition, + 0, + 1, + outletTransition),ThermofluidStream.Undirected.Internal.regStep( + staticHeadFores[i] + shiftFore[i]*outletTransition, + 1, + 0, + outletTransition)}); + + fore[i].state_forwards = state_out_fore[i]; + end for; + + V_liquid = MXi[end]/liquidDensity; + + medium.p = p_ref + K*(V/V_ref - 1); + + der(M) = sum(inlet.m_flow) + sum(outlet.m_flow) + sum(rear.m_flow) + sum(fore.m_flow); + der(U_med) = W_v + Q_flow + sum(inlet.m_flow .* h_in) + sum(outlet.m_flow .* + h_out) + h_rear*rear.m_flow + h_fore*fore.m_flow; + der(MXi) = Xi_in*inlet.m_flow + Xi_out*outlet.m_flow + Xi_rear*rear.m_flow + + Xi_fore*fore.m_flow; + + Q_flow = U*A*(T_heatPort - medium.T); + W_v = 0; + + outlet.state = state_out; + + if not useHeatport then + T_heatPort = medium.T; + end if; + + annotation ( + Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse( + extent={{-56,76},{64,16}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Rectangle( + extent={{-56,46},{64,-56}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Ellipse( + extent={{-56,-28},{64,-88}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Line( + points={{-100,0},{100,0}}, + color={28,108,200}, + thickness=0.5), + Ellipse( + extent={{-60,-20},{60,-80}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={170,213,255}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-60,50},{60,-50}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={170,213,255}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Ellipse( + extent={{-60,80},{60,20}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={170,213,255}, + fillPattern=FillPattern.Solid), + Line( + points={{-60,50},{-60,-52}}, + color={28,108,200}, + thickness=0.5), + Line( + points={{60,50},{60,-52}}, + color={28,108,200}, + thickness=0.5), + Ellipse(extent={{-60,24},{60,-32}}, lineColor={28,108,200}), + Line( + points={{20,100},{-24,42}}, + color={206,103,0}, + arrow={Arrow.None,Arrow.Filled}, + thickness=1), + Line( + points={{52,78},{8,20}}, + color={206,103,0}, + arrow={Arrow.None,Arrow.Filled}, + thickness=1), + Line( + points={{84,56},{40,-2}}, + color={206,103,0}, + arrow={Arrow.None,Arrow.Filled}, + thickness=1), + Text( + extent={{-120,108},{-94,66}}, + textColor={116,116,116}, + textString="%N_inlets"), + Text( + extent={{98,108},{124,66}}, + textColor={116,116,116}, + textString="%N_outlets"), + Text( + extent={{40,102},{84,70}}, + textColor={206,103,0}, + textString="a"), + Text( + extent={{98,-70},{124,-112}}, + textColor={116,116,116}, + textString="%N_fores"), + Text( + extent={{-122,-70},{-96,-112}}, + textColor={116,116,116}, + textString="%N_rears")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +

To complete the partialTank, equations for total tank volume V, centreOfMass, staticHeadInlets, staticHeadOutlets, staticHeadRears and staticHeadFores needs to be provided.

+

This separation is made to make it easy to implement arbitrary geometries. In this component, medium.p is interpreted as the pressure at the liquid surface.

+

This Volume is the parent class for Accumulator and Receiver models that separate the two phases and are able to output gas, liquid or two-phase medium, depending on its liquid level and the height of the outlet. Numerical stiffness is handled as in VolumeFlex.

+

Since there is no formula to compute density_derp_h for this volume, an upper bound has to be set in the parameter density_derp_h_set. Alternativeley the derivative can be taken from the media model for all the media that implement the corresponding formula by setting density_derp_h_from_media=true (default:false).

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end PartialTankUndirected; diff --git a/ThermofluidStream/Undirected/Boundaries/Internal/package.order b/ThermofluidStream/Undirected/Boundaries/Internal/package.order index a0687706..6925c92a 100644 --- a/ThermofluidStream/Undirected/Boundaries/Internal/package.order +++ b/ThermofluidStream/Undirected/Boundaries/Internal/package.order @@ -1,2 +1,3 @@ PartialVolume PartialVolumeN +PartialTankUndirected diff --git a/ThermofluidStream/Undirected/Boundaries/TankCuboid.mo b/ThermofluidStream/Undirected/Boundaries/TankCuboid.mo new file mode 100644 index 00000000..0453fd6f --- /dev/null +++ b/ThermofluidStream/Undirected/Boundaries/TankCuboid.mo @@ -0,0 +1,152 @@ +within ThermofluidStream.Undirected.Boundaries; +model TankCuboid + "This is a cuboid tank in an acceleration field for the special case of the liquid surface normal to xz-plane." + extends ThermofluidStream.Undirected.Boundaries.Internal.PartialTankUndirected; + //Everything media related is located in the partialTank. Below is only geometry + //dependent equations for the computation of static head and, for now, a + // constant centre of mass. To complete the partialTank equations for total tank volume V, + //centreOfMass, staticHeadInlets and staticHeadOutlets needs to be provided. + //The division is made to easily implement any geometry, regardless of complexity. + + parameter Modelica.Units.SI.Length xLength "Length in x-direction" annotation(Dialog(tab="General",group="Geometry")); + parameter Modelica.Units.SI.Length yLength "Length in y-direction" annotation(Dialog(tab="General",group="Geometry")); + parameter Modelica.Units.SI.Length zLength "Length in z-direction" annotation(Dialog(tab="General",group="Geometry")); + Modelica.Units.SI.Length D; + +protected + final parameter Real eps_geometry = 0.0000001 "numerical epsilon for geometric considerations"; + Modelica.Units.SI.Length D1; + Modelica.Units.SI.Length D2; + Modelica.Units.SI.Length D3; + Modelica.Units.SI.Length D4; + Real nx=normAcc[1]; + Real nz=normAcc[3]; + Modelica.Units.SI.Area Area = V_liquid/yLength; + Modelica.Units.SI.Area AxLimit; + Modelica.Units.SI.Area AzLimit; + +initial equation + + //check that all inlet and outlet positions are within the tank geometry + for i in 1:N_inlets loop + assert(tankCenter[1]-xLength/2<=inletPositions[i,1] and inletPositions[i,1] <= tankCenter[1]+xLength/2, "Inlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[2]-yLength/2<=inletPositions[i,2] and inletPositions[i,2] <= tankCenter[2]+yLength/2,"Inlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[3]-zLength/2<=inletPositions[i,3] and inletPositions[i,3] <= tankCenter[3]+zLength/2,"Inlet outside tank geometry",level = AssertionLevel.error); + end for; + + for i in 1:N_outlets loop + assert(tankCenter[1]-xLength/2<=outletPositions[i,1] and outletPositions[i,1] <= tankCenter[1]+xLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[2]-yLength/2<=outletPositions[i,2] and outletPositions[i,2] <= tankCenter[2]+yLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[3]-zLength/2<=outletPositions[i,3] and outletPositions[i,3] <= tankCenter[3]+zLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + end for; + + for i in 1:N_rears loop + assert(tankCenter[1]-xLength/2<=rearPositions[i,1] and rearPositions[i,1] <= tankCenter[1]+xLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[2]-yLength/2<=rearPositions[i,2] and rearPositions[i,2] <= tankCenter[2]+yLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[3]-zLength/2<=rearPositions[i,3] and rearPositions[i,3] <= tankCenter[3]+zLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + end for; + for i in 1:N_fores loop + assert(tankCenter[1]-xLength/2<=forePositions[i,1] and forePositions[i,1] <= tankCenter[1]+xLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[2]-yLength/2<=forePositions[i,2] and forePositions[i,2] <= tankCenter[2]+yLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + assert(tankCenter[3]-zLength/2<=forePositions[i,3] and forePositions[i,3] <= tankCenter[3]+zLength/2,"Outlet outside tank geometry",level = AssertionLevel.error); + end for; +equation + V_ref =xLength*yLength*zLength; + + assert((Modelica.Math.Vectors.length(normAcc)>0.99 and Modelica.Math.Vectors.length(normAcc)<1.01),"Acceleration vector is not normalized",level = AssertionLevel.error); + assert(-eps_geometry <= normAcc[2] and normAcc[2] <= eps_geometry,"Acceleration in y-direction not supported by squareBlockGeometry",level=AssertionLevel.warning); + assert(V_liquid<=V_ref,"Trying to fit more liquid into tank than it holds",level=AssertionLevel.warning); + + centreOfMass =tankCenter;//constant in first implementation + + // where is the liquid surface? The possible solutions D1 to D4 goes from small liquid volume to large liquid volume. + if nz<0 then + if nx<0 then + //small triangle of liquid + D1 =sqrt(2*abs(nx*nz)*Area); + //rectangle plus triangle of liquid, bottom mostly in z-direction + D2 =-nz*Area/xLength - nx*xLength/2; + //rectangle plus triangle of liquid, bottom mostly in x-direction + D3 =-nx*Area/zLength - nz*zLength/2; + // Full apart from small triangle of gas + D4 =-(nx*xLength + nz*zLength) - sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + else + //nx >=0 + D1 =-nx*xLength + sqrt(2*abs(nx*nz)*Area); + D2 =-nz*Area/xLength - nx*xLength/2; + D3 =nx*Area/zLength - nx*xLength - nz*zLength/2; + D4 =-nz*zLength - sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + end if; + else + //nz >=0 + if nx < 0 then + D1 =-nz*zLength + sqrt(2*abs(nx*nz)*Area); + D2 =nz*Area/xLength - nx*xLength/2 - nz*zLength; + D3 =-nx*Area/zLength - nz*zLength/2; + D4 =-nx*xLength - sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + else + //nx>=0 + D1 =-(nx*xLength + nz*zLength) + sqrt(2*abs(nx*nz)*Area); + D2 =nz*Area/xLength - nx*xLength/2 - nz*zLength; + D3 =nx*Area/zLength - nx*xLength - nz*zLength/2; + D4 =-sqrt(2*abs(nx*nz)*(xLength*zLength - Area)); + + end if; + end if; + + if abs(nx) <= eps_geometry then + D =D2; + AzLimit =0; + AxLimit =0; + elseif abs(nz) <= eps_geometry then + D =D3; + AzLimit =0; + AxLimit =0; + else + AxLimit =abs(nx/nz)*xLength^2/2; + AzLimit =abs(nz/nx)*zLength^2/2; + if (Area <= AzLimit) and (Area <= AxLimit) then + D =D1; + elseif (AxLimit <= Area) and (Area <= xLength*zLength - AxLimit) then + D =D2; + elseif (AzLimit <= Area) and (Area <= xLength*zLength - AzLimit) then + D =D3; + else + D =D4; + end if; + end if; + //D is relative to origo in the tank corner chosen such that all coordinates within the tank are positive + //The distance from a point p to the surface is given by p*normAcc+D +for i in 1:N_inlets loop + staticHeadInlets[i] =(inletPositions[i] - (tankCenter - {xLength/2, + yLength/2,zLength/2}))*normAcc + D; +end for; +for i in 1:N_outlets loop + staticHeadOutlets[i]=(outletPositions[i] - (tankCenter - {xLength/2, + yLength/2,zLength/2}))*normAcc + D; +end for; +for i in 1:N_rears loop + staticHeadRears[i]=(rearPositions[i] - (tankCenter - {xLength/2, + yLength/2,zLength/2}))*normAcc + D; +end for; +for i in 1:N_fores loop + staticHeadFores[i]=(forePositions[i] - (tankCenter - {xLength/2, + yLength/2,zLength/2}))*normAcc + D; +end for; + + annotation (Documentation(info=" +

In order to ensure that the surface is level is perpendicular to the xz-plane, the acceleration in y-direction is neglected.

+

To specify the acceleration vector, please use the AccelerationBoundary component.

+

The tank works only with media that have gas and incompressible parts contained in them.

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end TankCuboid; diff --git a/ThermofluidStream/Undirected/Boundaries/Tests/Tank_fillingClosedTank.mo b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_fillingClosedTank.mo new file mode 100644 index 00000000..8fd4daa0 --- /dev/null +++ b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_fillingClosedTank.mo @@ -0,0 +1,109 @@ +within ThermofluidStream.Undirected.Boundaries.Tests; +model Tank_fillingClosedTank + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=1, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.01,0.99}, + M_liq_start=750, + outletTransition=0.001, + N_outlets=0, + N_rears=0, + N_fores=1, + inletPositions={{0,0,1}}, + tankCenter={0.5,0.5,0.5}, + forePositions={{0,1,0}}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{-40,-6},{-20,14}}))); + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-104,-2},{-84,18}}))); + inner ThermofluidStream.Boundaries.AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-88,-86},{-68,-66}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-58,-82},{-38,-62}}))); + ThermofluidStream.Processes.FlowResistance flowResistance( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=false, + A=0.0028)) + annotation (Placement(transformation(extent={{-70,-2},{-50,18}}))); + TankCuboid tank1( + redeclare package Medium = Medium, + N_inlets=0, + useHeatport=false, + initialize_pressure=true, + p_start=100000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=500, + outletTransition=0.001, + N_outlets=0, + N_rears=1, + N_fores=0, + tankCenter={-0.5,-0.5,-0.5}, + rearPositions={{0,0,-0.7}}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{66,-6},{86,14}}))); + Processes.StaticHead staticHead2(redeclare package Medium = Medium,forePosition={0,0,-0.7}, rearPosition={0,0,1}) + annotation (Placement(transformation(extent={{0,-10},{20,10}}))); + Processes.FlowResistance flowResistance3(redeclare package Medium = Medium, + r=0.03, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{34,-10},{54,10}}))); +equation + connect(source.outlet, flowResistance.inlet) annotation (Line( + points={{-84,8},{-70,8}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.outlet, tank.inlet[1]) annotation (Line( + points={{-50,8},{-39.8,8}}, + color={28,108,200}, + thickness=0.5)); + connect(tank.fore[1], staticHead2.rear) annotation (Line( + points={{-20.2,-0.6},{-18,0},{0,0}}, + color={28,108,200}, + thickness=0.5)); + connect(staticHead2.fore, flowResistance3.rear) annotation (Line( + points={{20,0},{34,0}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance3.fore, tank1.rear[1]) annotation (Line( + points={{54,0},{52,0},{52,-0.6},{66,-0.6}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=20, __Dymola_Algorithm="Dassl"),Documentation( revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end Tank_fillingClosedTank; diff --git a/ThermofluidStream/Undirected/Boundaries/Tests/Tank_overfilling.mo b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_overfilling.mo new file mode 100644 index 00000000..830f90a1 --- /dev/null +++ b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_overfilling.mo @@ -0,0 +1,134 @@ +within ThermofluidStream.Undirected.Boundaries.Tests; +model Tank_overfilling +extends Modelica.Icons.Example; + import ThermofluidStream; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + ThermofluidStream.Boundaries.Source source( + redeclare package Medium = + Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{100,-40},{80,-20}}))); + inner ThermofluidStream.Boundaries.AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-80,-80},{-60,-60}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-40,-80},{-20,-60}}))); + ThermofluidStream.Processes.FlowResistance flowResistance( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=true, + A=0.00005)) + annotation (Placement(transformation(extent={{66,-40},{46,-20}}))); + ThermofluidStream.Processes.FlowResistance flowResistance2( + redeclare package Medium = + Medium, + l=1, + shape=ThermofluidStream.Processes.Internal.ShapeOfResistance.circular, + r=0.03, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1, + fromGeometry=true, + A=0.00005)) + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=-90, + origin={30,10}))); + ThermofluidStream.Undirected.Boundaries.TankCuboid + tank1( + redeclare package Medium = Medium, + chaoticLife=false, + K=20000000, + N_inlets=2, + useHeatport=false, + initialize_pressure=true, + p_start=100000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=750, + outletTransition=0.0001, + N_outlets=0, + N_rears=0, + N_fores=1, + inletPositions={{-0.1,0,0},{0,0,0}}, + tankCenter={-0.5,-0.5,-0.5}, + forePositions={{0,0,0}}, + xLength=1, + yLength=1, + zLength=1) + annotation (Placement(transformation(extent={{-6,-20},{-26,0}}))); + ThermofluidStream.Boundaries.Source source1( + redeclare package Medium = Medium, + T0_par=295.15, + p0_par=500000, + Xi0_par={0,1}) + annotation (Placement(transformation(extent={{10,-10},{-10,10}}, + rotation=90, + origin={30,50}))); + ThermofluidStream.FlowControl.CheckValve checkValve(redeclare package Medium = Medium) + annotation (Placement(transformation(extent={{40,-40},{20,-20}}))); + ThermofluidStream.Undirected.Boundaries.BoundaryFore + boundaryFore1( + redeclare package Medium = Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-80,-24},{-100,-4}}))); + ThermofluidStream.Undirected.Processes.FlowResistance + flowResistance5( + redeclare package Medium = Medium, + r=0.03/1.4, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{-46,-24},{-66,-4}}))); +equation + connect(source.outlet, flowResistance.inlet) annotation (Line( + points={{80,-30},{66,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance2.outlet, tank1.inlet[1]) annotation (Line( + points={{30,0},{30,-8},{8,-8},{8,-6.5},{-6.2,-6.5}}, + color={28,108,200}, + thickness=0.5)); + connect(source1.outlet, flowResistance2.inlet) annotation (Line( + points={{30,40},{30,20}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.outlet, checkValve.inlet) annotation (Line( + points={{46,-30},{40,-30}}, + color={28,108,200}, + thickness=0.5)); + connect(checkValve.outlet, tank1.inlet[2]) annotation (Line( + points={{20,-30},{8,-30},{8,-5.5},{-6.2,-5.5}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance5.fore,boundaryFore1. rear) annotation (Line( + points={{-66,-14},{-80,-14}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance5.rear, tank1.fore[1]) annotation (Line( + points={{-46,-14},{-34,-14},{-34,-14.6},{-25.8,-14.6}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=1000, __Dymola_Algorithm="Dassl"),Documentation( revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end Tank_overfilling; diff --git a/ThermofluidStream/Undirected/Boundaries/Tests/Tank_selfDraining.mo b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_selfDraining.mo new file mode 100644 index 00000000..31699aa8 --- /dev/null +++ b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_selfDraining.mo @@ -0,0 +1,122 @@ +within ThermofluidStream.Undirected.Boundaries.Tests; +model Tank_selfDraining + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=0, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=600, + outletTransition=0.001, + N_outlets=0, + tankCenter={0.5,0.5,0.5}, + rearPositions={{0,0,0.8},{0,0,1}}, + forePositions={{0,0,0.5},{0,0,0.1}}, + xLength=1, + yLength=1, + zLength=1) annotation (Placement(transformation(extent={{-10,-8},{10,12}}))); + inner ThermofluidStream.Boundaries.AccelerationBoundary acceleration( + az=-dropOfCommons.g*10) + annotation (Placement(transformation(extent={{-78,-86},{-58,-66}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-58,-82},{-38,-62}}))); + BoundaryFore boundaryFore(redeclare package Medium = Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{58,-36},{78,-16}}))); + BoundaryRear boundaryRear(redeclare package Medium = Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-96,12},{-76,32}}))); + Processes.FlowResistance flowResistance3(redeclare package Medium = Medium, + r=0.03, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{-56,10},{-36,30}}))); + BoundaryFore boundaryFore1(redeclare package Medium = Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{68,-54},{88,-34}}))); + Processes.FlowResistance flowResistance4( + redeclare package Medium = Medium, + r=0.03, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{-52,-22},{-32,-2}}))); + Processes.FlowResistance flowResistance5( + redeclare package Medium = Medium, + r=0.03, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{30,-54},{50,-34}}))); + Processes.FlowResistance flowResistance6( + redeclare package Medium = Medium, + r=0.03, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{26,-34},{46,-14}}))); + BoundaryRear boundaryRear1( + redeclare package Medium = Medium, + T0_par=295.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-94,-20},{-74,0}}))); +equation + connect(boundaryRear1.fore, flowResistance4.rear) annotation (Line( + points={{-74,-10},{-60,-10},{-60,-12},{-52,-12}}, + color={28,108,200}, + thickness=0.5)); + connect(boundaryRear.fore, flowResistance3.rear) annotation (Line( + points={{-76,22},{-64,22},{-64,20},{-56,20}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance3.fore, tank.rear[1]) annotation (Line( + points={{-36,20},{-22,20},{-22,-4},{-10,-4},{-10,-2.6}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance4.fore, tank.rear[2]) annotation (Line( + points={{-32,-12},{-32,-4},{-10,-4},{-10,-2.6}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance6.fore, boundaryFore.rear) annotation (Line( + points={{46,-24},{46,-26},{58,-26}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance5.fore, boundaryFore1.rear) annotation (Line( + points={{50,-44},{68,-44}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance6.rear, tank.fore[1]) annotation (Line( + points={{26,-24},{16,-24},{16,-10},{18,-10},{18,-2.6},{9.8,-2.6}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance5.rear, tank.fore[2]) annotation (Line( + points={{30,-44},{16,-44},{16,-10},{18,-10},{18,-2.6},{9.8,-2.6}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=40, __Dymola_Algorithm="Dassl"), Documentation(revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end Tank_selfDraining; diff --git a/ThermofluidStream/Undirected/Boundaries/Tests/Tank_upsideDownBottle.mo b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_upsideDownBottle.mo new file mode 100644 index 00000000..b8fce950 --- /dev/null +++ b/ThermofluidStream/Undirected/Boundaries/Tests/Tank_upsideDownBottle.mo @@ -0,0 +1,103 @@ +within ThermofluidStream.Undirected.Boundaries.Tests; +model Tank_upsideDownBottle + extends Modelica.Icons.Example; + package Medium = + ThermofluidStream.Media.additionalMedia.SingleGasAndIncompressible.JP8DryAir; + TankCuboid tank( + redeclare package Medium = Medium, + N_inlets=0, + useHeatport=false, + p_start=99000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.01,0.99}, + M_liq_start=0.38, + outletTransition=0.001, + N_outlets=0, + N_rears=0, + N_fores=1, + tankCenter={0.025,0.025,0.1}, + forePositions={{0,0,0}}, + xLength=0.05, + yLength=0.05, + zLength=0.2) + annotation (Placement(transformation(extent={{0,38},{20,58}}))); + inner ThermofluidStream.Boundaries.AccelerationBoundary acceleration + annotation (Placement(transformation(extent={{-88,-86},{-68,-66}}))); + inner ThermofluidStream.DropOfCommons dropOfCommons(assertionLevel= + AssertionLevel.warning) + annotation (Placement(transformation(extent={{-96,-54},{-76,-34}}))); + TankCuboid tank1( + redeclare package Medium = Medium, + N_inlets=0, + useHeatport=false, + initialize_pressure=true, + p_start=100000, + initialize_energy=true, + T_start=293.15, + initialize_Xi=false, + Xi_0={0.001,0.999}, + M_liq_start=0.1, + outletTransition=0.001, + N_outlets=0, + N_rears=1, + N_fores=1, + tankCenter={-0.05,-0.05,-0.1}, + rearPositions={{0,0,0}}, + forePositions={{-0.01,0,0}}, + xLength=0.1, + yLength=0.1, + zLength=0.2) + annotation (Placement(transformation(extent={{34,-76},{14,-56}}))); + Processes.FlowResistance flowResistance( + redeclare package Medium = Medium, + r=0.03, + l=1, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) + annotation (Placement(transformation(extent={{0,-80},{-20,-60}}))); + Processes.FlowResistance flowResistance3( + redeclare package Medium = Medium, + r=0.01, + l=0.02, + redeclare function pLoss = + ThermofluidStream.Processes.Internal.FlowResistance.zetaPressureLoss ( + zeta=1)) annotation (Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=90, + origin={42,0}))); + BoundaryFore boundaryFore( + redeclare package Medium = Medium, + T0_par=293.15, + p0_par=100000, + Xi0_par={1,0}) + annotation (Placement(transformation(extent={{-40,-80},{-60,-60}}))); +equation + connect(flowResistance3.rear, tank.fore[1]) annotation (Line( + points={{42,10},{42,43.4},{19.8,43.4}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance3.fore, tank1.rear[1]) annotation (Line( + points={{42,-10},{42,-70.6},{34,-70.6}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.fore, boundaryFore.rear) annotation (Line( + points={{-20,-70},{-40,-70}}, + color={28,108,200}, + thickness=0.5)); + connect(flowResistance.rear, tank1.fore[1]) annotation (Line( + points={{0,-70},{0,-70.6},{14.2,-70.6}}, + color={28,108,200}, + thickness=0.5)); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=2000, __Dymola_Algorithm="Dassl"),Documentation( revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+")); +end Tank_upsideDownBottle; diff --git a/ThermofluidStream/Undirected/Boundaries/Tests/package.order b/ThermofluidStream/Undirected/Boundaries/Tests/package.order index 82c8a40d..ed30f848 100644 --- a/ThermofluidStream/Undirected/Boundaries/Tests/package.order +++ b/ThermofluidStream/Undirected/Boundaries/Tests/package.order @@ -3,3 +3,7 @@ TestVolumes Reservoir VolumesDirectCoupling PhaseSeperator +Tank_fillingClosedTank +Tank_overfilling +Tank_selfDraining +Tank_upsideDownBottle diff --git a/ThermofluidStream/Undirected/Boundaries/package.order b/ThermofluidStream/Undirected/Boundaries/package.order index 784157de..9dc7aa4c 100644 --- a/ThermofluidStream/Undirected/Boundaries/package.order +++ b/ThermofluidStream/Undirected/Boundaries/package.order @@ -9,3 +9,4 @@ PhaseSeparator Reservoir Tests Internal +TankCuboid diff --git a/ThermofluidStream/Undirected/Processes/StaticHead.mo b/ThermofluidStream/Undirected/Processes/StaticHead.mo new file mode 100644 index 00000000..2506cff0 --- /dev/null +++ b/ThermofluidStream/Undirected/Processes/StaticHead.mo @@ -0,0 +1,133 @@ +within ThermofluidStream.Undirected.Processes; +model StaticHead "Static head model" + extends ThermofluidStream.Undirected.Interfaces.SISOBiFlow(final clip_p_out= + true); + parameter Modelica.Units.SI.Length forePosition[3] + "Coordinates for the position the static head is computed from" annotation (Dialog(group="Geometry", + enable=true)); + parameter Modelica.Units.SI.Length rearPosition[3] + "Coordinates for the position the static head is computed to" annotation (Dialog(group="Geometry", + enable=true)); + + parameter ThermofluidStream.Utilities.Units.Inertance L_value=dropOfCommons.L + "Inertance of pipe" annotation (Dialog(tab="Advanced", enable=not computeL)); + + parameter Modelica.Units.SI.Density rho_min=dropOfCommons.rho_min + "Minimal input density" annotation (Dialog(tab="Advanced")); + + Modelica.Units.SI.Length staticHead_forwards "static head in m"; + Modelica.Units.SI.Pressure staticHead_forwards_Pa_relative "static head measured i Pa, taking current acceleration and limitations into account"; + Modelica.Units.SI.Length staticHead_rearwards "static head in m"; + Modelica.Units.SI.Pressure staticHead_rearwards_Pa_relative "static head measured i Pa, taking current acceleration and limitations into account"; + parameter Boolean displayPositions=true "show positions in icon"; + +protected + outer ThermofluidStream.Boundaries.AccelerationBoundary acceleration; + +equation + + //forwards model + dp_fore = (forePosition - rearPosition)*acceleration.a*Medium.density(rear.state_forwards); + h_fore_out = h_rear_in; + Xi_fore_out = Xi_rear_in; + staticHead_forwards= (p_fore_out-p_rear_in)/max(abs(dp_fore),1e-12)*(forePosition - rearPosition)*Modelica.Math.Vectors.normalize(acceleration.a); + staticHead_forwards_Pa_relative=p_fore_out-p_rear_in; + + //rearwards model + dp_rear = -(forePosition - rearPosition)*acceleration.a*Medium.density(fore.state_rearwards); + h_rear_out = h_fore_in; + Xi_rear_out = Xi_fore_in; + staticHead_rearwards= (p_rear_out-p_fore_in)/max(abs(dp_rear),1e-12)*(forePosition - rearPosition)*Modelica.Math.Vectors.normalize(acceleration.a); + staticHead_rearwards_Pa_relative=p_rear_out-p_fore_in; + + + annotation (Documentation(info=" +

Implementation of static head in a pipe. Bidirectional implementation.

+

To specify the acceleration vector, please use the AccelerationBoundary component.

+

Default is pure graviation in the negative z-direction.

+

Energy is moved between potential energy in an acceleration field and internal energy (pressure).

+

The main assumption is that the density is constant for the pressure change along the pipe. That would be the case for non-compressible fluids and many gases at low Mach numbers. For more insight in this look into the difference between the simplified and generalised forms of the Bernoulli equation.

+

Note that it is only the position difference that influence the pressure difference, not the absolute positions. If the inlet pressure is not sufficient to overcome the acceleration field between the pipe ends the static head is less than the length given by the position difference in the acceleration direction.

+

Beware: This is a new addition to the library. It may be subject to design reconsiderations in future versions

+", revisions=" +

Author: Ingela Lind, M Sc, Ph D, Technical Fellow, +Simulation and Thermal Analysis, +Vehicle Systems, +SAAB Aerosystems, 2024 +

+"), +Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Ellipse( + extent={{-56,54},{64,-66}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Ellipse( + extent={{-56,52},{64,-68}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Line( + points={{-100,0},{100,0}}, + color={28,108,200}, + thickness=0.5), + Ellipse( + extent={{-60,60},{60,-60}}, + lineColor={28,108,200}, + lineThickness=0.5, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text(visible=displayPositions, + extent={{-164,118},{0,18}}, + textColor={28,108,200}, + textString="%rearPosition"), + Text( + visible=displayPositions, + extent={{-2,-22},{160,-120}}, + textColor={28,108,200}, + textString="%forePosition"), + Line( + points={{28,70},{-16,12}}, + color={206,103,0}, + thickness=1), + Text( + extent={{-46,4},{8,-38}}, + textColor={206,103,0}, + textString="a"), + Line( + points={{-18,10},{-16,26}}, + color={206,103,0}, + thickness=1), + Line( + points={{-18,10},{-4,14}}, + color={206,103,0}, + thickness=1), + Line( + points={{-2,-2},{0,14}}, + color={206,103,0}, + thickness=1), + Line( + points={{44,58},{0,0}}, + color={206,103,0}, + thickness=1), + Line( + points={{-2,-2},{12,2}}, + color={206,103,0}, + thickness=1), + Line( + points={{14,-14},{16,2}}, + color={206,103,0}, + thickness=1), + Line( + points={{60,46},{16,-12}}, + color={206,103,0}, + thickness=1), + Line( + points={{14,-14},{28,-10}}, + color={206,103,0}, + thickness=1)})); +end StaticHead; diff --git a/ThermofluidStream/Undirected/Processes/package.order b/ThermofluidStream/Undirected/Processes/package.order index b7af9f47..cea160ba 100644 --- a/ThermofluidStream/Undirected/Processes/package.order +++ b/ThermofluidStream/Undirected/Processes/package.order @@ -3,3 +3,4 @@ TransportDelay ConductionElement Tests Internal +StaticHead