# Specifying meshes for a new geometry

Figure A1 shows the proposed geometry we intend to model. The associated dimensions of the components are given in Table A1. The vertical structure can be captured by seven blocks, as shown in Figure A2, (the block containing the electrolyte is too thin to be discernible). The blocks containing the air and fuel channels can then be split horizontally to separate the channels from the ribs, the latter being part of the interconnects.

 Figure A1. A fuel cell with one air channel and one fuel channel. Left panel shows air (blue) and fuel (purple) inlets, interconnects (grey) and electrode sides. Centre panel shows air (blue) and fuel (purple) volume regions, each comprised of both a channel and a porous electrode zone. Right panel shows lower (blue) and upper (red) interconnect regions.

interconnect0air channelcathodeelectrolyteanodefuel channelinterconnect1
Table A1. Dimensions and extents of the cell components.
xlow0000000
xhigh50505050505050
length [mm]50505050505050
ylow0100010
yhigh4344434
width [mm]4244424
zlow03.55.005.295.36.36.3
zhigh55.05.295.306.37.811.3
height [mm]51.50.290.0111.55
 Bottom to top: interconnect0, air, cathode, electrolyte (too thin to discern), anode, fuel, and interconnect1.

We begin with a blockMeshDict dictionary that will create a parent mesh consisting of the seven vertical blocks (Figure A2), which for convenience, going from bottom to top, we refer to as interconnect0, air, cathode, electrolyte, anode, fuel, and interconnect1. Although the geometry shows symmetry about the y = 2 plane, we construct the entire domain for illustrative purposes. Here is the list of points for the blockMeshDict file:

blockMeshDictconvertToMeters 0.001;vertices(// ... From Bottom To Top// Interconnect0( 0 0 0) // 0(50 0 0) // 1(50 4 0) // 2( 0 4 0) // 3// Interconnect0_to_Air( 0 0 3.5) // 4(50 0 3.5) // 5(50 4 3.5) // 6( 0 4 3.5) // 7// Air_to_cathode( 0 0 5.0) // 8(50 0 5.0) // 9(50 4 5.0) //10( 0 4 5.0) //11// cathode_to_Electrolyte( 0 0 5.29) //12(50 0 5.29) //13(50 4 5.29) //14( 0 4 5.29) //15// Electrolyte_to_anode( 0 0 5.3) //16(50 0 5.3) //17(50 4 5.3) //18( 0 4 5.3) //19// anode_to_Fuel( 0 0 6.3) //20(50 0 6.3) //21(50 4 6.3) //22( 0 4 6.3) //23// fuel_to_Interconnect1( 0 0 7.8) //24(50 0 7.8) //25(50 4 7.8) //26( 0 4 7.8) //27// Interconnect1( 0 0 11.3) //28(50 0 11.3) //29(50 4 11.3) //30( 0 4 11.3) //31);In the vertices section above, each set of four vertices defines a horizontal rectangle representing an interface between the above mentioned blocks (and including the top and bottom surfaces). As can be readily seen, the vertices of a rectangle are arranged so that a traversal from one to the next takes one anticlockwise around the rectangle, starting from x=0. Note that the coordinates are scaled by 0.001 metres, so the maximum x-coordinate, for example, is 50 mm. The vertices are numbered by their index in the list, beginning at index 0. Figure A3 shows the location of some of these points on the geometry.

In the blocks section below, each hexahedral block is defined by two successive sets of four vertices, i.e. the corner vertices of the block. The air block, eg, is defined by: hex (4 5 6 7 8 9 10 11). The number of cells in each coordinate direction and the grading of the mesh are also prescribed here.

blocks(// Interconnect0hex (0 1 2 3 4 5 6 7) (25 8 7) simpleGrading (1 1 1)// airhex (4 5 6 7 8 9 10 11) (25 8 3) simpleGrading (1 1 1)// cathodehex (8 9 10 11 12 13 14 15) (25 8 1) simpleGrading (1 1 1)// electrolytehex (12 13 14 15 16 17 18 19) (25 8 1) simpleGrading (1 1 1)// anodehex (16 17 18 19 20 21 22 23) (25 8 2) simpleGrading (1 1 1)// fuelhex (20 21 22 23 24 25 26 27) (25 8 3) simpleGrading (1 1 1)// Interconnect1hex (24 25 26 27 28 29 30 31) (25 8 7) simpleGrading (1 1 1));We have no need to define any edges.
edges();
A patch consists of one or more outer boundaries of the blocks. These boundaries (rectangles in our case) are described by their corner vertices, arranged so that a traversal from one to the next takes one round the rectangle anticlockwise about the outward normal.

patches(// ... From Bottom to Top// Interconnect0patch interconnect0Bottom((0 3 2 1))patch interconnect0Sides((0 1 5 4)(3 7 6 2)(0 4 7 3)(1 2 6 5))// Airpatch airInlet((4 8 11 7))patch airOutlet((5 6 10 9))patch airSides((4 5 9 8)(7 11 10 6))// Cathodepatch cathodeSides((8 9 13 12)(11 15 14 10)(8 12 15 11)(9 10 14 13))// Electrolytepatch electrolyteSides((12 13 17 16)(15 19 18 14)(12 16 19 15)(13 14 18 17))// Anodepatch anodeSides((16 17 21 20)(19 23 22 18)(16 20 23 19)(17 18 22 21))// Fuelpatch fuelInlet((20 24 27 23))patch fuelOutlet((21 22 26 25))patch fuelSides((20 21 25 24)(23 27 26 22))// interconnect1patch interconnect1Sides((24 28 31 27)(25 26 30 29)(24 25 29 28)(27 31 30 26))patch interconnect1Top((28 29 30 31)));mergePatchPairs();// **********************************

For more description of the blockMeshDict dictionary and the blockMesh utility, see section 5.3, Mesh generation with the blockMesh utility, in the OpenFoam User Guide.

We must now define the cellSets that will make up the cells of our five regions: interconnect0, air, electrolyte, fuel and interconnect1. Using the cellSets, a mesh will be generated for each region. Note that the cathode and anode blocks will become porousZones within the air and fuel regions, respectively. A portion of the air block contains two ribs that must become part of the interconnect0 region, and similarly two ribs contained in the fuel block must become part of the interconnect1 region. Cells in the electrolyte block will form the electrolyte region, and cells in the interconnect blocks will become part of the interconnect regions.

The cellSets for the regions are specified in config/make.setSet. Here each cellSet is defined by the diagonally opposite corners of a box bounded by coordinate planes.

The first set specified is the cellSet interconnect0. The specification begins with the cells in the interconnect0 block, which consists of all the cells below z=3.5mm (note that the coordinates are given in metres). Then the cells of the ribs are added. One of these extends from y=0 mm to y=1 mm, and the other from y=3 mm to y=4 mm. Both extend the full length of 50 mm in x, and in height from z=3.5 mm to z=5 mm.

The specification for the air cellSet begins with the cathode block and adds the channel, which extends the full length of 50 mm in x, from y=1 mm to y=3 mm in width, and from y=3.5 mm to y=5 mm in height. The remaining sets are similarly specified.

make.setSet

cellSet interconnect0 new boxToCell (0 0.0e-3 0.0e-3) (50.0e-3 4.0e-3 3.5e-3)cellSet interconnect0 add boxToCell (0 0.0e-3 3.5e-3) (50.0e-3 1.0e-3 5.0e-3)cellSet interconnect0 add boxToCell (0 3.0e-3 3.5e-3) (50.0e-3 4.0e-3 5.0e-3)cellSet air new boxToCell (0 0.0e-3 5.0e-3) (50.0e-3 4.0e-3 5.29e-3)cellSet air add boxToCell (0 1.0e-3 3.5e-3) (50.0e-3 3.0e-3 5.0e-3)cellSet electrolyte new boxToCell (0 0 5.29e-3) (50.0e-3 4.0e-3 5.3e-3)cellSet fuel new boxToCell (0 0.0e-3 5.3e-3) (50.0e-3 4.0e-3 6.3e-3)cellSet fuel add boxToCell (0 1.0e-3 6.3e-3) (50.0e-3 3.0e-3 7.8e-3)cellSet interconnect1 new boxToCell (0 0.0e-3 7.8e-3) (50.0e-3 4.0e-3 11.3e-3)cellSet interconnect1 add boxToCell (0 0.0e-3 6.3e-3) (50.0e-3 1.0e-3 7.8e-3)cellSet interconnect1 add boxToCell (0 3.0e-3 6.3e-3) (50.0e-3 4.0e-3 7.8e-3)

The air and fuel regions are each given a porous zone within the fluid zone, as specified in config/make.setAir and config/make.set fuel:

make.setAir

cellSet air new boxToCell (0 0.0e-3 5.0e-3) (50.0e-3 4.0e-3 5.29e-3)cellSet air add boxToCell (0 1.0e-3 3.5e-3) (50.0e-3 3.0e-3 5.0e-3)cellSet cathode new boxToCell (0 0 5.0e-3) (40.0e-3 4.0e-3 5.29e-3)

make.setFuel

cellSet fuel new boxToCell (0 0.0e-3 5.3e-3) (50.0e-3 4.0e-3 6.3e-3)cellSet fuel add boxToCell (0 1.0e-3 6.3e-3) (50.0e-3 3.0e-3 7.8e-3)cellSet anode new boxToCell (0 0 5.3e-3) (50.0e-3 4.0e-3 6.3e-3)

Clearly, the fluid inlet and outlet patches on the global mesh are incorrect, since their original definitions include faces that are really part of the interconnect ribs. The correction proceeds in three steps. First, faceSets for all of the existing patches of the blockMesh are created using the patchToFace action of the faceSet utility, as specified by the config/make.faceSet file:

faceSet interconnect0Sides new patchToFace interconnect0Sides allfaceSet interconnect0Bottom new patchToFace interconnect0Bottom allfaceSet interconnect1Sides new patchToFace interconnect1sides allfaceSet interconnect1Top new patchToFace interconnect1Top allfaceSet electrolyteSides new patchToFace electrolyteSides allfaceSet cathodeSides new patchToFace cathodeSides allfaceSet airSides new patchToFace airSides allfaceSet airInlet new patchToFace airInlet allfaceSet airOutlet new patchToFace airOutlet allfaceSet anodeSides new patchToFace anodeSides allfaceSet fuelSides new patchToFace fuelSides allfaceSet fuelInlet new patchToFace fuelInlet allfaceSet fuelOutlet new patchToFace fuelOutlet allfaceSet interconnect0Sides add patchToFace airInlet allfaceSet interconnect0Sides add patchToFace airOutlet allfaceSet interconnect0Sides add patchToFace airSides allfaceSet interconnect1Sides add patchToFace fuelInlet allfaceSet interconnect1Sides add patchToFace fuelOutlet allfaceSet interconnect1Sides add patchToFace fuelSides allfaceSet airSides clearfaceSet airInlet clearfaceSet airOutlet clearfaceSet fuelSides clearfaceSet fuelInlet clearfaceSet fuelOutlet clearNote that the make.faceset file also specifies some manipulations, adding faceSets airInlet, airOutlet, and airSides to the faceSet interconnect0, and similary on the fuel side. After being added, they are subsequently cleared. Next, the inlet and outlet faceSets are corrected using new specifications in config/make.faceAir and config/make.faceFuel:

make.faceAir

faceSet airInlet new boxToFace (-1e-6 1.0e-3 3.5e-3) (1e-6 3.0e-3 5.0e-3)faceSet airOutlet new boxToFace (39.999e-3 1.0e-3 3.5e-3) (40.001e-3 3.0e-3 5.0e-3)faceSet interconnect0Sides delete faceToFace airInlet allfaceSet interconnect0Sides delete faceToFace airOutlet all

make.faceFuel

faceSet fuelInlet new boxToFace (-1e-6 1e-3 6.3e-3) (1e-6 3.0e-3 7.8e-3)faceSet fuelOutlet new boxToFace (39.999e-3 1e-3 6.3e-3) (40.001e-3 3.0e-3 7.8e-3)faceSet interconnect1Sides delete faceToFace fuelInlet allfaceSet interconnect1Sides delete faceToFace fuelOutlet all

The new inlet and outlet patches are defined by a bounding box for the new patch. Here the new airInlet, eg, is normal to the x-direction and is bounded by a box which is shallow in x, extending 1e-6 m in front of and behind the prescribed x-coordinate location. The lateral extents of the box in the other two directions correspond to the lateral extent of the inlet in those directions. Faces with face centre within the box will be selected, so the box must not extend to the adjacent grid cell. The fuelInlet and the two outlets are similarly defined. The new inlets and outlets are then removed from the interconnect faceSets.

Finally, the faceSets are used to create new patches using the createPatch utility, which is controlled by the system/createPatchDict file. Here is an excerpt for the airInlet patch:

patchInfo({name airInlet;// Type of new patchdictionary{type patch;}constructFrom set;patches ();set airInlet;}. . .);

We will find the following entry (with additional face numbering information) for the airInlet in the mesh boundary file.
airInlet{type patch;}
The remaining patches are formed in the same way. The complete patch list is:
interconnect0Bottominterconnect0SidesairInletairOutletcathodeSideselectrolyteSidesanodeSidesfuelInletfuelOutletinterconnect1Sidesinterconnect1Top