diff --git a/Chemical/Boundaries.mo b/Chemical/Boundaries.mo index c847cf3..e7a3bef 100644 --- a/Chemical/Boundaries.mo +++ b/Chemical/Boundaries.mo @@ -1076,8 +1076,8 @@ Test package for the Boundaries package of ThermofluidStream. Real r_out,n_flow_out,u_out,h_out; equation - assert(n_flow_in > n_flow_assert, "Negative massflow at Volume inlet", dropOfCommons.assertionLevel); - assert(-n_flow_out > n_flow_assert, "Positive massflow at Volume outlet", dropOfCommons.assertionLevel); + //assert(n_flow_in > n_flow_assert, "Negative massflow at Volume inlet", dropOfCommons.assertionLevel); + //assert(-n_flow_out > n_flow_assert, "Positive massflow at Volume outlet", dropOfCommons.assertionLevel); assert(x > 0, "Molar fraction must be positive"); n_flow = n_flow_in + n_flow_out; diff --git a/Chemical/Examples.mo b/Chemical/Examples.mo index 99f0df4..3b9b4ed 100644 --- a/Chemical/Examples.mo +++ b/Chemical/Examples.mo @@ -3145,7 +3145,7 @@ extends Modelica.Icons.ExamplesPackage; points={{-8,54},{-8,46},{0,46}}, color={107,45,134})); connect(R1.port_a,oxyR2. products[1]) annotation (Line( - points={{0,46},{0,32},{-8,32}}, + points={{0,46},{0,32},{-11,32}}, color={107,45,134})); connect(oxyR2.substrates[1],R2. port_a) annotation (Line( points={{-10,12},{-10,0},{0,0}}, @@ -3154,28 +3154,28 @@ extends Modelica.Icons.ExamplesPackage; points={{-10,-34},{-10,-44},{0,-44}}, color={107,45,134})); connect(oxyR3.products[1],R2. port_a) annotation (Line( - points={{-8,-14},{-8,-7},{0,-7},{0,0}}, + points={{-11,-14},{-11,-7},{0,-7},{0,0}}, color={107,45,134})); connect(R3.port_a,oxyR4. products[1]) annotation (Line( - points={{0,-44},{0,-56},{-8,-56}}, + points={{0,-44},{0,-56},{-11,-56}}, color={107,45,134})); connect(oxyR4.substrates[1],R4. port_a) annotation (Line( points={{-10,-76},{-10,-82},{0,-82}}, color={107,45,134})); connect(oxyT1.products[1],T0. port_a) annotation (Line( - points={{42,74},{42,88},{54,88}}, + points={{45,74},{45,88},{54,88}}, color={107,45,134})); connect(oxyT1.substrates[1],T1. port_a) annotation (Line( points={{44,54},{44,46},{54,46}}, color={107,45,134})); connect(T1.port_a,oxyT2. products[1]) annotation (Line( - points={{54,46},{54,32},{42,32}}, + points={{54,46},{54,32},{45,32}}, color={107,45,134})); connect(oxyT3.substrates[1],T3. port_a) annotation (Line( points={{44,-34},{44,-44},{54,-44}}, color={107,45,134})); connect(T3.port_a,oxyT4. products[1]) annotation (Line( - points={{54,-44},{54,-56},{42,-56}}, + points={{54,-44},{54,-56},{45,-56}}, color={107,45,134})); connect(oxyT4.substrates[1],T4. port_a) annotation (Line( points={{44,-76},{44,-82},{54,-82}}, @@ -3184,7 +3184,7 @@ extends Modelica.Icons.ExamplesPackage; points={{0,88},{4,88}}, color={107,45,134})); connect(R0.port_a,oxyR1. products[1]) annotation (Line( - points={{0,88},{0,74},{-6,74}}, + points={{0,88},{0,74},{-9,74}}, color={107,45,134})); connect(R1.port_a,quaternaryForm1. substrates[1]) annotation (Line( points={{0,46},{8,46}}, @@ -3209,35 +3209,35 @@ extends Modelica.Icons.ExamplesPackage; color={107,45,134})); connect(oxyR1.products[2],oxygen_unbound. port_a) annotation (Line( - points={{-10,74},{-42,74},{-42,-36}}, + points={{-7,74},{-42,74},{-42,-36}}, color={107,45,134})); connect(oxyR2.products[2],oxygen_unbound. port_a) annotation (Line( - points={{-12,32},{-42,32},{-42,-36}}, + points={{-9,32},{-42,32},{-42,-36}}, color={107,45,134})); connect(oxyR3.products[2],oxygen_unbound. port_a) annotation (Line( - points={{-12,-14},{-42,-14},{-42,-36}}, + points={{-9,-14},{-42,-14},{-42,-36}}, color={107,45,134})); connect(oxyR4.products[2],oxygen_unbound. port_a) annotation (Line( - points={{-12,-56},{-42,-56},{-42,-36}}, + points={{-9,-56},{-42,-56},{-42,-36}}, color={107,45,134})); connect(oxygen_unbound.port_a, oxyT1.products[2]) annotation (Line( - points={{-42,-36},{-42,74},{46,74}}, + points={{-42,-36},{-42,74},{43,74}}, color={107,45,134})); connect(oxygen_unbound.port_a, oxyT2.products[2]) annotation (Line( - points={{-42,-36},{-42,32},{46,32}}, + points={{-42,-36},{-42,32},{43,32}}, color={107,45,134})); connect(oxygen_unbound.port_a, oxyT3.products[2]) annotation (Line( - points={{-42,-36},{-42,-14},{46,-14}}, + points={{-42,-36},{-42,-14},{43,-14}}, color={107,45,134})); connect(oxygen_unbound.port_a, oxyT4.products[2]) annotation (Line( - points={{-42,-36},{-42,-56},{46,-56}}, + points={{-42,-36},{-42,-56},{43,-56}}, color={107,45,134})); connect(O2_in_air.port_a, gasSolubility.gas_port) annotation (Line( points={{-84,12},{-84,4}}, @@ -3283,7 +3283,7 @@ extends Modelica.Icons.ExamplesPackage; points={{44,12},{44,0},{54,0}}, color={158,66,200})); connect(T2.port_a, oxyT3.products[1]) annotation (Line( - points={{54,0},{54,-14},{42,-14}}, + points={{54,0},{54,-14},{45,-14}}, color={158,66,200})); connect(T2.solution, solution.solution) annotation (Line(points={{38,-10}, {38,-99.74},{60.8,-99.74}}, @@ -3351,145 +3351,180 @@ extends Modelica.Icons.ExamplesPackage; parameter Real KC = 1e-6 "Slow down factor"; //0.000001 - Chemical.Solution solution annotation (Placement(transformation(extent={{-100,-100},{100,42}}))); + Chemical.Solution solution annotation (Placement(transformation(extent={{-100,-100},{100,100}}))); - Chemical.Components.Reaction quaternaryForm( + Chemical.Processes.Reaction quaternaryForm( nS=1, nP=1, - KC=KC) annotation (Placement(transformation(extent={{12,-58},{32,-38}}))); - Chemical.Components.Speciation R0_in_R(NumberOfSubunits=4) annotation (Placement(transformation(extent={{-46,-48},{-26,-28}}))); + KC=KC) annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=180, + origin={22,-48}))); + Processes.SpeciationIn R0_in_R(NumberOfSubunits=4) annotation (Placement(transformation(extent={{-46,-48},{-26,-28}}))); // AmountOfSubstance_start=4e-11) - Chemical.Components.Speciation T0_in_T(NumberOfSubunits=4) annotation (Placement(transformation(extent={{74,-48},{54,-28}}))); + Processes.SpeciationOut T0_in_T(NumberOfSubunits=4) annotation (Placement(transformation(extent={{74,-48},{54,-28}}))); // AmountOfSubstance_start=totalAmountOfHemoglobin) - Chemical.Components.Substance OxyRHm[4]( + Chemical.Boundaries.Substance OxyRHm[4]( + useInlet=true, + useOutlet=false, redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, each substanceData(DfG=DfG_O2 + RT*log(KRx) + DfG_tR/4), each use_mass_start=false, - each amountOfSubstance_start=5.88e-9) "Oxygenated subunit in R structure of hemoglobin tetramer" - annotation (Placement(transformation(extent={{-96,-18},{-76,2}}))); + each amountOfSubstance_start=2e-12) "Oxygenated subunit in R structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{-76,-20},{-96,0}}))); - Chemical.Components.Reaction oxygenation_R[4]( - each nS=1, - each nP=2, - each KC=KC) annotation (Placement(transformation(extent={{-68,-18},{-48,2}}))); - Chemical.Components.Substance DeoxyRHm[4]( + Chemical.Processes.Reaction oxygenation_R[4]( + each nS=2, each nP=1, each KC=KC) annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=180, + origin={-52,-10}))); + Chemical.Boundaries.Substance DeoxyRHm[4]( + useInlet=true, redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, each substanceData(DfG=DfG_tR/4), each use_mass_start=false, - each amountOfSubstance_start=1.58e-7) "Deoxygenated subunit in R structure of hemoglobin tetramer" + each amountOfSubstance_start=1.471e-10) + "Deoxygenated subunit in R structure of hemoglobin tetramer" annotation (Placement(transformation(extent={{-8,-20},{-28,0}}))); - Chemical.Components.Substance OxyTHm[4]( + Chemical.Boundaries.Substance OxyTHm[4]( + useInlet=true, + useOutlet=false, redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, each substanceData(DfG=DfG_O2 + RT*log(KTx) + DfG_tT/4), each use_mass_start=false, - each amountOfSubstance_start=1e-4) "Oxygenated subunit in T structure of hemoglobin tetramer" - annotation (Placement(transformation(extent={{14,-18},{34,2}}))); + each amountOfSubstance_start=5e-8) "Oxygenated subunit in T structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{28,-16},{8,4}}))); - Chemical.Components.Reaction oxygenation_T[4]( - each nS=1, - each nP=2, - each KC=KC) annotation (Placement(transformation(extent={{42,-18},{62,2}}))); - Chemical.Components.Substance DeoxyTHm[4]( + Chemical.Processes.Reaction oxygenation_T[4]( + each nS=2, each nP=1, + each KC=KC) annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=180, + origin={40,-8}))); + Chemical.Boundaries.Substance DeoxyTHm[4]( redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, each substanceData(DfG=DfG_tT/4), each use_mass_start=false, - each amountOfSubstance_start=THb - 1e-4 - 1.58e-7 - 5.88e-9) "Deoxygenated subunit in T structure of hemoglobin tetramer" - annotation (Placement(transformation(extent={{96,-20},{76,0}}))); + each amountOfSubstance_start=1e-3) "Deoxygenated subunit in T structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{106,-18},{86,2}}))); - Chemical.Components.Substance oxygen_unbound( + Chemical.Boundaries.Substance oxygen_unbound( + useInlet=true, + useOutlet=true, substanceData(DfG=DfG_O2), use_mass_start=false, - amountOfSubstance_start=2e-9) annotation (Placement(transformation(extent={{-2,6},{18,26}}))); + amountOfSubstance_start=2e-9) annotation (Placement(transformation(extent={{2,34},{22,54}}))); Modelica.Blocks.Sources.ContinuousClock clock(offset=1) annotation ( - Placement(transformation(extent={{-40,74},{-20,94}}))); - Chemical.Sources.ExternalIdealGasSubstance oxygen_in_air(usePartialPressureInput=true, substanceData=Chemical.Substances.Oxygen_gas()) + Placement(transformation(extent={{-82,70},{-62,90}}))); + Boundaries.ExternalIdealGasSubstance oxygen_in_air(usePartialPressureInput=true) annotation (Placement(transformation( extent={{-10,-10},{10,10}}, - rotation=270, - origin={8,68}))); - Chemical.Components.GasSolubility partialPressure1(KC=KC) annotation (Placement(transformation(extent={{-10,-10},{10,10}}, origin={8,40}))); + rotation=0, + origin={-36,80}))); + Chemical.Processes.GasSolubility partialPressure1(KC=KC) annotation (Placement(transformation(extent={{-10,-10},{10,10}}, origin={-14,62}))); Real sO2 "Hemoglobin oxygen saturation"; - Components.Substance H2O(substanceData=Chemical.Substances.Water_liquid(), + Boundaries.Substance H2O(substanceData=Chemical.Substances.Water_liquid(), mass_start=1) annotation (Placement(transformation(extent={{32,-92},{52,-72}}))); + Topology.SplitterT2 sT2[4] annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=180, + origin={66,-8}))); + Topology.SplitterN uO2(N=8) annotation (Placement(transformation(extent={{38,34},{58,54}}))); + inner DropOfCommons dropOfCommons(L=1e-8) annotation (Placement(transformation(extent={{58,70},{84,94}}))); equation sO2 = (sum(OxyRHm.x) + sum(OxyTHm.x)) / (sum(DeoxyRHm.x) + sum(DeoxyTHm.x) + sum(OxyRHm.x) + sum(OxyTHm.x)); - connect(OxyTHm.port_a, oxygenation_T.substrates[1]) - annotation (Line( - points={{34,-8},{42,-8}}, - color={107,45,134})); - connect(oxygenation_T.products[1], DeoxyTHm.port_a) - annotation (Line( - points={{62,-9},{70,-10},{76,-10}}, - color={107,45,134})); - connect(clock.y, oxygen_in_air.partialPressure) annotation (Line( - points={{-19,84},{8,84},{8,78}}, + points={{-61,80},{-46,80}}, color={0,0,127})); - connect(OxyRHm.port_a, oxygenation_R.substrates[1]) annotation (Line( - points={{-76,-8},{-68,-8}}, - color={107,45,134})); - connect(DeoxyRHm.port_a, R0_in_R.subunits) annotation (Line( - points={{-28,-10},{-39,-10},{-39,-27.8}}, - color={107,45,134})); - connect(oxygenation_R.products[1], DeoxyRHm.port_a) annotation (Line( - points={{-48,-9},{-38,-9},{-38,-10},{-28,-10}}, - color={107,45,134})); - - connect(T0_in_T.subunits, DeoxyTHm.port_a) annotation (Line( - points={{67,-27.8},{67,-10},{76,-10}}, - color={107,45,134})); - - connect(oxygen_in_air.port_a, partialPressure1.gas_port) annotation (Line( - points={{8,58},{8,50}}, - color={158,66,200})); - connect(partialPressure1.liquid_port, oxygen_unbound.port_a) annotation (Line( - points={{8,30},{8,16},{18,16}}, - color={158,66,200})); - connect(R0_in_R.port_a, quaternaryForm.substrates[1]) annotation (Line( - points={{-26,-48},{-26,-48},{12,-48}}, - color={158,66,200})); - connect(quaternaryForm.products[1], T0_in_T.port_a) annotation (Line( - points={{32,-48},{54,-48}}, - color={158,66,200})); for i in 1:4 loop - connect(oxygenation_T[i].products[2], oxygen_unbound.port_a) annotation (Line( - points={{62,-7},{70,-7},{70,16},{18,16}}, + + connect(oxygenation_T[i].substrates[2], uO2.outlets[i]) annotation (Line( + points={{50,-8.25},{58,-8.25},{58,44}}, color={107,45,134})); - connect(oxygenation_R[i].products[2], oxygen_unbound.port_a) annotation (Line( - points={{-48,-7},{-34,-7},{-34,16},{18,16}}, + connect(oxygenation_R[i].substrates[2], uO2.outlets[i+4]) annotation (Line( + points={{-42,-10.25},{-38,-10.25},{-38,20},{58,20},{58,44}}, color={107,45,134})); + connect(R0_in_R.subunitSolution, DeoxyRHm[i].solution) annotation (Line( points={{-32,-32},{-32,-22},{-12,-22},{-12,-20}}, color={127,127,0})); connect(R0_in_R.subunitSolution, OxyRHm[i].solution) annotation (Line( - points={{-32,-32},{-32,-22},{-92,-22},{-92,-18}}, + points={{-32,-32},{-32,-22},{-80,-22},{-80,-20}}, color={127,127,0})); connect(OxyTHm[i].solution, T0_in_T.subunitSolution) annotation (Line( - points={{18,-18},{18,-22},{60,-22},{60,-32}}, + points={{24,-16},{24,-22},{60,-22},{60,-32}}, color={127,127,0})); connect(DeoxyTHm[i].solution, T0_in_T.subunitSolution) annotation (Line( - points={{92,-20},{92,-22},{60,-22},{60,-32}}, + points={{102,-18},{102,-22},{60,-22},{60,-32}}, color={127,127,0})); end for; connect(R0_in_R.solution, solution.solution) annotation (Line( - points={{-42,-48},{-42,-98.58},{60,-98.58}}, + points={{-42,-48},{0,-48},{0,-98},{60,-98}}, color={127,127,0})); connect(T0_in_T.solution, solution.solution) annotation (Line( - points={{70,-48},{70,-98.58},{60,-98.58}}, + points={{70,-48},{104,-48},{104,-104},{60,-104},{60,-98}}, color={127,127,0})); - connect(oxygen_unbound.solution, solution.solution) annotation (Line(points={{2,6},{2, - -98.58},{60,-98.58}}, color={127,127,0})); + connect(oxygen_unbound.solution, solution.solution) annotation (Line(points={{6,34},{6,-100},{104,-100},{104,-104},{60,-104},{60,-98}}, + color={127,127,0})); connect(solution.solution, H2O.solution) annotation (Line( - points={{60,-98.58},{36,-98.58},{36,-92}}, + points={{60,-98},{36,-98},{36,-92}}, color={127,127,0})); + connect(T0_in_T.outlet, quaternaryForm.substrates[1]) annotation (Line( + points={{54,-48},{32,-48}}, + color={158,66,200}, + thickness=0.5)); + connect(quaternaryForm.products[1], R0_in_R.inlet) annotation (Line( + points={{12,-48},{-26,-48}}, + color={158,66,200}, + thickness=0.5)); + connect(oxygen_in_air.outlet, partialPressure1.inlet) annotation (Line( + points={{-26,80},{-22,80},{-22,72},{-14,72}}, + color={158,66,200}, + thickness=0.5)); + connect(partialPressure1.outlet, oxygen_unbound.inlet) + annotation (Line( + points={{-14,52},{-14,42},{2,42},{2,44}}, + color={158,66,200}, + thickness=0.5)); + connect(R0_in_R.subunits, DeoxyRHm.inlet) + annotation (Line( + points={{-39,-27.8},{-4,-27.8},{-4,-10},{-8,-10}}, + color={158,66,200}, + thickness=0.5)); + connect(oxygenation_R.substrates[1], DeoxyRHm.outlet) annotation (Line( + points={{-42,-9.75},{-36,-9.75},{-36,-10},{-28,-10}}, + color={158,66,200}, + thickness=0.5)); + connect(oxygenation_R.products[1], OxyRHm.inlet) annotation (Line( + points={{-62,-10},{-76,-10}}, + color={158,66,200}, + thickness=0.5)); + connect(oxygenation_T.products[1], OxyTHm.inlet) annotation (Line( + points={{30,-8},{30,-6},{28,-6}}, + color={158,66,200}, + thickness=0.5)); + connect(oxygen_in_air.solution, solution.solution) annotation (Line(points={{-42,70},{-42,46},{-98,46},{-98,-156},{60,-156},{60,-98}}, color={127,127,0})); + connect(DeoxyTHm.outlet, sT2.inlet) annotation (Line( + points={{86,-8},{76,-8}}, + color={158,66,200}, + thickness=0.5)); + connect(sT2.outletA, T0_in_T.subunits) annotation (Line( + points={{66,-18},{66,-22.9},{67,-22.9},{67,-27.8}}, + color={158,66,200}, + thickness=0.5)); + connect(sT2.outletB, oxygenation_T.substrates[1]) annotation (Line( + points={{56,-8},{54,-8},{54,-7.75},{50,-7.75}}, + color={158,66,200}, + thickness=0.5)); + connect(oxygen_unbound.outlet, uO2.inlet) annotation (Line( + points={{22,44},{38,44}}, + color={158,66,200}, + thickness=0.5)); annotation ( experiment(StopTime=15000), Documentation(revisions="
2013-2018
@@ -5046,86 +5081,783 @@ extends Modelica.Icons.ExamplesPackage; Diagram(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100, 100}}))); end HemoglobinCarboxylation; - end Hemoglobin; - - package CheckSubstancesData - model SimpleReaction - "The simple chemical reaction A<->B with equilibrium B/A = 2" - extends Modelica.Icons.Example; - - constant Real K = 2 "Dissociation constant of the reaction"; - constant Modelica.Units.SI.Temperature T_25degC=298.15 - "Temperature"; - constant Real R = Modelica.Constants.R "Gas constant"; + model Allosteric_Hemoglobin2_MWC_ + "Monod,Wyman,Changeux (1965) - The same allosteric hemoglobin model as Allosteric_Hemoglobin_MWC implemented by Speciation blocks" + extends Modelica.Icons.Example; - Chemical.Sensors.DissociationCoefficient dissociationCoefficient(nS=1, nP=1) annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); - Chemical.Sources.PureSubstance A(redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, substanceData(DfG=0)) - annotation (Placement(transformation(extent={{-56,-10},{-36,10}}))); - Chemical.Sources.PureSubstance B(redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, substanceData(DfG=-R*T_25degC*log(K))) - annotation (Placement(transformation(extent={{60,-10},{40,10}}))); - inner Modelica.Fluid.System system(p_ambient=100000, T_ambient=298.15) - annotation (Placement(transformation(extent={{-58,62},{-38,82}}))); - equation - connect(A.port_a, dissociationCoefficient.substrates[1]) - annotation (Line(points={{-36,0},{-10,0}}, color={158,66,200})); - connect(dissociationCoefficient.products[1], B.port_a) - annotation (Line(points={{10,0},{40,0}}, color={158,66,200})); - annotation (Documentation(revisions=" -2015-2018
-Marek Matejak, Charles University, Prague, Czech Republic
-"), - experiment(StopTime=0.001)); - end SimpleReaction; + constant Modelica.Units.SI.AmountOfSubstance THb=0.001 + "Total amount of hemoglobin"; - model SimpleReaction2 - "The simple chemical reaction A+B<->C with equilibrium [C]/([A]*[B]) = 2, where [A] is molar concentration of A in water" - extends Modelica.Icons.Example; + constant Modelica.Units.SI.Temperature T=298.15 "Base Temperature"; + constant Real RT=Modelica.Constants.R*T; - constant Real Kb(unit="kg/mol") = 2 - "Molarity based dissociation constant of the reaction with one more reactant"; + // constant Modelica.SIunits.AmountOfSubstance AmountOfSolutionIn1L = 38.7 + // "Amount of solution used for molarity to mole fraction conversion"; + constant Modelica.Units.SI.Volume OneLiter=0.001; - constant Real Kx(unit="1") = Kb*55.508 - "Mole fraction based dissociation constant of the reaction with one more reactant in the pure water"; + parameter Real L=7.0529*10^6 + "=[T0]/[R0] .. dissociation constant of relaxed <-> tensed change of deoxyhemoglobin tetramer"; + parameter Real c=0.00431555 + "=KR/KT .. ration between oxygen affinities of relaxed vs. tensed subunit"; + parameter Modelica.Units.SI.Concentration KR=0.000671946*(55.508/ + 38.7) "oxygen dissociation on relaxed(R) hemoglobin subunit"; + //*7.875647668393782383419689119171e-5 + //10.500001495896 7.8756465463794e-05 + parameter Modelica.Units.SI.Concentration KT=KR/c + "oxygen dissociation on tensed(T) hemoglobin subunit"; - constant Modelica.Units.SI.Temperature T_25degC=298.15 - "Temperature"; - constant Real R = Modelica.Constants.R "Gas constant"; + parameter Modelica.Units.SI.MoleFraction KRx=KR*OneLiter; + //AmountOfSolutionIn1L; + parameter Modelica.Units.SI.MoleFraction KTx=KT*OneLiter; + //AmountOfSolutionIn1L; + parameter Modelica.Units.SI.ChemicalPotential DfG_O2=-RT*log(0.0013); + parameter Modelica.Units.SI.ChemicalPotential DfG_uR=0; + parameter Modelica.Units.SI.ChemicalPotential DfG_uRO2=DfG_uR + + DfG_O2 + RT*log(KRx); + parameter Modelica.Units.SI.ChemicalPotential DfG_uT=0; + parameter Modelica.Units.SI.ChemicalPotential DfG_uTO2=DfG_uT + + DfG_O2 + RT*log(KTx); + parameter Modelica.Units.SI.ChemicalPotential DfG_tT=0; + parameter Modelica.Units.SI.ChemicalPotential DfG_tR=DfG_tT + RT* + log(L); - Chemical.Sources.PureSubstance A annotation (Placement(transformation(extent={{-34,2},{-14,22}}))); - Chemical.Sensors.DissociationCoefficient reaction(nS=2, nP=1) annotation (Placement(transformation(extent={{4,-8},{24,12}}))); - Chemical.Sources.PureSubstance B annotation (Placement(transformation(extent={{-34,-24},{-14,-4}}))); - Chemical.Sources.PureSubstance C(substanceData(DfG=-R*T_25degC*log(Kx))) annotation (Placement(transformation(extent={{68,-8},{48,12}}))); + parameter Real KC = 1e-6 "Slow down factor"; + //0.000001 + Chemical.Solution solution annotation (Placement(transformation(extent={{-100,-100},{100,42}}))); - equation + Chemical.Components.Reaction quaternaryForm( + nS=1, + nP=1, + KC=KC) annotation (Placement(transformation(extent={{12,-58},{32,-38}}))); + Chemical.Components.Speciation R0_in_R(NumberOfSubunits=4) annotation (Placement(transformation(extent={{-46,-48},{-26,-28}}))); + // AmountOfSubstance_start=4e-11) + Chemical.Components.Speciation T0_in_T(NumberOfSubunits=4) annotation (Placement(transformation(extent={{74,-48},{54,-28}}))); + // AmountOfSubstance_start=totalAmountOfHemoglobin) + Chemical.Components.Substance OxyRHm[4]( + redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, + each substanceData(DfG=DfG_O2 + RT*log(KRx) + DfG_tR/4), + each use_mass_start=false, + each amountOfSubstance_start=5.88e-9) "Oxygenated subunit in R structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{-96,-18},{-76,2}}))); - connect(A.port_a, reaction.substrates[1]) annotation (Line(points={ - {-14,12},{-4,12},{-4,1.5},{4,1.5}}, color={158,66,200})); - connect(B.port_a, reaction.substrates[2]) annotation (Line(points={ - {-14,-14},{-4,-14},{-4,2.5},{4,2.5}}, color={158,66,200})); - connect(reaction.products[1], C.port_a) - annotation (Line(points={{24,2},{48,2}}, color={158,66,200})); - annotation ( Documentation(revisions=" -2015-2018
-Marek Matejak, Charles University, Prague, Czech Republic
-"), - experiment(StopTime=0.001)); - end SimpleReaction2; + Chemical.Components.Reaction oxygenation_R[4]( + each nS=1, + each nP=2, + each KC=KC) annotation (Placement(transformation(extent={{-68,-18},{-48,2}}))); + Chemical.Components.Substance DeoxyRHm[4]( + redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, + each substanceData(DfG=DfG_tR/4), + each use_mass_start=false, + each amountOfSubstance_start=1.58e-7) "Deoxygenated subunit in R structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{-8,-20},{-28,0}}))); - model SimpleReaction2_Get_DfG - "The simple chemical reaction A+B<->C with equilibrium [C]/([A]*[B]) = 2, where [A] is molar concentration of A in water" - extends Modelica.Icons.Example; + Chemical.Components.Substance OxyTHm[4]( + redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, + each substanceData(DfG=DfG_O2 + RT*log(KTx) + DfG_tT/4), + each use_mass_start=false, + each amountOfSubstance_start=1e-4) "Oxygenated subunit in T structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{14,-18},{34,2}}))); - Chemical.Sources.PureSubstance A annotation (Placement(transformation(extent={{-28,42},{-8,62}}))); - Chemical.Sensors.DissociationCoefficient reaction(nP=1, nS=2) annotation (Placement(transformation(extent={{10,32},{30,52}}))); - Chemical.Sources.PureSubstance B annotation (Placement(transformation(extent={{-28,16},{-8,36}}))); + Chemical.Components.Reaction oxygenation_T[4]( + each nS=1, + each nP=2, + each KC=KC) annotation (Placement(transformation(extent={{42,-18},{62,2}}))); + Chemical.Components.Substance DeoxyTHm[4]( + redeclare package stateOfMatter = Chemical.Interfaces.Incompressible, + each substanceData(DfG=DfG_tT/4), + each use_mass_start=false, + each amountOfSubstance_start=THb - 1e-4 - 1.58e-7 - 5.88e-9) "Deoxygenated subunit in T structure of hemoglobin tetramer" + annotation (Placement(transformation(extent={{96,-20},{76,0}}))); - Modelica.Blocks.Math.InverseBlockConstraints inverseBlockConstraints - annotation (Placement(transformation(extent={{-42,-80},{82,80}}))); - Chemical.Sources.ExternalElectroChemicalPotential C(usePotentialInput=true) annotation (Placement(transformation(extent={{60,32},{40,52}}))); - Modelica.Blocks.Sources.Constant K(k=2*55.508) - annotation (Placement(transformation(extent={{-92,-10},{-72,10}}))); - equation + Chemical.Components.Substance oxygen_unbound( + substanceData(DfG=DfG_O2), + use_mass_start=false, + amountOfSubstance_start=2e-9) annotation (Placement(transformation(extent={{-2,6},{18,26}}))); + Modelica.Blocks.Sources.ContinuousClock clock(offset=1) annotation ( + Placement(transformation(extent={{-40,74},{-20,94}}))); + Chemical.Sources.ExternalIdealGasSubstance oxygen_in_air(usePartialPressureInput=true, substanceData=Chemical.Substances.Oxygen_gas()) + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=270, + origin={8,68}))); + Chemical.Components.GasSolubility partialPressure1(KC=KC) annotation (Placement(transformation(extent={{-10,-10},{10,10}}, origin={8,40}))); + + Real sO2 "Hemoglobin oxygen saturation"; + Components.Substance H2O(substanceData=Chemical.Substances.Water_liquid(), + mass_start=1) + annotation (Placement(transformation(extent={{32,-92},{52,-72}}))); + equation + sO2 = (sum(OxyRHm.x) + sum(OxyTHm.x)) / + (sum(DeoxyRHm.x) + sum(DeoxyTHm.x) + sum(OxyRHm.x) + sum(OxyTHm.x)); + + connect(OxyTHm.port_a, oxygenation_T.substrates[1]) + annotation (Line( + points={{34,-8},{42,-8}}, + color={107,45,134})); + connect(oxygenation_T.products[1], DeoxyTHm.port_a) + annotation (Line( + points={{62,-9},{70,-10},{76,-10}}, + color={107,45,134})); + + connect(clock.y, oxygen_in_air.partialPressure) annotation (Line( + points={{-19,84},{8,84},{8,78}}, + color={0,0,127})); + connect(OxyRHm.port_a, oxygenation_R.substrates[1]) annotation (Line( + points={{-76,-8},{-68,-8}}, + color={107,45,134})); + connect(DeoxyRHm.port_a, R0_in_R.subunits) annotation (Line( + points={{-28,-10},{-39,-10},{-39,-27.8}}, + color={107,45,134})); + connect(oxygenation_R.products[1], DeoxyRHm.port_a) annotation (Line( + points={{-48,-9},{-38,-9},{-38,-10},{-28,-10}}, + color={107,45,134})); + + connect(T0_in_T.subunits, DeoxyTHm.port_a) annotation (Line( + points={{67,-27.8},{67,-10},{76,-10}}, + color={107,45,134})); + + connect(oxygen_in_air.port_a, partialPressure1.gas_port) annotation (Line( + points={{8,58},{8,50}}, + color={158,66,200})); + connect(partialPressure1.liquid_port, oxygen_unbound.port_a) annotation (Line( + points={{8,30},{8,16},{18,16}}, + color={158,66,200})); + connect(R0_in_R.port_a, quaternaryForm.substrates[1]) annotation (Line( + points={{-26,-48},{-26,-48},{12,-48}}, + color={158,66,200})); + connect(quaternaryForm.products[1], T0_in_T.port_a) annotation (Line( + points={{32,-48},{54,-48}}, + color={158,66,200})); + + for i in 1:4 loop + connect(oxygenation_T[i].products[2], oxygen_unbound.port_a) annotation (Line( + points={{62,-7},{70,-7},{70,16},{18,16}}, + color={107,45,134})); + connect(oxygenation_R[i].products[2], oxygen_unbound.port_a) annotation (Line( + points={{-48,-7},{-34,-7},{-34,16},{18,16}}, + color={107,45,134})); + connect(R0_in_R.subunitSolution, DeoxyRHm[i].solution) annotation (Line( + points={{-32,-32},{-32,-22},{-12,-22},{-12,-20}}, + color={127,127,0})); + connect(R0_in_R.subunitSolution, OxyRHm[i].solution) annotation (Line( + points={{-32,-32},{-32,-22},{-92,-22},{-92,-18}}, + color={127,127,0})); + connect(OxyTHm[i].solution, T0_in_T.subunitSolution) annotation (Line( + points={{18,-18},{18,-22},{60,-22},{60,-32}}, + color={127,127,0})); + connect(DeoxyTHm[i].solution, T0_in_T.subunitSolution) annotation (Line( + points={{92,-20},{92,-22},{60,-22},{60,-32}}, + color={127,127,0})); + end for; + + connect(R0_in_R.solution, solution.solution) annotation (Line( + points={{-42,-48},{-42,-98.58},{60,-98.58}}, + color={127,127,0})); + connect(T0_in_T.solution, solution.solution) annotation (Line( + points={{70,-48},{70,-98.58},{60,-98.58}}, + color={127,127,0})); + connect(oxygen_unbound.solution, solution.solution) annotation (Line(points={{2,6},{2, + -98.58},{60,-98.58}}, color={127,127,0})); + connect(solution.solution, H2O.solution) annotation (Line( + points={{60,-98.58},{36,-98.58},{36,-92}}, + color={127,127,0})); + + annotation ( experiment(StopTime=15000), + Documentation(revisions=" +2013-2018
+Marek Matejak, Charles University, Prague, Czech Republic
+", + info=" +
To understand the model is necessary to study the principles of MWC allosteric transitions first published by
[1] Monod,Wyman,Changeux (1965). "On the nature of allosteric transitions: a plausible model." Journal of molecular biology 12(1): 88-118.
+
In short it is about binding oxygen to hemoglobin.
Oxgen are driven by its partial pressure using clock source - from very little pressure to pressure of 10kPa.
+(Partial pressure of oxygen in air is the air pressure multiplied by the fraction of the oxygen in air.)
+Hemoglobin was observed (by Perutz) in two structuraly different forms R and T.
+These forms are represented by blocks T0..T4 and R0..R4, where the suffexed index means the number of oxygen bounded to the form.
+
In equilibrated model can be four chemical reactions removed and the results will be the same, but dynamics will change a lot. ;)
If you remove the quaternaryForm1,quaternaryForm2,quaternaryForm3,quaternaryForm4 then the model in equilibrium will be exactly the same as in MWC article.
+
Parameters was fitted to data of Severinghaus article from 1979. (For example at pO2=26mmHg is oxygen saturation sO2 = 48.27 %).
2013-2018
+Marek Matejak, Charles University, Prague, Czech Republic
+", + info=" +
To understand the model is necessary to study the principles of MWC allosteric transitions first published by
[1] Monod,Wyman,Changeux (1965). "On the nature of allosteric transitions: a plausible model." Journal of molecular biology 12(1): 88-118.
+
In short it is about binding oxygen to hemoglobin.
Oxgen are driven by its partial pressure using clock source - from very little pressure to pressure of 10kPa.
+(Partial pressure of oxygen in air is the air pressure multiplied by the fraction of the oxygen in air.)
+Hemoglobin was observed (by Perutz) in two structuraly different forms R and T.
+These forms are represented by blocks T0..T4 and R0..R4, where the suffexed index means the number of oxygen bounded to the form.
+
In equilibrated model can be four chemical reactions removed and the results will be the same, but dynamics will change a lot. ;)
If you remove the quaternaryForm1,quaternaryForm2,quaternaryForm3,quaternaryForm4 then the model in equilibrium will be exactly the same as in MWC article.
+
Parameters was fitted to data of Severinghaus article from 1979. (For example at pO2=26mmHg is oxygen saturation sO2 = 48.27 %).
2013-2018
+Marek Matejak, Charles University, Prague, Czech Republic
+", + info=" +
To understand the model is necessary to study the principles of MWC allosteric transitions first published by
[1] Monod,Wyman,Changeux (1965). "On the nature of allosteric transitions: a plausible model." Journal of molecular biology 12(1): 88-118.
+
In short it is about binding oxygen to hemoglobin.
Oxgen are driven by its partial pressure using clock source - from very little pressure to pressure of 10kPa.
+(Partial pressure of oxygen in air is the air pressure multiplied by the fraction of the oxygen in air.)
+Hemoglobin was observed (by Perutz) in two structuraly different forms R and T.
+These forms are represented by blocks T0..T4 and R0..R4, where the suffexed index means the number of oxygen bounded to the form.
+
In equilibrated model can be four chemical reactions removed and the results will be the same, but dynamics will change a lot. ;)
If you remove the quaternaryForm1,quaternaryForm2,quaternaryForm3,quaternaryForm4 then the model in equilibrium will be exactly the same as in MWC article.
+
Parameters was fitted to data of Severinghaus article from 1979. (For example at pO2=26mmHg is oxygen saturation sO2 = 48.27 %).
2013-2018
+Marek Matejak, Charles University, Prague, Czech Republic
+", + info=" +
To understand the model is necessary to study the principles of MWC allosteric transitions first published by
[1] Monod,Wyman,Changeux (1965). "On the nature of allosteric transitions: a plausible model." Journal of molecular biology 12(1): 88-118.
+
In short it is about binding oxygen to hemoglobin.
Oxgen are driven by its partial pressure using clock source - from very little pressure to pressure of 10kPa.
+(Partial pressure of oxygen in air is the air pressure multiplied by the fraction of the oxygen in air.)
+Hemoglobin was observed (by Perutz) in two structuraly different forms R and T.
+These forms are represented by blocks T0..T4 and R0..R4, where the suffexed index means the number of oxygen bounded to the form.
+
In equilibrated model can be four chemical reactions removed and the results will be the same, but dynamics will change a lot. ;)
If you remove the quaternaryForm1,quaternaryForm2,quaternaryForm3,quaternaryForm4 then the model in equilibrium will be exactly the same as in MWC article.
+
Parameters was fitted to data of Severinghaus article from 1979. (For example at pO2=26mmHg is oxygen saturation sO2 = 48.27 %).
2015-2018
+Marek Matejak, Charles University, Prague, Czech Republic
+"), + experiment(StopTime=0.001)); + end SimpleReaction; + + model SimpleReaction2 + "The simple chemical reaction A+B<->C with equilibrium [C]/([A]*[B]) = 2, where [A] is molar concentration of A in water" + extends Modelica.Icons.Example; + + constant Real Kb(unit="kg/mol") = 2 + "Molarity based dissociation constant of the reaction with one more reactant"; + + constant Real Kx(unit="1") = Kb*55.508 + "Mole fraction based dissociation constant of the reaction with one more reactant in the pure water"; + + constant Modelica.Units.SI.Temperature T_25degC=298.15 + "Temperature"; + constant Real R = Modelica.Constants.R "Gas constant"; + + Chemical.Sources.PureSubstance A annotation (Placement(transformation(extent={{-34,2},{-14,22}}))); + Chemical.Sensors.DissociationCoefficient reaction(nS=2, nP=1) annotation (Placement(transformation(extent={{4,-8},{24,12}}))); + Chemical.Sources.PureSubstance B annotation (Placement(transformation(extent={{-34,-24},{-14,-4}}))); + Chemical.Sources.PureSubstance C(substanceData(DfG=-R*T_25degC*log(Kx))) annotation (Placement(transformation(extent={{68,-8},{48,12}}))); + + equation + + connect(A.port_a, reaction.substrates[1]) annotation (Line(points={ + {-14,12},{-4,12},{-4,1.5},{4,1.5}}, color={158,66,200})); + connect(B.port_a, reaction.substrates[2]) annotation (Line(points={ + {-14,-14},{-4,-14},{-4,2.5},{4,2.5}}, color={158,66,200})); + connect(reaction.products[1], C.port_a) + annotation (Line(points={{24,2},{48,2}}, color={158,66,200})); + annotation ( Documentation(revisions=" +2015-2018
+Marek Matejak, Charles University, Prague, Czech Republic
+"), + experiment(StopTime=0.001)); + end SimpleReaction2; + + model SimpleReaction2_Get_DfG + "The simple chemical reaction A+B<->C with equilibrium [C]/([A]*[B]) = 2, where [A] is molar concentration of A in water" + extends Modelica.Icons.Example; + + Chemical.Sources.PureSubstance A annotation (Placement(transformation(extent={{-28,42},{-8,62}}))); + Chemical.Sensors.DissociationCoefficient reaction(nP=1, nS=2) annotation (Placement(transformation(extent={{10,32},{30,52}}))); + Chemical.Sources.PureSubstance B annotation (Placement(transformation(extent={{-28,16},{-8,36}}))); + + Modelica.Blocks.Math.InverseBlockConstraints inverseBlockConstraints + annotation (Placement(transformation(extent={{-42,-80},{82,80}}))); + Chemical.Sources.ExternalElectroChemicalPotential C(usePotentialInput=true) annotation (Placement(transformation(extent={{60,32},{40,52}}))); + Modelica.Blocks.Sources.Constant K(k=2*55.508) + annotation (Placement(transformation(extent={{-92,-10},{-72,10}}))); + equation connect(reaction.DissociationCoefficient_MoleFractionBased, inverseBlockConstraints.u2) annotation (Line( @@ -6148,6 +6880,10 @@ extends Modelica.Icons.ExamplesPackage; annotation (Placement(transformation(extent={{280,-6},{260,14}}))); inner DropOfCommons dropOfCommons(L=1e-8, assertionLevel=AssertionLevel.warning) annotation (Placement(transformation(extent={{40,60},{60,80}}))); + Sensors.SingleSensorSelect singleSensorSelect( + substanceData(MolarWeight=1), + quantity=Chemical.Sensors.Internal.Types.Quantities.x_molpmol, + outputValue=true) annotation (Placement(transformation(extent={{-26,24},{-6,44}}))); equation connect(A.solution, solution.solution) annotation (Line( points={{-48,-8},{-48,-92},{60,-92},{60,-98}}, @@ -6166,6 +6902,11 @@ extends Modelica.Icons.ExamplesPackage; connect(B1.solution, solution1.solution) annotation (Line(points={{276,-6},{278,-6},{278,-96}}, color={127,127,0})); connect(A1.port_a, reaction1.substrates[1]) annotation (Line(points={{186,4},{208,4}}, color={158,66,200})); connect(reaction1.products[1], B1.port_a) annotation (Line(points={{228,4},{260,4}}, color={158,66,200})); + connect(singleSensorSelect.solution, solution.solution) annotation (Line(points={{-22,24},{18,24},{18,-98},{60,-98}}, color={127,127,0})); + connect(A.outlet, singleSensorSelect.inlet) annotation (Line( + points={{-32,2},{-26,2},{-26,34}}, + color={158,66,200}, + thickness=0.5)); annotation (Documentation(revisions="2015-2018
Marek Matejak, Charles University, Prague, Czech Republic
diff --git a/Chemical/Processes.mo b/Chemical/Processes.mo index 2aec054..5e296a0 100644 --- a/Chemical/Processes.mo +++ b/Chemical/Processes.mo @@ -744,7 +744,7 @@ package Processes * ones(NumberOfSubunits)); h_out = outlet.h; - subunits.h = (outlet.h/NumberOfSubunits)*ones(NumberOfSubunits); + (subunits.h*ones(NumberOfSubunits)) = (outlet.h); //properties from subunits subunitSolution.dH + solution.dH = 0; diff --git a/Chemical/Sensors.mo b/Chemical/Sensors.mo index 710ad5a..172c905 100644 --- a/Chemical/Sensors.mo +++ b/Chemical/Sensors.mo @@ -5,7 +5,6 @@ package Sensors "Chemical sensors" model MolarFlowSensor "Measure of molar flow" extends Modelica.Icons.RoundSensor; - extends Interfaces.OnePort; Modelica.Blocks.Interfaces.RealOutput molarFlowRate(final unit="mol/s") annotation ( Placement(transformation( @@ -16,11 +15,15 @@ package Sensors "Chemical sensors" rotation=270, origin={0,-100}))); + Interfaces.Inlet inlet annotation (Placement(transformation(extent={{-108,-10},{-88,10}}))); + Interfaces.Outlet outlet annotation (Placement(transformation(extent={{92,-10},{112,10}}))); equation - molarFlowRate = port_a.q; - - port_a.u = port_b.u; + molarFlowRate = inlet.n_flow; + connect(inlet, outlet) annotation (Line( + points={{-98,0},{102,0}}, + color={158,66,200}, + thickness=0.5)); annotation ( Documentation(revisions="2009-2015
@@ -47,7 +50,7 @@ package Sensors "Chemical sensors" model MoleFractionSensor "Measure of mole fraction" extends Modelica.Icons.RoundSensor; - extends Interfaces.PartialSubstanceSensor; + extends Internal.PartialSubstanceSensor; Modelica.Blocks.Interfaces.RealOutput moleFraction(final unit="1") "Mole fraction of the substance" @@ -57,11 +60,10 @@ package Sensors "Chemical sensors" rotation=270, origin={0,-60}), iconTransformation( extent={{-20,-20},{20,20}}, - origin={-100,0}, - rotation=180))); + origin={100,0}, + rotation=0))); equation - port_a.q = 0; moleFraction = x; @@ -667,4 +669,417 @@ package Sensors "Chemical sensors" ")); end ActivityCoefficient; + + package Internal + partial model PartialSubstance + + outer Modelica.Fluid.System system "System wide properties"; + + Interfaces.Inlet inlet "The substance" annotation (Placement(transformation(extent={{-110,-10},{-90,10}}), iconTransformation(extent={{-110,-10},{-90,10}}))); + + replaceable package stateOfMatter = Interfaces.Incompressible constrainedby Interfaces.StateOfMatter + "Substance model to translate data into substance properties" + annotation (choices( + choice(redeclare package stateOfMatter = + Chemical.Interfaces.Incompressible "Incompressible"), + choice(redeclare package stateOfMatter = + Chemical.Interfaces.IdealGas "Ideal Gas"), + choice(redeclare package stateOfMatter = + Chemical.Interfaces.IdealGasMSL "Ideal Gas from MSL"), + choice(redeclare package stateOfMatter = + Chemical.Interfaces.IdealGasShomate "Ideal Gas using Shomate model"))); + + parameter stateOfMatter.SubstanceData substanceData + "Definition of the substance" + annotation (choicesAllMatching = true); + + Modelica.Units.SI.MoleFraction x "Mole fraction of the substance"; + + Modelica.Units.SI.ActivityOfSolute a + "Activity of the substance (mole-fraction based)"; + + protected + Modelica.Units.SI.ActivityCoefficient gamma + "Activity coefficient of the substance"; + + Modelica.Units.SI.ChargeNumberOfIon z "Charge number of ion"; + + Modelica.Units.SI.Temperature temperature + "Temperature of the solution"; + + Modelica.Units.SI.Pressure pressure "Pressure of the solution"; + + Modelica.Units.SI.ElectricPotential electricPotential + "Electric potential of the solution"; + + Modelica.Units.SI.MoleFraction moleFractionBasedIonicStrength + "Ionic strength of the solution"; + + //Modelica.Units.SI.MolarMass molarMass "Molar mass of the substance"; + + Modelica.Units.SI.MolarEnthalpy molarEnthalpy + "Molar enthalpy of the substance"; + + Modelica.Units.SI.MolarEntropy molarEntropyPure + "Molar entropy of the pure substance"; + + Modelica.Units.SI.ChemicalPotential u0 + "Chemical potential of the pure substance"; + + Modelica.Units.SI.ChemicalPotential uPure + "Electro-Chemical potential of the pure substance"; + + Modelica.Units.SI.MolarVolume molarVolume + "Molar volume of the substance"; + + Modelica.Units.SI.MolarVolume molarVolumePure + "Molar volume of the pure substance"; + + Modelica.Units.SI.MolarVolume molarVolumeExcess + "Molar volume excess of the substance in solution (typically it is negative as can be negative)"; + + // Modelica.SIunits.MolarHeatCapacity molarHeatCapacityCp + // "Molar heat capacity of the substance at constant pressure"; + + equation + //aliases + gamma = stateOfMatter.activityCoefficient(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + z = stateOfMatter.chargeNumberOfIon(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + // molarMass = stateOfMatter.molarMass(substanceData); + + molarEnthalpy = stateOfMatter.molarEnthalpy(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + molarEntropyPure = stateOfMatter.molarEntropyPure(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + u0 = stateOfMatter.chemicalPotentialPure( + substanceData, + temperature, + pressure, + electricPotential, + moleFractionBasedIonicStrength); + uPure = stateOfMatter.electroChemicalPotentialPure( + substanceData, + temperature, + pressure, + electricPotential, + moleFractionBasedIonicStrength); + molarVolume = stateOfMatter.molarVolume(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + molarVolumePure = stateOfMatter.molarVolumePure(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + molarVolumeExcess = stateOfMatter.molarVolumeExcess(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + // molarHeatCapacityCp = stateOfMatter.molarHeatCapacityCp(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + + //activity of the substance + a = gamma*x; + + //electro-chemical potential of the substance in the solution + inlet.u = stateOfMatter.chemicalPotentialPure( + substanceData, + temperature, + pressure, + electricPotential, + moleFractionBasedIonicStrength) + + Modelica.Constants.R*temperature*log(a) + + z*Modelica.Constants.F*electricPotential; + + inlet.h = molarEnthalpy; + + annotation ( + Documentation(revisions=" +2009-2015
+Marek Matejak, Charles University, Prague, Czech Republic
+")); + end PartialSubstance; + + partial model PartialSubstanceInSolution "Substance properties for components, where the substance is connected with the solution" + + Interfaces.SolutionPort solution "To connect substance with solution, where is pressented" + annotation (Placement(transformation(extent={{-70,-110},{-50,-90}}), iconTransformation(extent={{-70,-110},{-50,-90}}))); + + extends PartialSubstance; + + protected + Modelica.Units.SI.AmountOfSubstance amountOfSolution + "Amount of all solution particles"; + + equation + + //aliases + temperature = solution.T; + pressure = solution.p; + electricPotential = solution.v; + amountOfSolution = solution.n; + moleFractionBasedIonicStrength = solution.I; + + end PartialSubstanceInSolution; + + model PartialSubstanceSensor "Base class for sensor based on substance and solution properties" + extends PartialSubstanceInSolution; + + equation + //solution is not changed by the sensor components + solution.dH = 0; + solution.i = 0; + solution.dV = 0; + solution.Gj = 0; + solution.nj = 0; + solution.mj = 0; + solution.Qj = 0; + solution.Ij = 0; + solution.Vj = 0; + + end PartialSubstanceSensor; + + package Types + type Quantities = enumeration( + c_molpm3 "Concentration (mmol/L)", + X_kgpkg "Mass fraction (kg/kg)", + b_molpkg "Molality (mol/kg)", + x_molpmol "Mole fraction (mol/mol)", + p_Pa "Partial pressure (Pa)", + p_mmHg "Partial pressure (mmHg)", + p_bar "Partial pressure (bar)", + u_Jpmol "Steadystate electro-chemical potential (J/mol)", + u_kJpmol "Steadystate electro-chemical potential (kJ/mol)", + r_Jpmol "Inertial electro-chemical potential (J/mol)", + r_kJpmol "Inertial electro-chemical potential (kJ/mol)", + u_total_Jpmol "Total electro-chemical potential (J/mol)", + u_total_kJpmol "Total electro-chemical potential (kJ/mol)", + h_Jpmol "Specific enthalpy (J/mol)", + s_JpmolK "Specific enthropy (J/(mol.K))"); + type InitializationModelSensor = enumeration( + steadyState + "Steady state initialization (derivatives of states are zero)", + state + "Initialization with initial output state") "Initialization modes for sensor lowpass"; + end Types; + + function getQuantity "Computes selected quantity from state" + extends Modelica.Icons.Function; + + replaceable package stateOfMatter = Interfaces.Incompressible constrainedby Interfaces.StateOfMatter + "Substance model to translate data into substance properties" + annotation (choicesAllMatching=true, + Documentation(info=" +Medium Model for the function. Make sure it implements the needed functions.
+ ")); + + input Modelica.Units.SI.ChemicalPotential u "Electro-chemical potential"; + input Modelica.Units.SI.MolarEnthalpy h "Molar enthalpy"; + input Modelica.Units.SI.Pressure r "Inertial electro-chemical potential"; + input Types.Quantities quantity "What to measure?"; + input stateOfMatter.SubstanceData substanceData "Data record of substance"; + input Modelica.Units.SI.Temperature temperature=298.15 "Temperature"; + input Modelica.Units.SI.Pressure pressure=100000 "Pressure"; + input Modelica.Units.SI.ElectricPotential electricPotential=0 + "Electric potential of the substance"; + input Modelica.Units.SI.MoleFraction moleFractionBasedIonicStrength=0 + "Ionic strengh (mole fraction based)"; + input Modelica.Units.SI.Mass solutionMass; + input Modelica.Units.SI.AmountOfSubstance solutionAmount; + input Modelica.Units.SI.Volume solutionVolume; + + output Real value; + + /* + c_molpm3 "Concentration (mmol/L)", + X_kgpkg "Mass fraction (kg/kg)", + b_molpkg "Molality (mol/kg)", + x_molpmol "Mole fraction (mol/mol)", + p_Pa "Partial pressure (Pa)", + p_mmHg "Partial pressure (mmHg)", + p_bar "Partial pressure (bar)", + u_Jpmol "Steadystate electro-chemical potential (J/mol)", + u_kJpmol "Steadystate electro-chemical potential (kJ/mol)", + r_Jpmol "Inertial electro-chemical potential (J/mol)", + r_kJpmol "Inertial electro-chemical potential (kJ/mol)", + u_total_Jpmol "Total electro-chemical potential (J/mol)", + u_total_kJpmol "Total electro-chemical potential (kJ/mol)", + h_Jpmol "Specific enthalpy (J/mol)", + s_JpmolK "Specific enthropy (J/(mol.K))" + */ + + protected + Modelica.Units.SI.ChargeNumberOfIon z; + Modelica.Units.SI.ChemicalPotential u0; + Modelica.Units.SI.MoleFraction a,x; + Modelica.Units.SI.ActivityCoefficient gamma + "Activity coefficient of the substance"; + + algorithm + z := stateOfMatter.chargeNumberOfIon( substanceData, + temperature, + pressure, + electricPotential, + moleFractionBasedIonicStrength); + gamma := stateOfMatter.activityCoefficient(substanceData,temperature,pressure,electricPotential,moleFractionBasedIonicStrength); + + + u0 := stateOfMatter.chemicalPotentialPure( + substanceData, + temperature, + pressure, + electricPotential, + moleFractionBasedIonicStrength) + + z*Modelica.Constants.F*electricPotential; + + a := exp((u - u0)/(Modelica.Constants.R*temperature)); + x := a/gamma; + + if quantity == Types.Quantities.c_molpm3 then + value := (x * solutionAmount)/solutionVolume; + elseif quantity == Types.Quantities.X_kgpkg then + value := ((x * solutionAmount)/solutionMass)/stateOfMatter.specificAmountOfParticles(substanceData, + temperature, + pressure, + electricPotential, + moleFractionBasedIonicStrength); + elseif quantity == Types.Quantities.b_molpkg then + value := (x * solutionAmount)/solutionMass; + elseif quantity == Types.Quantities.x_molpmol then + value := x; + elseif quantity == Types.Quantities.p_Pa then + value := x*pressure; + elseif quantity == Types.Quantities.p_mmHg then + value := x*pressure * (760/101325); + elseif quantity == Types.Quantities.p_bar then + value := Modelica.Units.Conversions.to_bar(x*pressure); + elseif quantity == Types.Quantities.u_Jpmol then + value := u; + elseif quantity == Types.Quantities.u_kJpmol then + value := u/1000; + elseif quantity == Types.Quantities.h_Jpmol then + value := h; + elseif quantity == Types.Quantities.s_JpmolK then + value := (h-u)/temperature; + else + value :=0; + end if; + + annotation (Documentation(info=" +Helper function to get a quantity from an Thermofluid state.
+")); + end getQuantity; + + function getUnit "Returns unit of input quantity" + extends Modelica.Icons.Function; + + input Types.Quantities quantity; + output String unit; + + algorithm + + if quantity == Types.Quantities.c_molpm3 then + unit := "mol/m3"; + elseif quantity == Types.Quantities.X_kgpkg then + unit := "kg/kg"; + elseif quantity == Types.Quantities.b_molpkg then + unit := "mol/kg"; + elseif quantity == Types.Quantities.x_molpmol then + unit := "mol/mol"; + elseif quantity == Types.Quantities.p_Pa then + unit := "Pa"; + elseif quantity == Types.Quantities.p_mmHg then + unit := "mmHg"; + elseif quantity == Types.Quantities.p_bar then + unit := "bar"; + elseif quantity == Types.Quantities.u_Jpmol then + unit := "J/mol"; + elseif quantity == Types.Quantities.u_kJpmol then + unit := "kJ/mol"; + elseif quantity == Types.Quantities.h_Jpmol then + unit :="J/mol"; + elseif quantity == Types.Quantities.s_JpmolK then + unit := "J/(mol.K)"; + else + unit :=""; + end if; + + annotation (Documentation(info=" +Helper function to get the unit for a quantity.
+")); + end getUnit; + end Internal; + + model SingleSensorSelect "Sensor with selectable measured quantity" + import Chemical.Sensors.Internal.Types.Quantities; + import InitMode = Chemical.Sensors.Internal.Types.InitializationModelSensor; + extends Internal.PartialSubstanceSensor; + + parameter Integer digits(min=0) = 1 "Number of displayed digits"; + parameter Quantities quantity "Quantity the sensor measures"; + parameter Boolean outputValue = false "Enable sensor-value output" + annotation(Dialog(group="Output Value")); + parameter Boolean filter_output = false "Filter sensor-value to break algebraic loops" + annotation(Dialog(group="Output Value", enable=outputValue)); + parameter InitMode init=InitMode.steadyState "Initialization mode for sensor lowpass" + annotation(Dialog(tab="Initialization", enable=filter_output)); + parameter Real value_0(unit=Internal.getUnit(quantity)) = 0 "Initial output state of sensor" + annotation(Dialog(tab="Initialization", enable=filter_output and init == InitMode.state)); + parameter Modelica.Units.SI.Time TC=0.1 "PT1 time constant" annotation (Dialog(tab="Advanced", enable=outputValue and filter_output)); + + Modelica.Blocks.Interfaces.RealOutput value_out(unit=Internal.getUnit(quantity)) = value if outputValue "Measured value [variable]" + annotation (Placement(transformation(extent={{80,-20},{120,20}}))); + + output Real value(unit=Internal.getUnit(quantity)) "Computed value of the selected quantity"; + + protected + outer DropOfCommons dropOfCommons; + + Real direct_value(unit=Internal.getUnit(quantity)); + + function getQuantity = Internal.getQuantity (redeclare package stateOfMatter = stateOfMatter) + "Quantity compute function" + annotation (Documentation(info=" +This function computes the selected quantity from state. r and rho_min are neddet for the quantities r/p_total and v respectively.
+ ")); + + initial equation + if filter_output and init==InitMode.steadyState then + value= direct_value; + elseif filter_output then + value = value_0; + end if; + + equation + + direct_value = getQuantity(inlet.u, inlet.h, inlet.r, quantity, substanceData, temperature, pressure, electricPotential, moleFractionBasedIonicStrength, + solution.m, solution.n, solution.V); + + + if filter_output then + der(value) * TC = direct_value-value; + else + value = direct_value; + end if; + + annotation (Icon(coordinateSystem(preserveAspectRatio=false), graphics={ + Rectangle( + extent={{-54,24},{66,-36}}, + lineColor={0,0,0}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), + Line( + points={{-100,0},{0,0}}, + color={28,108,200}, + thickness=0.5), + Rectangle( + extent={{-60,30},{60,-30}}, + lineColor={0,0,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + extent={{-60,30},{60,-30}}, + textColor={28,108,200}, + textString=DynamicSelect("value", String( + value, + format="1."+String(digits)+"f"))), + Text( + extent={{0,25},{60,75}}, + textColor={175,175,175}, + textString="%quantity")}), + Diagram(coordinateSystem(preserveAspectRatio=false)), + Documentation(info=" +Sensor for measuring a selectable quantity.
+This sensor can be connected to a fluid stream without a junction.
+")); + end SingleSensorSelect; end Sensors;