diff --git a/.impact/project.json b/.impact/project.json new file mode 100644 index 00000000..779c9bb8 --- /dev/null +++ b/.impact/project.json @@ -0,0 +1,57 @@ +{ + "name": "ThermofluidStream", + "format": "1.0.0", + "dependencies": [ + { + "name": "Modelica", + "versionSpecifier": "4.0.0" + } + ], + "content": [ + { + "relpath": "ThermofluidStream", + "contentType": "MODELICA", + "name": "ThermofluidStream", + "defaultDisabled": false, + "id": "e74f4457bc544294b6e50858706270d6" + }, + { + "relpath": "TILMediaWrapper", + "contentType": "MODELICA", + "name": "TILMediaWrapper", + "defaultDisabled": false, + "id": "a79a8cc6a9174ffdb2dd3823e48003ac" + }, + { + "relpath": "Resources/Views", + "contentType": "VIEWS", + "defaultDisabled": false, + "id": "aac16222f99f466c964a95374ce14877" + }, + { + "relpath": "Resources/Favorites", + "contentType": "FAVORITES", + "defaultDisabled": false, + "id": "a8b7ca68eff743bbbe6ef284693f7c5b" + }, + { + "relpath": "Resources/CustomFunctions", + "contentType": "CUSTOM_FUNCTIONS", + "defaultDisabled": false, + "id": "41005c09694840d1a8846873932506b8" + }, + { + "relpath": "Resources/Custom", + "contentType": "GENERIC", + "defaultDisabled": false, + "id": "7c56884aa265475b8c6c388a6fa8326e" + }, + { + "relpath": "Resources/ExperimentDefinitions", + "contentType": "EXPERIMENT_DEFINITIONS", + "defaultDisabled": false, + "id": "7c0cf26cfdd04ff198522c9ea7d6298e" + } + ], + "executionOptions": [] +} diff --git a/ThermofluidStream/HeatExchangers/CounterFlowNTU.mo b/ThermofluidStream/HeatExchangers/CounterFlowNTU.mo index 8384f2db..40d73d95 100644 --- a/ThermofluidStream/HeatExchangers/CounterFlowNTU.mo +++ b/ThermofluidStream/HeatExchangers/CounterFlowNTU.mo @@ -1,7 +1,7 @@ within ThermofluidStream.HeatExchangers; model CounterFlowNTU "Counter flow heat exchanger using the epsilon-NTU method" - extends ThermofluidStream.HeatExchangers.Internal.PartialNTU; + extends ThermofluidStream.HeatExchangers.Internal.PartialNTUCounterFlow; equation //Calculating heat exchanger effectiveness derived from NTU correlations (see VDI Waermeatlas) diff --git a/ThermofluidStream/HeatExchangers/CrossFlowNTU.mo b/ThermofluidStream/HeatExchangers/CrossFlowNTU.mo index 4bf8cc68..e180c7ed 100644 --- a/ThermofluidStream/HeatExchangers/CrossFlowNTU.mo +++ b/ThermofluidStream/HeatExchangers/CrossFlowNTU.mo @@ -1,7 +1,7 @@ within ThermofluidStream.HeatExchangers; model CrossFlowNTU "Cross flow heat exchanger using the epsilon-NTU method" - extends ThermofluidStream.HeatExchangers.Internal.PartialNTU(crossFlow=true); + extends ThermofluidStream.HeatExchangers.Internal.PartialNTUCrossFlow(crossFlow=true); equation //Calculating heat exchanger effectiveness derived from NTU correlations (see VDI Waermeatlas) diff --git a/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX.mo b/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX.mo index e622fc72..8d7193e3 100644 --- a/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX.mo +++ b/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX.mo @@ -1,7 +1,7 @@ within ThermofluidStream.HeatExchangers; model DiscretizedCounterFlowHEX "Discretized heat exchanger for single- or two-phase working fluids without pressure drop" - extends Internal.PartialDiscretizedHEX; + extends Internal.PartialDiscretizedHEXCounterFlow; initial equation if initializeMassFlow then diff --git a/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX_FR.mo b/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX_FR.mo index 7e202695..4d6bb8de 100644 --- a/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX_FR.mo +++ b/ThermofluidStream/HeatExchangers/DiscretizedCounterFlowHEX_FR.mo @@ -1,7 +1,7 @@ within ThermofluidStream.HeatExchangers; model DiscretizedCounterFlowHEX_FR "Discretized Heat Exchanger for single- or two-phase working fluid with pressure drop" - extends Internal.PartialDiscretizedHEX; + extends Internal.PartialDiscretizedHEXCrossFlow; parameter Real k1_A=1e2 "Linear flow resistance coefficient at side A" annotation (Dialog(group="Flow resistance coefficients")); diff --git a/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX.mo b/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX.mo index fa6a3804..9e536f92 100644 --- a/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX.mo +++ b/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX.mo @@ -1,7 +1,7 @@ within ThermofluidStream.HeatExchangers; model DiscretizedCrossFlowHEX "Discretized heat exchanger for single- or two-phase working fluid without pressure drop" - extends Internal.PartialDiscretizedHEX(nCellsParallel=nCells,crossFlow=true); + extends Internal.PartialDiscretizedHEXCrossFlow(nCellsParallel=nCells,crossFlow=true); Processes.FlowResistance flowResistanceA[nCells]( redeclare package Medium = MediumA, diff --git a/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX_FR.mo b/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX_FR.mo index e2867610..2714af04 100644 --- a/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX_FR.mo +++ b/ThermofluidStream/HeatExchangers/DiscretizedCrossFlowHEX_FR.mo @@ -1,7 +1,7 @@ within ThermofluidStream.HeatExchangers; model DiscretizedCrossFlowHEX_FR "Discretized Heat Exchanger for single- or two-phase working fluid with pressure drop" - extends Internal.PartialDiscretizedHEX(nCellsParallel=nCells,crossFlow=true); + extends Internal.PartialDiscretizedHEXCrossFlow(nCellsParallel=nCells,crossFlow=true); parameter Real k1_A=1e2 "Linear flow resistance coefficient at side A" annotation (Dialog(group="Flow resistance coefficients")); diff --git a/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEXCounterFlow.mo b/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEXCounterFlow.mo new file mode 100644 index 00000000..d93d5b51 --- /dev/null +++ b/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEXCounterFlow.mo @@ -0,0 +1,183 @@ +within ThermofluidStream.HeatExchangers.Internal; + +partial model PartialDiscretizedHEXCounterFlow "Base class for discretized heat exchangers" + + extends .ThermofluidStream.Utilities.DropOfCommonsPlus; + extends .ThermofluidStream.HeatExchangers.Internal.DiscretizedHexIcon; + + replaceable package MediumA = .ThermofluidStream.Media.myMedia.Interfaces.PartialMedium "Medium model side A" + annotation (choicesAllMatching=true, Dialog(group="Medium definitions")); + replaceable package MediumB = .ThermofluidStream.Media.myMedia.Interfaces.PartialMedium "Medium model side B" + annotation (choicesAllMatching=true, Dialog(group="Medium definitions")); + replaceable model ConductionElementA = .ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX + constrainedby .ThermofluidStream.HeatExchangers.Internal.PartialConductionElementHEX( + final nCellsParallel=nCellsParallel, + final A=A/nCells, + final V=V_Hex/nCells, + redeclare package Medium = MediumA, + final enforce_global_energy_conservation=enforce_global_energy_conservation) "Heat transfer element model for side A" annotation (choicesAllMatching=true, Dialog(group="Medium definitions")); + replaceable model ConductionElementB = .ThermofluidStream.HeatExchangers.Internal.ConductionElementHEX + constrainedby .ThermofluidStream.HeatExchangers.Internal.PartialConductionElementHEX( + final nCellsParallel=1, + final A=A/nCells, + final V=V_Hex/nCells, + redeclare package Medium = MediumB, + final enforce_global_energy_conservation=enforce_global_energy_conservation) "Heat transfer element model for side B" annotation (choicesAllMatching=true, Dialog(group="Medium definitions")); + + parameter Integer nCells=3 "Number of discretization elements"; + parameter Boolean calculate_efficiency=false "= true, if heat exchanger efficiency is calculated" + annotation(Evaluate=true, HideResult=true, choices(checkBox=true)); + + parameter .Modelica.Units.SI.Area A=10 "Heat transfer area" + annotation (Dialog(group="Heat transfer parameters")); + parameter .Modelica.Units.SI.Volume V_Hex=0.001 "Volume for heat transfer calculation" + annotation (Dialog(group="Heat transfer parameters")); + parameter .Modelica.Units.SI.CoefficientOfHeatTransfer k_wall=100 "Coefficient of heat transfer for pipe wall" + annotation (Dialog(group="Heat transfer parameters")); + + parameter Boolean initializeMassFlow=false "= true, if inlet mass flow rates are initialized" + annotation (Dialog(tab="Initialization", group="Mass flow rate"),Evaluate=true, HideResult=true, choices(checkBox=true)); + parameter .Modelica.Units.SI.MassFlowRate m_flow_0_A=0 "Initial mass flow rate for side A" + annotation (Dialog( + tab="Initialization", + group="Mass flow rate", + enable=initializeMassFlow)); + parameter .Modelica.Units.SI.MassFlowRate m_flow_0_B=0 "Initial mass flow rate for side B" + annotation (Dialog( + tab="Initialization", + group="Mass flow rate", + enable=initializeMassFlow)); + parameter .Modelica.Units.SI.MassFlowRate m_flow_assert(max=0) = -dropOfCommons.m_flow_reg "Assertion threshold for negative mass flow rate" + annotation (Dialog(tab="Advanced")); + parameter Boolean enforce_global_energy_conservation=false "= true, if global conservation of energy is enforced" + annotation (Dialog(tab="Advanced"),Evaluate=true, HideResult=true, choices(checkBox=true)); + + // ------ Parameter Display Configuration ------------------------ + parameter Boolean displayArea = true "= true, if heat transfer area A is displayed" + annotation(Dialog(tab="Layout",group="Display parameters",enable=displayParameters),Evaluate=true, HideResult=true, choices(checkBox=true)); + final parameter Boolean d1A = displayParameters and displayArea "displayArea at position 1" + annotation(Evaluate=true, HideResult=true); //d1A -> Display at position 1 A=Area + //----------------------------------------------------------------- + + .ThermofluidStream.Interfaces.Inlet inletB(redeclare package Medium = MediumB) + annotation (Placement(transformation(extent={{-120,40},{-80,80}}), iconTransformation(extent={{-120,40},{-80,80}}))); + .ThermofluidStream.Interfaces.Outlet outletB(redeclare package Medium = MediumB) + annotation (Placement(transformation(extent={{80,40},{120,80}}), iconTransformation(extent={{80,40},{120,80}}))); + .ThermofluidStream.Interfaces.Inlet inletA(redeclare package Medium = MediumA) + annotation (Placement(transformation(extent={{120,-80},{80,-40}}), iconTransformation(extent={{120,-80},{80,-40}}, rotation=0))); + .ThermofluidStream.Interfaces.Outlet outletA(redeclare package Medium = MediumA) + annotation (Placement(transformation(extent={{-80,-80},{-120,-40}}), iconTransformation(extent={{-80,-80},{-120,-40}}, rotation=0))); + + + .Modelica.Units.SI.HeatFlowRate Q_flow_A=sum(thermalElementA.heatPort.Q_flow) "Heat flow rate into medium A"; + .Modelica.Units.SI.HeatFlowRate Q_flow_B=sum(thermalElementB.heatPort.Q_flow) "Heat flow rate into medium B"; + .Modelica.Units.SI.Mass M_A=sum(thermalElementA.M) "Mass of medium A"; + .Modelica.Units.SI.Mass M_B=sum(thermalElementB.M) "Mass of medium B"; + .Modelica.Units.SI.Energy deltaE_system=sum(thermalElementA.deltaE_system) + sum(thermalElementB.deltaE_system) "Error in global conservation of energy"; + + + .ThermofluidStream.HeatExchangers.Internal.DiscretizedHEXSummary summary "Summary record of Quantities"; + +protected + parameter Boolean crossFlow=false "Selection whether HEX is in crossflow or counterflow configuration"; + parameter Integer nCellsParallel=1 "Number of discretization elements in parallel"; + parameter .Modelica.Units.SI.ThermalConductance G=k_wall*A "Wall thermal conductance" + annotation (Dialog(group="Wall parameters")); + function efficiency = .ThermofluidStream.HeatExchangers.Internal.calculateEfficiency (redeclare package MediumA = MediumA, redeclare package MediumB = MediumB) "Heat exchanger efficiency"; + +public + .Modelica.Thermal.HeatTransfer.Components.ThermalConductor thermalConductor[nCells](each G=G/nCells) annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={0,0}))); + + ConductionElementB thermalElementB[nCells] annotation (Placement(transformation(extent={{-10,50},{10,70}}))); + ConductionElementA thermalElementA[nCells] annotation (Placement(transformation(extent={{10,-50},{-10,-70}}))); + +equation + assert( + inletB.m_flow > m_flow_assert, + "Negative mass flow rate at inlet B", + dropOfCommons.assertionLevel); + assert( + inletA.m_flow > m_flow_assert, + "Negative massflow at inlet A", + dropOfCommons.assertionLevel); + + //Summary record + summary.Tin_B = MediumB.temperature(inletB.state); + summary.Tin_A = MediumA.temperature(inletA.state); + summary.Tout_B = MediumB.temperature(outletB.state); + summary.Tout_A = MediumA.temperature(outletA.state); + summary.hin_B = MediumB.specificEnthalpy(inletB.state); + summary.hin_A = MediumA.specificEnthalpy(inletA.state); + summary.hout_B = MediumB.specificEnthalpy(outletB.state); + summary.hout_A = MediumA.specificEnthalpy(outletA.state); + summary.dT_A = summary.Tout_A - summary.Tin_A; + summary.dT_B = summary.Tout_B - summary.Tin_B; + summary.dh_A = summary.hout_A - summary.hin_A; + summary.dh_B = summary.hout_B - summary.hin_B; + summary.Q_flow_A = Q_flow_A; + summary.Q_flow_B = Q_flow_B; + summary.efficiency = if calculate_efficiency then efficiency( + inletA.state, + inletB.state, + outletA.state, + outletB.state, + inletA.m_flow, + inletB.m_flow, + Q_flow_A) else 0; + + annotation (Documentation(info=" +
+This is the partial parent class for discretized heat exchangers. It contains
+the inlet and outlet connectors as well as a number of conduction elements (which
+is set by the parameter nCells) as discrete control volumes to
+exchange heat between two fluid streams.
+
+The conduction elements are computing a heat transfer coefficient between their +heatport and the fluid contained. They are replaceable with a choice between +a single-phase and a two-phase version, both can be further parametrized. +Although the single-phase version works for two-phase media (not the other +way around), using the two-phase one for two-phase media enables to set different +heat transfer coefficients depending on the phase (liquid/gaseous/2-phase) state +of the medium. +
++Note that since the model uses conductionElements as discrete control volumes that +in turn assume quasi-stationary mass and, therefore, are part of a fluid stream +rather than break it into two (like a full volume would), the same holds for +both sides of the heat exchanger – they are part of a fluid stream and +don't break it. The quasi-stationary mass assumption also implies that for +(fast) changing masses/densities in any of the conduction elements the heat +exchanger will (slightly) violate the conservation of energy. Furthermore, the +conduction elements change their behavior for reversed mass-flow, therefore, this +model asserts for negative mass-flow with the level +"DropOfCommons.assertionLevel". +
+
+The parameters A (heat transferring area), k_wall (heat
+transfer coefficient of the wall between the streams) and the heat transfer
+coefficients in the conduction elements scale the transferred heat (the middle
+only if the wall and the latter only of the heat transfer into a fluid is the
+choke of the heatflow).
+
+The parameter V determines the amount of fluid in the heat exchanger
+and, therefore, the dynamic for non-steady states.
+
+The "Initialization" tab allows for a mass-flow initialization for both paths. +
++The "Advanced" tab allows to modify the massflow that triggers the +reverse-massflow-assertion and has an option to enforce global conservation of +energy. The latter is done by feeding back any energy the conduction elements +accumulated over time, basically making it impossible to store energy in their +fluid long-term. While this enforces long-term conservation of energy, it +changes the medium-/short-term dynamics of the system and is, therefore, +disabled by default. +
+")); +end PartialDiscretizedHEXCounterFlow; diff --git a/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEX.mo b/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEXCrossFlow.mo similarity index 94% rename from ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEX.mo rename to ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEXCrossFlow.mo index 4314df40..e51a1bb7 100644 --- a/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEX.mo +++ b/ThermofluidStream/HeatExchangers/Internal/PartialDiscretizedHEXCrossFlow.mo @@ -1,5 +1,5 @@ within ThermofluidStream.HeatExchangers.Internal; -partial model PartialDiscretizedHEX "Base class for discretized heat exchangers" +partial model PartialDiscretizedHEXCrossFlow "Base class for discretized heat exchangers" extends ThermofluidStream.Utilities.DropOfCommonsPlus; extends Internal.DiscretizedHexIcon; @@ -59,13 +59,13 @@ partial model PartialDiscretizedHEX "Base class for discretized heat exchangers" //----------------------------------------------------------------- Interfaces.Inlet inletB(redeclare package Medium = MediumB) - annotation (Placement(transformation(extent={{-120,40},{-80,80}}), iconTransformation(extent=if crossFlow then {{120,-80},{80,-40}} else {{-120,40},{-80,80}}))); + annotation (Placement(transformation(extent={{-120,40},{-80,80}}), iconTransformation(extent= {{120,-80},{80,-40}}))); Interfaces.Outlet outletB(redeclare package Medium = MediumB) - annotation (Placement(transformation(extent={{80,40},{120,80}}), iconTransformation(extent=if crossFlow then {{-80,-80},{-120,-40}} else {{80,40},{120,80}}))); + annotation (Placement(transformation(extent={{80,40},{120,80}}), iconTransformation(extent={{-80,-80},{-120,-40}}))); Interfaces.Inlet inletA(redeclare package Medium = MediumA) - annotation (Placement(transformation(extent={{120,-80},{80,-40}}), iconTransformation(extent=if crossFlow then {{-120,-20},{-80,20}} else {{120,-80},{80,-40}}, rotation=if crossFlow then -90 else 0))); + annotation (Placement(transformation(extent={{120,-80},{80,-40}}), iconTransformation(extent={{-120,-20},{-80,20}}, rotation=-90))); Interfaces.Outlet outletA(redeclare package Medium = MediumA) - annotation (Placement(transformation(extent={{-80,-80},{-120,-40}}), iconTransformation(extent=if crossFlow then {{80,-20},{120,20}} else {{-80,-80},{-120,-40}}, rotation=if crossFlow then -90 else 0))); + annotation (Placement(transformation(extent={{-80,-80},{-120,-40}}), iconTransformation(extent={{80,-20},{120,20}}, rotation=-90))); SI.HeatFlowRate Q_flow_A=sum(thermalElementA.heatPort.Q_flow) "Heat flow rate into medium A"; @@ -179,4 +179,4 @@ changes the medium-/short-term dynamics of the system and is, therefore, disabled by default.