FCSys.Phases

Mixtures of species

Information

The graphite, ionomer, and liquid phases can only be used with a compressible phase (gas).

Extends from Modelica.Icons.Package (Icon for standard packages).

Package Content

NameDescription
FCSys.Phases.Gas Gas Gas phase
FCSys.Phases.Graphite Graphite Graphite phase
FCSys.Phases.Ionomer Ionomer Ionomer phase
FCSys.Phases.Liquid Liquid Liquid phase
PartialPhase Base model for a phase
FCSys.Phases.ExchangeParams ExchangeParams Independence factors for an exchange process

FCSys.Phases.Gas FCSys.Phases.Gas

Gas phase FCSys.Phases.Gas

Information

It is usually appropriate to assume that species exist at the same temperature within a phase. The time constants for thermal exchange (τQE) are usually much shorter than the time span of interest due to the very small coupling resistances. If this is the case, set common.k_Q to zero. This will reduce the index of the problem, so it may be necessary to eliminate some initial conditions.

In bulk flow, it is usually appropriate to assume that species travel with the same velocity within a phase. If this is the case, set the entries of common.k_Phi to zero. This will reduce the index of the problem, so it may be necessary to eliminate some initial conditions.

Please see the documentation of the PartialPhase model.

Extends from Icons.Phases.Gas (Icon for a gas phase), PartialPhase (Base model for a phase).

Parameters

TypeNameDefaultDescription
Integern_speccountTrue({inclH2,inclH2O,in…Number of species
Integern_trans1Number of transport axes
VolumeVdalton.VVolume of the phase [L3]
Geometry
NumberAbsolutek[Axis]{1,1,1}Length factors for transport [1]
Independence factors
NumberAbsolutek_inter_Phi[n_inter, n_trans]ones(n_inter, n_trans)For translational exchange with other phases [1]
NumberAbsolutek_inter_Q[n_inter]ones(n_inter)For thermal exchange with other phases [1]
ExchangeParamscommon Among species in the phase
ExchangeParamsH2_H2O Between H2 and H2O
ExchangeParamsH2O_N2 Between H2O and N2
ExchangeParamsH2O_O2 Between H2O and O2
ExchangeParamsN2_O2 Between N2 and O2
Species
BooleaninclH2falseInclude H2
FixedH2redeclare FCSys.Species.H2.G…H2 model
BooleaninclH2OfalseInclude H2O
FixedH2Oredeclare FCSys.Species.H2O….H2O model
BooleaninclN2falseInclude N2
FixedN2redeclare FCSys.Species.N2.G…N2 model
BooleaninclO2falseInclude O2
FixedO2redeclare FCSys.Species.O2.G…O2 model

Connectors

TypeNameDescription
BoundaryBusxNegativeNegative boundary along the x axis
BoundaryBusyNegativeNegative boundary along the y axis
BoundaryBuszNegativeNegative boundary along the z axis
BoundaryBusxPositivePositive boundary along the x axis
BoundaryBusyPositivePositive boundary along the y axis
BoundaryBuszPositivePositive boundary along the z axis
DaltondaltonConnector for additivity of pressure
Interinter[n_inter]Connector to exchange momentum and energy with other phases
ChemicalchemH2[H2.n_chem]Chemical connector for H2
ChemicalchemH2O[H2O.n_chem]Chemical connector for H2O
ChemicalchemO2[O2.n_chem]Chemical connector for O2

Modelica definition

model Gas "Gas phase"
  import Modelica.Constants.inf;
  import Modelica.Math.BooleanVectors.countTrue;
  import FCSys.Characteristics.MobilityFactors;

  extends Icons.Phases.Gas;
  extends PartialPhase(final n_spec=countTrue({inclH2,inclH2O,inclN2,inclO2}), 
      final V=dalton.V);

  // Conditionally include species.
  parameter Boolean inclH2=false "Include H2";
  replaceable FCSys.Species.H2.Gas.Fixed H2(
    final n_trans,
    final n_inter,
    final kL,
    final n_chem,
    final k_intra_Phi,
    final k_intra_Q) if inclH2 constrainedby FCSys.Species.Fluid(
    n_trans=n_trans,
    n_intra=2,
    n_inter=n_inter,
    kL=kL,
    k_intra_Phi={common.k_Phi[cartTrans],H2_H2O.k_Phi[cartTrans]},
    k_intra_Q={common.k_Q,H2_H2O.k_Q}) "H2 model";

  parameter Boolean inclH2O=false "Include H2O";

  replaceable FCSys.Species.H2O.Gas.Fixed H2O(
    final n_trans,
    final n_inter,
    final kL,
    final n_chem,
    final k_intra_Phi,
    final k_intra_Q) if inclH2O constrainedby FCSys.Species.Fluid(
    n_trans=n_trans,
    n_intra=4,
    n_inter=n_inter,
    kL=kL,
    k_intra_Phi={common.k_Phi[cartTrans],H2_H2O.k_Phi[cartTrans],H2O_N2.k_Phi[
        cartTrans],H2O_O2.k_Phi[cartTrans]},
    k_intra_Q={common.k_Q,H2_H2O.k_Q,H2O_N2.k_Q,H2O_O2.k_Q}) "H2O model";

  parameter Boolean inclN2=false "Include N2";

  replaceable FCSys.Species.N2.Gas.Fixed N2(
    final n_trans,
    final n_inter,
    final kL,
    final n_chem,
    final k_intra_Phi,
    final k_intra_Q) if inclN2 constrainedby FCSys.Species.Fluid(
    n_trans=n_trans,
    n_intra=3,
    n_inter=n_inter,
    kL=kL,
    k_intra_Phi={common.k_Phi[cartTrans],H2O_N2.k_Phi[cartTrans],N2_O2.k_Phi[
        cartTrans]},
    k_intra_Q={common.k_Q,H2O_N2.k_Q,N2_O2.k_Q}) "N2 model";

  parameter Boolean inclO2=false "Include O2";

  replaceable FCSys.Species.O2.Gas.Fixed O2(
    final n_trans,
    final n_inter,
    final kL,
    final n_chem,
    final k_intra_Phi,
    final k_intra_Q) if inclO2 constrainedby FCSys.Species.Fluid(
    n_trans=n_trans,
    n_intra=3,
    n_inter=n_inter,
    kL=kL,
    k_intra_Phi={common.k_Phi[cartTrans],H2O_O2.k_Phi[cartTrans],N2_O2.k_Phi[
        cartTrans]},
    k_intra_Q={common.k_Q,H2O_O2.k_Q,N2_O2.k_Q}) "O2 model";

  // Independence factors
  ExchangeParams common(k_Phi={inf,inf,inf}, k_Q=0) if n_spec > 0 
    "Among species in the phase";
  ExchangeParams H2_H2O(k_Phi=fill(MobilityFactors.k_H2_H2O(p_A=environment.p_dry,
        p_B=environment.p_H2O), 3), k_Q=inf) if inclH2 or inclH2O 
    "Between H2 and H2O";
  ExchangeParams H2O_N2(k_Phi=fill(MobilityFactors.k_H2O_N2(p_A=environment.p_H2O,
        p_B=environment.p_dry - environment.p_O2), 3), k_Q=inf) if inclH2O or 
    inclN2 "Between H2O and N2";
  ExchangeParams H2O_O2(k_Phi=fill(MobilityFactors.k_H2O_O2(p_A=environment.p_H2O,
        p_B=environment.p_O2), 3), k_Q=inf) if inclH2O or inclO2 
    "Between H2O and O2";
  ExchangeParams N2_O2(k_Phi=fill(MobilityFactors.k_N2_O2(p_A=environment.p_dry -
        environment.p_O2, p_B=environment.p_O2), 3), k_Q=inf) if inclN2 or 
    inclO2 "Between N2 and O2";

  Connectors.BoundaryBus xNegative if inclTrans[Axis.x] 
    "Negative boundary along the x axis";
  Connectors.BoundaryBus yNegative if inclTrans[Axis.y] 
    "Negative boundary along the y axis";
  Connectors.BoundaryBus zNegative if inclTrans[Axis.z] 
    "Negative boundary along the z axis";
  Connectors.BoundaryBus xPositive if inclTrans[Axis.x] 
    "Positive boundary along the x axis";
  Connectors.BoundaryBus yPositive if inclTrans[Axis.y] 
    "Positive boundary along the y axis";
  Connectors.BoundaryBus zPositive if inclTrans[Axis.z] 
    "Positive boundary along the z axis";
  Connectors.Dalton dalton if n_spec > 0 "Connector for additivity of pressure";
  Connectors.Inter inter[n_inter](each final n_trans=n_trans) if n_spec > 0 
    "Connector to exchange momentum and energy with other phases";

  // Auxiliary variables (for analysis)
  output Q.PressureAbsolute p(stateSelect=StateSelect.never) = dalton.p if 
    n_spec > 0 and environment.analysis "Total thermodynamic pressure";

  Connectors.Chemical chemH2[H2.n_chem](each final n_trans=n_trans) if inclH2 
    "Chemical connector for H2";
  Connectors.Chemical chemH2O[H2O.n_chem](each final n_trans=n_trans) if 
    inclH2O "Chemical connector for H2O";
  Connectors.Chemical chemO2[O2.n_chem](each final n_trans=n_trans) if inclO2 
    "Chemical connector for O2";

protected 
  Connectors.InertNode exchCommon 
    "Connector for exchange among species in the phase";
  Connectors.InertNode exchH2_H2O "Connector for exchange between H2 and H2O";
  Connectors.InertNode exchH2O_N2 "Connector for exchange between H2O and N2";
  Connectors.InertNode exchH2O_O2 "Connector for exchange between H2O and O2";
  Connectors.InertNode exchN2_O2 "Connector for exchange between N2 and O2";

equation 
  // Chemical exchange
  connect(O2.chemical, chemO2);
  connect(H2.chemical, chemH2);
  connect(H2O.chemical, chemH2O);

  // Inert exchange
  connect(H2.inter, inter);
  connect(H2O.inter, inter);
  connect(N2.inter, inter);
  connect(O2.inter, inter);
  connect(H2.intra[1], exchCommon.node);
  connect(H2O.intra[1], exchCommon.node);
  connect(N2.intra[1], exchCommon.node);
  connect(O2.intra[1], exchCommon.node);
  connect(H2.intra[2], exchH2_H2O.node);
  connect(H2O.intra[2], exchH2_H2O.node);
  connect(H2O.intra[3], exchH2O_N2.node);
  connect(N2.intra[2], exchH2O_N2.node);
  connect(H2O.intra[4], exchH2O_O2.node);
  connect(O2.intra[2], exchH2O_O2.node);
  connect(N2.intra[3], exchN2_O2.node);
  connect(O2.intra[3], exchN2_O2.node);
  // Mixing
  connect(H2.dalton, dalton);
  connect(H2O.dalton, dalton);
  connect(N2.dalton, dalton);
  connect(O2.dalton, dalton);

  // Transport
  // ---------
  // H2
  connect(H2.boundaries[transCart[Axis.x], Side.n], xNegative.H2);

  connect(H2.boundaries[transCart[Axis.x], Side.p], xPositive.H2);

  connect(H2.boundaries[transCart[Axis.y], Side.n], yNegative.H2);

  connect(H2.boundaries[transCart[Axis.y], Side.p], yPositive.H2);

  connect(H2.boundaries[transCart[Axis.z], Side.n], zNegative.H2);
  connect(H2.boundaries[transCart[Axis.z], Side.p], zPositive.H2);
  // H2O
  connect(H2O.boundaries[transCart[Axis.x], Side.n], xNegative.H2O);

  connect(H2O.boundaries[transCart[Axis.x], Side.p], xPositive.H2O);

  connect(H2O.boundaries[transCart[Axis.y], Side.n], yNegative.H2O);

  connect(H2O.boundaries[transCart[Axis.y], Side.p], yPositive.H2O);

  connect(H2O.boundaries[transCart[Axis.z], Side.n], zNegative.H2O);
  connect(H2O.boundaries[transCart[Axis.z], Side.p], zPositive.H2O);
  // N2
  connect(N2.boundaries[transCart[Axis.x], Side.n], xNegative.N2);

  connect(N2.boundaries[transCart[Axis.x], Side.p], xPositive.N2);

  connect(N2.boundaries[transCart[Axis.y], Side.n], yNegative.N2);

  connect(N2.boundaries[transCart[Axis.y], Side.p], yPositive.N2);
  connect(N2.boundaries[transCart[Axis.z], Side.n], zNegative.N2);
  connect(N2.boundaries[transCart[Axis.z], Side.p], zPositive.N2);
  // O2
  connect(O2.boundaries[transCart[Axis.x], Side.n], xNegative.O2);
  connect(O2.boundaries[transCart[Axis.x], Side.p], xPositive.O2);
  connect(O2.boundaries[transCart[Axis.y], Side.n], yNegative.O2);
  connect(O2.boundaries[transCart[Axis.y], Side.p], yPositive.O2);
  connect(O2.boundaries[transCart[Axis.z], Side.n], zNegative.O2);
  connect(O2.boundaries[transCart[Axis.z], Side.p], zPositive.O2);
end Gas;

FCSys.Phases.Graphite FCSys.Phases.Graphite

Graphite phase FCSys.Phases.Graphite

Information

From a physical standpoint, the electrolytic double layer is probably best considered its own phase, but it is modeled as a part of the graphite phase in order to reduce the number of connections. It is assumed to store no material, translational momentum, or thermal energy. It only stores electrical energy due to a charge difference.

C+ and e- are assumed to have the same temperature. C+ should be used to initialize the temperature.

See Species.'e-'.Graphite.Fixed for assumptions. For more information, please see the PartialPhase model.

Extends from Icons.Phases.Solid (Icon for a solid phase), PartialPhase (Base model for a phase).

Parameters

TypeNameDefaultDescription
Integern_speccountTrue({'inclC+','incle-'})Number of species
Integern_trans1Number of transport axes
VolumeV-amagat.VVolume of the phase [L3]
Geometry
NumberAbsolutek[Axis]{1,1,1}Length factors for transport [1]
Independence factors
NumberAbsolutek_inter_Phi[n_inter, n_trans]ones(n_inter, n_trans)For translational exchange with other phases [1]
NumberAbsolutek_inter_Q[n_inter]ones(n_inter)For thermal exchange with other phases [1]
Species
Boolean'inclC+'falseInclude C+
Fixed'C+'redeclare FCSys.Species.'C+'…C+ model
Boolean'incle-'falseInclude e-
Fixed'e-'redeclare FCSys.Species.'e-'…e- model
Assumptions
Boolean'incle-Transfer'falseInclude electron transfer
BooleaninclDLfalseInclude the double-layer capacitance

Connectors

TypeNameDescription
BoundaryBusxNegativeNegative boundary along the x axis
BoundaryBusyNegativeNegative boundary along the y axis
BoundaryBuszNegativeNegative boundary along the z axis
BoundaryBusxPositivePositive boundary along the x axis
BoundaryBusyPositivePositive boundary along the y axis
BoundaryBuszPositivePositive boundary along the z axis
Interinter[n_inter]Connector to exchange momentum and energy with other phases
AmagatamagatConnector for additivity of volume
Chemical'cheme-'[1]Chemical connector for e-

Modelica definition

model Graphite "Graphite phase"
  import assert = FCSys.Utilities.assertEval;
  import Modelica.Math.BooleanVectors.countTrue;

  extends Icons.Phases.Solid;
  extends PartialPhase(final n_spec=countTrue({'inclC+','incle-'}),final V=-
        amagat.V);

  // Conditionally include species.
  parameter Boolean 'inclC+'=false "Include C+";

  replaceable FCSys.Species.'C+'.Graphite.Fixed 'C+'(
    final n_trans,
    final n_inter,
    final kL) if 'inclC+' constrainedby FCSys.Species.Solid(
    n_trans=n_trans,
    n_intra=1,
    n_inter=n_inter,
    kL=kL,
    final k_intra_Phi={ones(n_trans)},
    final k_intra_Q={0}) "C+ model";

  parameter Boolean 'incle-'=false "Include e-";
  replaceable FCSys.Species.'e-'.Graphite.Fixed 'e-'(final n_trans, final 
      n_inter) if 'incle-' constrainedby FCSys.Species.Fluid(
    n_trans=n_trans,
    n_intra=1,
    n_inter=0,
    final k_intra_Phi={ones(n_trans)},
    final k_intra_Q={0}) "e- model";

  parameter Boolean 'incle-Transfer'=false "Include electron transfer";

  parameter Boolean inclDL=false "Include the double-layer capacitance";

  Chemistry.Electrochemistry.ElectronTransfer 'e-Transfer'(redeclare constant Integer
      n_trans=1) if 'incle-' and 'incle-Transfer' "Electron transfer";
  Chemistry.Electrochemistry.DoubleLayer doubleLayer(redeclare constant Integer
      n_trans=1) if 'incle-' and 'incle-Transfer' and inclDL 
    "Electrolytic double layer";
  // Note:  n_trans must be constant in Dymola 2014 to prevent errors such as
  // "Failed to expand the variable
  // subregion.graphite.'e-Transfer'.negative.phi".  The setting of n_trans=1
  // must be manually changed at instantiation if additional transport axes
  //  are enabled.

  Connectors.BoundaryBus xNegative if inclTrans[Axis.x] 
    "Negative boundary along the x axis";
  Connectors.BoundaryBus yNegative if inclTrans[Axis.y] 
    "Negative boundary along the y axis";
  Connectors.BoundaryBus zNegative if inclTrans[Axis.z] 
    "Negative boundary along the z axis";
  Connectors.BoundaryBus xPositive if inclTrans[Axis.x] 
    "Positive boundary along the x axis";
  Connectors.BoundaryBus yPositive if inclTrans[Axis.y] 
    "Positive boundary along the y axis";
  Connectors.BoundaryBus zPositive if inclTrans[Axis.z] 
    "Positive boundary along the z axis";
  Connectors.Inter inter[n_inter](each final n_trans=n_trans) if n_spec > 0 
    "Connector to exchange momentum and energy with other phases";

  Connectors.Amagat amagat if n_spec > 0 "Connector for additivity of volume";

  Connectors.Chemical 'cheme-'[1](each final n_trans=n_trans) if 'incle-' and 
    'incle-Transfer' "Chemical connector for e-";

protected 
  Conditions.Adapters.AmagatDalton amagatDalton if n_spec > 0 
    "Adapter between additivity of volume and additivity of pressure";
  Connectors.InertNode exchCommon 
    "Connector for exchange among all species in the phase";

equation 
  // Chemical exchange
  connect('e-Transfer'.negative, doubleLayer.negative);
  connect('e-Transfer'.positive, doubleLayer.positive);
  connect('e-Transfer'.negative, 'e-'.chemical[1]);
  connect('e-Transfer'.positive, 'cheme-'[1]);

  // Inert exchange
  connect('C+'.inter, inter);
  connect('C+'.intra[1], exchCommon.node);
  connect('e-'.intra[1], exchCommon.node);
  connect('e-Transfer'.inert, 'C+'.intra[1]);
  connect(doubleLayer.inert, 'e-Transfer'.inert);

  // Mixing
  connect(amagatDalton.amagat, amagat);
  connect(amagatDalton.dalton, 'C+'.dalton);
  connect(amagatDalton.dalton, 'e-'.dalton);
  connect(doubleLayer.amagat, amagat);

  // Transport
  // ---------
  // C+
  connect('C+'.boundaries[transCart[Axis.x], Side.n], xNegative.'C+');
  connect('C+'.boundaries[transCart[Axis.x], Side.p], xPositive.'C+');

  connect('C+'.boundaries[transCart[Axis.y], Side.n], yNegative.'C+');

  connect('C+'.boundaries[transCart[Axis.y], Side.p], yPositive.'C+');

  connect('C+'.boundaries[transCart[Axis.z], Side.n], zNegative.'C+');
  connect('C+'.boundaries[transCart[Axis.z], Side.p], zPositive.'C+');

  // e-
  connect('e-'.boundaries[transCart[Axis.x], Side.n], xNegative.'e-');

  connect('e-'.boundaries[transCart[Axis.x], Side.p], xPositive.'e-');

  connect('e-'.boundaries[transCart[Axis.y], Side.n], yNegative.'e-');

  connect('e-'.boundaries[transCart[Axis.y], Side.p], yPositive.'e-');

  connect('e-'.boundaries[transCart[Axis.z], Side.n], zNegative.'e-');
  connect('e-'.boundaries[transCart[Axis.z], Side.p], zPositive.'e-');

end Graphite;

FCSys.Phases.Ionomer FCSys.Phases.Ionomer

Ionomer phase FCSys.Phases.Ionomer

Information

Assumptions:

  1. The water in the ionomer does not directly participate in the reaction (only the water vapor does).
  2. See Species.'H+'.Ionomer.Fixed for additional assumptions. For more information, please see the PartialPhase model.

    Extends from Icons.Phases.Solid (Icon for a solid phase), PartialPhase (Base model for a phase).

    Parameters

    TypeNameDefaultDescription
    Integern_speccountTrue({'inclSO3-','inclH…Number of species
    Integern_trans1Number of transport axes
    VolumeV-amagat.VVolume of the phase [L3]
    Geometry
    NumberAbsolutek[Axis]{1,1,1}Length factors for transport [1]
    Independence factors
    NumberAbsolutek_inter_Phi[n_inter, n_trans]ones(n_inter, n_trans)For translational exchange with other phases [1]
    NumberAbsolutek_inter_Q[n_inter]ones(n_inter)For thermal exchange with other phases [1]
    Species
    Boolean'inclSO3-'falseInclude C19HF37O5S- (abbreviated as SO3-)
    Fixed'SO3-'redeclare FCSys.Species.'SO3…SO3- model
    Boolean'inclH+'falseInclude H+
    Fixed'H+'redeclare FCSys.Species.'H+'…H+ model
    BooleaninclH2OfalseInclude H2O
    FixedH2Oredeclare FCSys.Species.H2O….H2O model
    Exchange (click to edit)
    ExchangeParamscommon Among all species in the phase
    ExchangeParams'H+_SO3-' Between H+ and SO3-)
    ExchangeParams'H+_H2O' Between H+ and H2O
    ExchangeParams'H2O_SO3-' Between H2O and SO3-

    Connectors

    TypeNameDescription
    BoundaryBusxNegativeNegative boundary along the x axis
    BoundaryBusyNegativeNegative boundary along the y axis
    BoundaryBuszNegativeNegative boundary along the z axis
    BoundaryBusxPositivePositive boundary along the x axis
    BoundaryBusyPositivePositive boundary along the y axis
    BoundaryBuszPositivePositive boundary along the z axis
    AmagatamagatConnector for additivity of volume
    Interinter[n_inter]Connector to exchange momentum and energy with other phases
    ChemicalchemH2O[H2O.n_chem]Chemical connector for H2O
    Chemical'chemH+'['H+'.n_chem]Chemical connector for H+

    Modelica definition

    model Ionomer "Ionomer phase"
      import Modelica.Constants.inf;
      import Modelica.Math.BooleanVectors.countTrue;
    
      extends Icons.Phases.Solid;
      extends PartialPhase(
        final n_spec=countTrue({'inclSO3-','inclH+',inclH2O}),
        final V=-amagat.V,
        n_inter=1);
    
      // Conditionally include species.
      parameter Boolean 'inclSO3-'=false 
        "Include C19HF37O5S- (abbreviated as SO3-)";
    
      replaceable FCSys.Species.'SO3-'.Ionomer.Fixed 'SO3-'(
        final n_trans,
        final n_inter,
        final kL,
        final k_intra_Phi,
        final k_intra_Q) if 'inclSO3-' constrainedby FCSys.Species.Solid(
        n_trans=n_trans,
        n_intra=3,
        n_inter=n_inter,
        kL=kL,
        k_intra_Phi={common.k_Phi[cartTrans],'H+_SO3-'.k_Phi[cartTrans],'H2O_SO3-'.k_Phi[
            cartTrans]},
        k_intra_Q={common.k_Q,'H+_SO3-'.k_Q,'H2O_SO3-'.k_Q}) "SO3- model";
    
      parameter Boolean 'inclH+'=false "Include H+";
    
      replaceable FCSys.Species.'H+'.Ionomer.Fixed 'H+'(
        final n_trans,
        final n_inter,
        final n_chem,
        final kL,
        final k_intra_Phi,
        final k_intra_Q) if 'inclH+' constrainedby FCSys.Species.Fluid(
        n_trans=n_trans,
        n_intra=3,
        n_inter=n_inter,
        kL=kL,
        k_intra_Phi={common.k_Phi[cartTrans],'H+_H2O'.k_Phi[cartTrans],'H+_SO3-'.k_Phi[
            cartTrans]},
        k_intra_Q={common.k_Q,'H+_SO3-'.k_Q,'H+_H2O'.k_Q}) "H+ model";
    
      parameter Boolean inclH2O=false "Include H2O";
    
      replaceable FCSys.Species.H2O.Ionomer.Fixed H2O(
        final n_trans,
        final n_inter,
        final n_chem,
        final kL,
        final k_intra_Phi,
        final k_intra_Q) if inclH2O constrainedby FCSys.Species.Fluid(
        n_trans=n_trans,
        n_intra=3,
        n_inter=0,
        kL=kL,
        k_intra_Phi={common.k_Phi[cartTrans],'H+_H2O'.k_Phi[cartTrans],'H2O_SO3-'.k_Phi[
            cartTrans]},
        k_intra_Q={common.k_Q,'H+_H2O'.k_Q,'H2O_SO3-'.k_Q}) "H2O model";
    
      Connectors.BoundaryBus xNegative if inclTrans[Axis.x] 
        "Negative boundary along the x axis";
      Connectors.BoundaryBus yNegative if inclTrans[Axis.y] 
        "Negative boundary along the y axis";
      Connectors.BoundaryBus zNegative if inclTrans[Axis.z] 
        "Negative boundary along the z axis";
      Connectors.BoundaryBus xPositive if inclTrans[Axis.x] 
        "Positive boundary along the x axis";
      Connectors.BoundaryBus yPositive if inclTrans[Axis.y] 
        "Positive boundary along the y axis";
      Connectors.BoundaryBus zPositive if inclTrans[Axis.z] 
        "Positive boundary along the z axis";
      Connectors.Amagat amagat if n_spec > 0 "Connector for additivity of volume";
      Connectors.Inter inter[n_inter](each final n_trans=n_trans) if n_spec > 0 
        "Connector to exchange momentum and energy with other phases";
      Connectors.Chemical chemH2O[H2O.n_chem](each final n_trans=n_trans) if 
        inclH2O "Chemical connector for H2O";
      Connectors.Chemical 'chemH+'['H+'.n_chem](each final n_trans=n_trans) if 
        'inclH+' "Chemical connector for H+";
    
      // Independence factors
      ExchangeParams common(k_Phi={inf,inf,inf},k_Q=0) if n_spec > 0 
        "Among all species in the phase";
      ExchangeParams 'H+_SO3-'(final k_Phi, k_Q=inf) if 'inclSO3-' or 'inclH+' 
        "Between H+ and SO3-)";
      ExchangeParams 'H+_H2O'(k_Phi={0.02,0.02,0.02}, k_Q=inf) if 'inclH+' or 
        inclH2O "Between H+ and H2O";
    
      ExchangeParams 'H2O_SO3-'(k_Phi={1,1,1}, k_Q=inf) if 'inclSO3-' or inclH2O 
        "Between H2O and SO3-";
    
    protected 
      Conditions.Adapters.AmagatDalton amagatDalton if n_spec > 0 
        "Adapter between additivity of volume and additivity of pressure";
    
      Connectors.InertNode exchCommon 
        "Connector for exchange among all species in the phase";
      Connectors.InertNode 'exchH+_SO3-' 
        "Connector for exchange between H+ and SO3-";
      Connectors.InertNode 'exchH+_H2O' "Connector for exchange between H+ and H2O";
      Connectors.InertNode 'exchH2O_SO3-' 
        "Connector for exchange between H2O and SO3-";
    
    equation 
      // Chemical exchange
      connect(H2O.chemical, chemH2O);
      connect('H+'.chemical, 'chemH+');
    
      // Inert exchange
      connect('SO3-'.inter, inter);
    
      connect('SO3-'.intra[1], exchCommon.node);
      connect('SO3-'.intra[2], 'exchH+_SO3-'.node);
      connect('SO3-'.intra[3], 'exchH2O_SO3-'.node);
      connect('H+'.intra[1], exchCommon.node);
      connect('H+'.intra[2], 'exchH+_H2O'.node);
      connect('H+'.intra[3], 'exchH+_SO3-'.node);
    
      connect(H2O.intra[1], exchCommon.node);
      connect(H2O.intra[2], 'exchH+_H2O'.node);
      connect(H2O.intra[3], 'exchH2O_SO3-'.node);
    
      // Mixing
      connect('SO3-'.dalton, amagatDalton.dalton);
      connect('H+'.dalton, amagatDalton.dalton);
      connect(H2O.dalton, amagatDalton.dalton);
      connect(amagatDalton.amagat, amagat);
    
      // Transport
      // ---------
      // SO3-
      connect('SO3-'.boundaries[transCart[Axis.x], Side.n], xNegative.'SO3-');
    
      connect('SO3-'.boundaries[transCart[Axis.x], Side.p], xPositive.'SO3-');
    
      connect('SO3-'.boundaries[transCart[Axis.y], Side.n], yNegative.'SO3-');
    
      connect('SO3-'.boundaries[transCart[Axis.y], Side.p], yPositive.'SO3-');
    
      connect('SO3-'.boundaries[transCart[Axis.z], Side.n], zNegative.'SO3-');
      connect('SO3-'.boundaries[transCart[Axis.z], Side.p], zPositive.'SO3-');
      // 'H+'
      connect('H+'.boundaries[transCart[Axis.x], Side.n], xNegative.'H+');
    
      connect('H+'.boundaries[transCart[Axis.x], Side.p], xPositive.'H+');
    
      connect('H+'.boundaries[transCart[Axis.y], Side.n], yNegative.'H+');
    
      connect('H+'.boundaries[transCart[Axis.y], Side.p], yPositive.'H+');
    
      connect('H+'.boundaries[transCart[Axis.z], Side.n], zNegative.'H+');
      connect('H+'.boundaries[transCart[Axis.z], Side.p], zPositive.'H+');
      // H2O
      connect(H2O.boundaries[transCart[Axis.x], Side.n], xNegative.H2O);
    
      connect(H2O.boundaries[transCart[Axis.x], Side.p], xPositive.H2O);
    
      connect(H2O.boundaries[transCart[Axis.y], Side.n], yNegative.H2O);
    
      connect(H2O.boundaries[transCart[Axis.y], Side.p], yPositive.H2O);
    
      connect(H2O.boundaries[transCart[Axis.z], Side.n], zNegative.H2O);
      connect(H2O.boundaries[transCart[Axis.z], Side.p], zPositive.H2O);
    
    end Ionomer;
    

    FCSys.Phases.Liquid FCSys.Phases.Liquid

    Liquid phase FCSys.Phases.Liquid

    Information

    Please see the documentation of the PartialPhase model.

    Extends from Icons.Phases.Liquid (Icon for a liquid phase), PartialPhase (Base model for a phase).

    Parameters

    TypeNameDefaultDescription
    Integern_specif inclH2O then 1 else 0Number of species
    Integern_trans1Number of transport axes
    VolumeV-amagat.VVolume of the phase [L3]
    Geometry
    NumberAbsolutek[Axis]{1,1,1}Length factors for transport [1]
    Independence factors
    NumberAbsolutek_inter_Phi[n_inter, n_trans]ones(n_inter, n_trans)For translational exchange with other phases [1]
    NumberAbsolutek_inter_Q[n_inter]ones(n_inter)For thermal exchange with other phases [1]
    Species
    BooleaninclH2OfalseInclude H2O
    FixedH2Oredeclare FCSys.Species.H2O….H2O model

    Connectors

    TypeNameDescription
    BoundaryBusxNegativeNegative boundary along the x axis
    BoundaryBusyNegativeNegative boundary along the y axis
    BoundaryBuszNegativeNegative boundary along the z axis
    BoundaryBusxPositivePositive boundary along the x axis
    BoundaryBusyPositivePositive boundary along the y axis
    BoundaryBuszPositivePositive boundary along the z axis
    Interinter[n_inter]Connector to exchange momentum and energy with other phases
    AmagatamagatConnector for additivity of volume
    ChemicalchemH2O[H2O.n_chem]Chemical connector for H2O

    Modelica definition

    model Liquid "Liquid phase"
      extends Icons.Phases.Liquid;
      extends PartialPhase(final n_spec=if inclH2O then 1 else 0,final V=-amagat.V);
    
      // Conditionally include species.
      parameter Boolean inclH2O=false "Include H2O";
    
      // Auxiliary variables (for analysis)
      output Q.PressureAbsolute p(stateSelect=StateSelect.never) = amagat.p if 
        n_spec > 0 and environment.analysis "Total thermodynamic pressure";
    
      replaceable FCSys.Species.H2O.Liquid.Fixed H2O(
        final n_trans,
        final n_inter,
        final kL,
        final n_chem) if inclH2O constrainedby FCSys.Species.Fluid(
        n_trans=n_trans,
        n_inter=n_inter,
        kL=kL) "H2O model";
    
      Connectors.BoundaryBus xNegative if inclTrans[Axis.x] 
        "Negative boundary along the x axis";
      Connectors.BoundaryBus yNegative if inclTrans[Axis.y] 
        "Negative boundary along the y axis";
      Connectors.BoundaryBus zNegative if inclTrans[Axis.z] 
        "Negative boundary along the z axis";
      Connectors.BoundaryBus xPositive if inclTrans[Axis.x] 
        "Positive boundary along the x axis";
      Connectors.BoundaryBus yPositive if inclTrans[Axis.y] 
        "Positive boundary along the y axis";
      Connectors.BoundaryBus zPositive if inclTrans[Axis.z] 
        "Positive boundary along the z axis";
      Connectors.Inter inter[n_inter](each final n_trans=n_trans) if n_spec > 0 
        "Connector to exchange momentum and energy with other phases";
      Connectors.Amagat amagat if n_spec > 0 "Connector for additivity of volume";
      Connectors.Chemical chemH2O[H2O.n_chem](each final n_trans=n_trans) if 
        inclH2O "Chemical connector for H2O";
    
    protected 
      Conditions.Adapters.AmagatDalton amagatDalton if n_spec > 0 
        "Adapter between additivity of volume and additivity of pressure";
    
    equation 
      // Chemical exchange
      connect(H2O.chemical, chemH2O);
    
      // Inert exchange
      connect(H2O.inter, inter);
    
      // Mixing
      connect(amagatDalton.amagat, amagat);
      connect(amagatDalton.dalton, H2O.dalton);
    
      // Transport
      // ---------
      // H2O
      connect(H2O.boundaries[transCart[Axis.x], Side.n], xNegative.H2O);
    
      connect(H2O.boundaries[transCart[Axis.x], Side.p], xPositive.H2O);
    
      connect(H2O.boundaries[transCart[Axis.y], Side.n], yNegative.H2O);
    
      connect(H2O.boundaries[transCart[Axis.y], Side.p], yPositive.H2O);
    
      connect(H2O.boundaries[transCart[Axis.z], Side.n], zNegative.H2O);
      connect(H2O.boundaries[transCart[Axis.z], Side.p], zPositive.H2O);
    
    end Liquid;
    

    FCSys.Phases.PartialPhase

    Base model for a phase

    Information

    The scaling factor for diffusive transport (k) is a vector which directly affects the resistance associated with the transport of material, transverse translational momentum, and energy of all of the species within the phase. It can be used to introduce minor head loss or the effects of porosity or tortousity. These effects may be anisotropic. Using Bruggeman correction [Weber2004, p. 4696], the factor (k) within a phase should be set to ε-1/2 along each axis, where ε is the volumetric filling ratio, or the ratio of the volume of the phase to the total volume of the subregion. The Bruggeman factor itself increases resistance by a ε-3/2, but a factor of ε-1 is included inherently.

    Parameters

    TypeNameDefaultDescription
    Integern_spec Number of species
    Integern_trans1Number of transport axes
    Geometry
    NumberAbsolutek[Axis]{1,1,1}Length factors for transport [1]
    Independence factors
    NumberAbsolutek_inter_Phi[n_inter, n_trans]ones(n_inter, n_trans)For translational exchange with other phases [1]
    NumberAbsolutek_inter_Q[n_inter]ones(n_inter)For thermal exchange with other phases [1]

    Modelica definition

    partial model PartialPhase "Base model for a phase"
      import Modelica.Math.BooleanVectors.index;
    
      parameter Integer n_spec(start=0) "Number of species";
      parameter Integer n_inter=0 
        "Number of exchange connections with other phases";
    
      // Geometric parameters
      parameter Q.NumberAbsolute k[Axis](
        each min=Modelica.Constants.small,
        each final nominal=1) = {1,1,1} if n_spec > 0 
        "Length factors for transport";
      parameter Integer n_trans=1 "Number of transport axes";
      // Note:  This can't be an inner/outer parameter in Dymola 2014.
      inner Q.Volume V=0 if n_spec > 0 "Volume of the phase";
    
      // Independence factors
      inner parameter Q.NumberAbsolute k_inter_Phi[n_inter, n_trans]=ones(n_inter,
          n_trans) if n_spec > 0 "For translational exchange with other phases";
      inner parameter Q.NumberAbsolute k_inter_Q[n_inter]=ones(n_inter) if n_spec >
        0 "For thermal exchange with other phases";
    
      // Auxiliary variables (for analysis)
      output Q.NumberAbsolute epsilon=V/product(L) if n_spec > 0 and environment.analysis
        "Volumetric fill fraction";
    
    protected 
      outer parameter Q.Length L[Axis] if n_spec > 0 "Length of the subregion";
      final parameter Q.Length kL[:]=k[cartTrans] .* L[cartTrans] if n_spec > 0 
        "Effective transport lengths";
      final inner Q.Area Aprime[n_trans]=fill(V, n_trans) ./ L[cartTrans] if n_spec >
        0 "Effective cross-sectional areas";
      outer parameter Integer cartTrans[:] 
        "Cartesian-axis indices of the components of translational momentum";
      outer parameter Integer transCart[:] 
        "Boundary-pair indices of the Cartesian axes";
      outer parameter Boolean inclTrans[Axis] 
        "true, if each pair of boundaries is included";
    
      outer Conditions.Environment environment "Environmental conditions";
    
    end PartialPhase;
    

    FCSys.Phases.ExchangeParams FCSys.Phases.ExchangeParams

    Independence factors for an exchange process

    Information

    Extends from Modelica.Icons.Record (Icon for records).

    Parameters

    TypeNameDefaultDescription
    NumberAbsolutek_Phi[Axis]{1,1,1}Translational [1]
    NumberAbsolutek_Q1Thermal [1]

    Modelica definition

    record ExchangeParams "Independence factors for an exchange process"
      extends Modelica.Icons.Record;
    
      parameter Q.NumberAbsolute k_Phi[Axis]={1,1,1} "Translational";
      parameter Q.NumberAbsolute k_Q=1 "Thermal";
    
    end ExchangeParams;