## FCSys.Subregions

Control volumes with multi-species transfer and storage

### Information

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

### Package Content

Name | Description
--- | ---
Examples | Examples
Subregion | Subregion with all phases
SubregionIonomer | Subregion with only the ionomer phase
SubregionNoIonomer | Subregion with all phases except ionomer
PartialSubregion | Base model for multi-dimensional, multi-species storage, transport, and exchange

## FCSys.Subregions.Subregion

Subregion with all phases

### Information

Assumptions:

1. The oxygen reduction reaction generates liquid water if it is included; otherwise, it generates H2O vapor. Since phase change is a dynamic, nonequilibrium process, there is a difference.

Please see the documentation of the PartialSubregion model.

Extends from PartialSubregion (Base model for multi-dimensional, multi-species storage, transport, and exchange).

### Parameters

Type | Name | Default | Description
--- | --- | --- | ---
CapillaryVolume | volume |  | Volume with capillary pressure included
Geometry
Length | L[Axis] | {U.cm,U.cm,U.cm} | Lengths [L]
Phases (click to edit)
Gas | gas |  | Gas
Graphite | graphite |  | Graphite
Ionomer | ionomer |  | Ionomer
Liquid | liquid |  | Liquid
Independence factors
ExchangeParams | common |  | Among all phases
ExchangeParams | gasLiq |  | Between gas and liquid
Assumptions
Included transport axes
Boolean | inclTransX | true | X
Boolean | inclTransY | true | Y
Boolean | inclTransZ | true | Z

### Connectors

Type | Name | Description
--- | --- | ---
BoundaryBus | xNegative | Negative boundary along the x axis
BoundaryBus | yNegative | Negative boundary along the y axis
BoundaryBus | zNegative | Negative boundary along the z axis
BoundaryBus | xPositive | Positive boundary along the x axis
BoundaryBus | yPositive | Positive boundary along the y axis
BoundaryBus | zPositive | Positive boundary along the z axis

### Modelica definition

    model Subregion "Subregion with all phases"
      import Modelica.Constants.inf;

      extends PartialSubregion(final n_spec=gas.n_spec + graphite.n_spec + ionomer.n_spec
             + liquid.n_spec);

      FCSys.Phases.Gas gas(
        n_inter=2,
        final n_trans=n_trans,
        final k_inter_Phi={common.k_Phi[cartTrans],gasLiq.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q,gasLiq.k_Q}) "Gas";

      FCSys.Phases.Graphite graphite(
        n_inter=1,
        final n_trans=n_trans,
        'incle-Transfer'=inclHOR or inclORR,
        final k_inter_Phi={common.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q}) "Graphite";

      FCSys.Phases.Ionomer ionomer(
        n_inter=1,
        final n_trans=n_trans,
        final k_inter_Phi={common.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q}) "Ionomer";

      FCSys.Phases.Liquid liquid(
        n_inter=2,
        final n_trans=n_trans,
        final k_inter_Phi={common.k_Phi[cartTrans],gasLiq.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q,gasLiq.k_Q}) "Liquid";

      Chemistry.HOR HOR(final n_trans=n_trans) if inclHOR
        "Hydrogen oxidation reaction";
      Chemistry.ORR ORR(final n_trans=n_trans) if inclORR
        "Oxygen reduction reaction";

      // Independence factors
      Phases.ExchangeParams common(k_Phi={1.7,1.7,1.7}) "Among all phases";
      Phases.ExchangeParams gasLiq(k_Phi={inf,inf,inf}) "Between gas and liquid";

      Connectors.BoundaryBus xNegative if inclTransX
        "Negative boundary along the x axis";
      Connectors.BoundaryBus yNegative if inclTransY
        "Negative boundary along the y axis";
      Connectors.BoundaryBus zNegative if inclTransZ
        "Negative boundary along the z axis";
      Connectors.BoundaryBus xPositive if inclTransX
        "Positive boundary along the x axis";
      Connectors.BoundaryBus yPositive if inclTransY
        "Positive boundary along the y axis";
      Connectors.BoundaryBus zPositive if inclTransZ
        "Positive boundary along the z axis";

      Chemistry.CapillaryVolume volume(
        final V=V,
        final inclGas=gas.n_spec > 0,
        final inclLiquid=liquid.n_spec > 0,
        final inclSolid=graphite.n_spec + ionomer.n_spec > 0)
        "Volume with capillary pressure included";

    protected
      final parameter Boolean inclHOR=graphite.'incle-' and ionomer.'inclH+' and
          gas.inclH2 "Include the hydrogen oxidation reaction";
      final parameter Boolean inclORR=graphite.'incle-' and ionomer.'inclH+' and
          gas.inclO2 and (gas.inclH2O or liquid.inclH2O)
        "Include the oxygen reduction reaction";

      outer Conditions.Environment environment "Environmental conditions";
      Connectors.InertNode exchCommon "Connector for exchange among all species";
      Connectors.InertNode exchGasLiq
        "Connector for exchange between gas and liquid";

    equation
      // Boundaries
      // ----------
      // Gas
      connect(gas.yNegative, yNegative.gas);
      connect(gas.zPositive, zPositive.gas);
      connect(gas.xNegative, xNegative.gas);
      connect(gas.yPositive, yPositive.gas);
      connect(gas.zNegative, zNegative.gas);
      connect(gas.xPositive, xPositive.gas);
      // Graphite
      connect(graphite.yNegative, yNegative.graphite);
      connect(graphite.yPositive, yPositive.graphite);
      connect(graphite.zNegative, zNegative.graphite);
      connect(graphite.zPositive, zPositive.graphite);
      connect(graphite.xNegative, xNegative.graphite);
      connect(graphite.xPositive, xPositive.graphite);
      // Ionomer
      connect(ionomer.yNegative, yNegative.ionomer);
      connect(ionomer.yPositive, yPositive.ionomer);
      connect(ionomer.zNegative, zNegative.ionomer);
      connect(ionomer.zPositive, zPositive.ionomer);
      connect(ionomer.xNegative, xNegative.ionomer);
      connect(ionomer.xPositive, xPositive.ionomer);
      // Liquid
      connect(liquid.yNegative, yNegative.liquid);
      connect(liquid.yPositive, yPositive.liquid);
      connect(liquid.zNegative, zNegative.liquid);
      connect(liquid.zPositive, zPositive.liquid);
      connect(liquid.xNegative, xNegative.liquid);
      connect(liquid.xPositive, xPositive.liquid);

      // Mixing
      connect(gas.dalton, volume.gas);
      connect(liquid.amagat, volume.liquid);
      connect(volume.solid, graphite.amagat);
      connect(volume.solid, ionomer.amagat);

      // Inert exchange
      // --------------
      // Common
      connect(gas.inter[1], exchCommon.node);
      connect(graphite.inter[1], exchCommon.node);
      connect(ionomer.inter[1], exchCommon.node);
      connect(liquid.inter[1], exchCommon.node);
      // Gas-liquid
      connect(gas.inter[2], exchGasLiq.node);
      connect(liquid.inter[2], exchGasLiq.node);

      // Reactions and phase change (not shown in diagram)
      // -------------------------------------------------
      connect(gas.chemH2[1], HOR.chemH2);
      connect(gas.chemO2[1], ORR.chemO2);
      connect(liquid.chemH2O[1], ORR.chemH2O);
      if liquid.inclH2O then
        if gas.inclH2O then
          connect(liquid.chemH2O[2], gas.chemH2O[2]);
        end if;
        if ionomer.inclH2O then
          connect(liquid.chemH2O[3], ionomer.chemH2O[1]);
        end if;
      elseif gas.inclH2O then
        connect(gas.chemH2O[1], ORR.chemH2O);
      end if;
      connect(graphite.'cheme-'[1], HOR.'cheme-');
      connect(graphite.'cheme-'[1], ORR.'cheme-');
      connect(ionomer.'chemH+'[1], HOR.'chemH+');
      connect(ionomer.'chemH+'[1], ORR.'chemH+');
    end Subregion;

## FCSys.Subregions.SubregionIonomer

Subregion with only the ionomer phase

### Information

Please see the documentation of the PartialSubregion model.

Extends from PartialSubregion (Base model for multi-dimensional, multi-species storage, transport, and exchange).

### Parameters

Type | Name | Default | Description
--- | --- | --- | ---
CapillaryVolume | volume |  | Volume with capillary pressure included
Geometry
Length | L[Axis] | {U.cm,U.cm,U.cm} | Lengths [L]
Phases (click to edit)
Ionomer | ionomer |  | Ionomer
Assumptions
Included transport axes
Boolean | inclTransX | true | X
Boolean | inclTransY | true | Y
Boolean | inclTransZ | true | Z

### Connectors

Type | Name | Description
--- | --- | ---
BoundaryBus | xNegative | Negative boundary along the x axis
BoundaryBus | yNegative | Negative boundary along the y axis
BoundaryBus | zNegative | Negative boundary along the z axis
BoundaryBus | xPositive | Positive boundary along the x axis
BoundaryBus | yPositive | Positive boundary along the y axis
BoundaryBus | zPositive | Positive boundary along the z axis

### Modelica definition

    model SubregionIonomer "Subregion with only the ionomer phase"

      extends PartialSubregion(final n_spec=ionomer.n_spec);

      FCSys.Phases.Ionomer ionomer(n_inter=0, final n_trans=n_trans) "Ionomer";

      Connectors.BoundaryBus xNegative if inclTransX
        "Negative boundary along the x axis";
      Connectors.BoundaryBus yNegative if inclTransY
        "Negative boundary along the y axis";
      Connectors.BoundaryBus zNegative if inclTransZ
        "Negative boundary along the z axis";
      Connectors.BoundaryBus xPositive if inclTransX
        "Positive boundary along the x axis";
      Connectors.BoundaryBus yPositive if inclTransY
        "Positive boundary along the y axis";
      Connectors.BoundaryBus zPositive if inclTransZ
        "Positive boundary along the z axis";

      Chemistry.CapillaryVolume volume(
        final V=V,
        final inclSolid=ionomer.n_spec > 0,
        final inclGas=false,
        final inclLiquid=false) "Volume with capillary pressure included";

    equation
      // Boundaries
      // ----------
      // Ionomer

      connect(ionomer.yNegative, yNegative.ionomer);

      connect(ionomer.yPositive, yPositive.ionomer);
      connect(ionomer.zNegative, zNegative.ionomer);
      connect(ionomer.zPositive, zPositive.ionomer);

      connect(ionomer.xNegative, xNegative.ionomer);
      connect(ionomer.xPositive, xPositive.ionomer);

      connect(volume.solid, ionomer.amagat);
    end SubregionIonomer;

## FCSys.Subregions.SubregionNoIonomer

Subregion with all phases except ionomer

### Information

Please see the documentation of the PartialSubregion model.

Extends from PartialSubregion (Base model for multi-dimensional, multi-species storage, transport, and exchange).

### Parameters

Type | Name | Default | Description
--- | --- | --- | ---
Geometry
Length | L[Axis] | {U.cm,U.cm,U.cm} | Lengths [L]
Phases (click to edit)
Gas | gas |  | Gas
Graphite | graphite |  | Graphite
Liquid | liquid |  | Liquid
Independence factors
ExchangeParams | common |  | Among all phases
ExchangeParams | gasLiq |  | Between gas and liquid
Assumptions
Included transport axes
Boolean | inclTransX | true | X
Boolean | inclTransY | true | Y
Boolean | inclTransZ | true | Z

### Connectors

Type | Name | Description
--- | --- | ---
BoundaryBus | xNegative | Negative boundary along the x axis
BoundaryBus | yNegative | Negative boundary along the y axis
BoundaryBus | zNegative | Negative boundary along the z axis
BoundaryBus | xPositive | Positive boundary along the x axis
BoundaryBus | yPositive | Positive boundary along the y axis
BoundaryBus | zPositive | Positive boundary along the z axis

### Modelica definition

    model SubregionNoIonomer "Subregion with all phases except ionomer"
      import Modelica.Constants.inf;

      extends PartialSubregion(final n_spec=gas.n_spec + graphite.n_spec + liquid.n_spec);

      FCSys.Phases.Gas gas(
        n_inter=2,
        final n_trans=n_trans,
        final k_inter_Phi={common.k_Phi[cartTrans],gasLiq.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q,gasLiq.k_Q}) "Gas";

      FCSys.Phases.Graphite graphite(
        n_inter=1,
        final n_trans=n_trans,
        final k_inter_Phi={common.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q}) "Graphite";

      FCSys.Phases.Liquid liquid(
        n_inter=2,
        final n_trans=n_trans,
        final k_inter_Phi={common.k_Phi[cartTrans],gasLiq.k_Phi[cartTrans]},
        final k_inter_Q={common.k_Q,gasLiq.k_Q}) "Liquid";

      // Independence factors
      Phases.ExchangeParams common(k_Phi={1.7,1.7,1.7}) "Among all phases";
      Phases.ExchangeParams gasLiq(k_Phi={inf,inf,inf}) "Between gas and liquid";

      Connectors.BoundaryBus xNegative if inclTransX
        "Negative boundary along the x axis";
      Connectors.BoundaryBus yNegative if inclTransY
        "Negative boundary along the y axis";
      Connectors.BoundaryBus zNegative if inclTransZ
        "Negative boundary along the z axis";
      Connectors.BoundaryBus xPositive if inclTransX
        "Positive boundary along the x axis";
      Connectors.BoundaryBus yPositive if inclTransY
        "Positive boundary along the y axis";
      Connectors.BoundaryBus zPositive if inclTransZ
        "Positive boundary along the z axis";

      Chemistry.CapillaryVolume volume(
        final V=V,
        final inclGas=gas.n_spec > 0,
        final inclLiquid=liquid.n_spec > 0,
        final inclSolid=graphite.n_spec > 0)
        "Volume with capillary pressure included";

    protected
      outer Conditions.Environment environment "Environmental conditions";

      // Exchange
      Connectors.InertNode exchCommon "Among all phases";
      Connectors.InertNode exchGasLiq "Between gas and liquid";

    equation
      // Boundaries
      // ----------
      // Gas
      connect(gas.yNegative, yNegative.gas);
      connect(gas.zPositive, zPositive.gas);
      connect(gas.xNegative, xNegative.gas);
      connect(gas.yPositive, yPositive.gas);
      connect(gas.zNegative, zNegative.gas);
      connect(gas.xPositive, xPositive.gas);
      // Graphite
      connect(graphite.yNegative, yNegative.graphite);
      connect(graphite.yPositive, yPositive.graphite);
      connect(graphite.zNegative, zNegative.graphite);
      connect(graphite.zPositive, zPositive.graphite);
      connect(graphite.xNegative, xNegative.graphite);
      connect(graphite.xPositive, xPositive.graphite);
      // Liquid
      connect(liquid.yNegative, yNegative.liquid);
      connect(liquid.yPositive, yPositive.liquid);
      connect(liquid.zNegative, zNegative.liquid);
      connect(liquid.zPositive, zPositive.liquid);
      connect(liquid.xNegative, xNegative.liquid);
      connect(liquid.xPositive, xPositive.liquid);

      // Mixing
      connect(liquid.amagat, volume.liquid);
      connect(gas.dalton, volume.gas);
      connect(volume.solid, graphite.amagat);

      // Inert exchange
      // --------------
      // Common
      connect(gas.inter[1], exchCommon.node);
      connect(graphite.inter[1], exchCommon.node);
      connect(liquid.inter[1], exchCommon.node);
      // Gas-liquid
      connect(gas.inter[2], exchGasLiq.node);
      connect(liquid.inter[2], exchGasLiq.node);

      // Phase change (not shown in diagram)
      // -----------------------------------
      if gas.inclH2O and liquid.inclH2O then
        connect(gas.chemH2O[2], liquid.chemH2O[2]);
      end if;

    end SubregionNoIonomer;

## FCSys.Subregions.PartialSubregion

Base model for multi-dimensional, multi-species storage, transport, and exchange

### Information

At least one component of translational momentum must be included. All of the components are included by default.

This model should be extended to include the appropriate phases, reactions, etc.

### Parameters

Type | Name | Default | Description
--- | --- | --- | ---
Geometry
Length | L[Axis] | {U.cm,U.cm,U.cm} | Lengths [L]
Assumptions
Included transport axes
Boolean | inclTransX | true | X
Boolean | inclTransY | true | Y
Boolean | inclTransZ | true | Z

### Modelica definition

    partial model PartialSubregion
      "Base model for multi-dimensional, multi-species storage, transport, and exchange"
      import Modelica.Math.BooleanVectors.countTrue;
      import Modelica.Math.BooleanVectors.enumerate;
      import Modelica.Math.BooleanVectors.index;
      // extends FCSys.Icons.Names.Top3;

      // Geometric parameters
      inner parameter Q.Length L[Axis](each min=Modelica.Constants.small) = {U.cm,U.cm,
        U.cm} "Lengths";

      // Assumptions
      // -----------
      // Included boundaries
      parameter Boolean inclTransX=true "X";
      parameter Boolean inclTransY=true "Y";
      parameter Boolean inclTransZ=true "Z";

      // Auxiliary variables (for analysis)
      final inner parameter Q.Volume V=product(L) "Volume";
      final parameter Q.Area A[Axis]=fill(V, 3) ./ L "Cross-sectional areas";

    protected
      parameter Integer n_spec(start=0) "Number of species";
      final inner parameter Boolean inclTrans[Axis]={inclTransX,inclTransY,
          inclTransZ} "true, if each pair of boundaries is included";
      final inner parameter Boolean inclRot[Axis]={inclTransY and inclTransZ,
          inclTransZ and inclTransX,inclTransX and inclTransY}
        "true, if each axis of rotation has all its tangential boundaries included";
      final parameter Integer n_trans=countTrue(inclTrans)
        "Number of transport axes";
      final inner parameter Integer cartRot[:]=index(inclRot)
        "Cartesian-axis indices of the components of rotational momentum";
      final inner parameter Integer cartTrans[n_trans]=index(inclTrans)
        "Cartesian-axis indices of the transport axes";
      final inner parameter Integer transCart[Axis]=enumerate(inclTrans)
        "Transport-axis indices of the Cartesian axes";

    end PartialSubregion;