fluentFvMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2020-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include <fstream>
30 #include <iostream>
31 
32 using std::ios;
33 
34 #include "Time.H"
35 #include "fluentFvMesh.H"
36 #include "primitiveMesh.H"
37 #include "wallFvPatch.H"
38 #include "symmetryPlaneFvPatch.H"
39 #include "symmetryFvPatch.H"
40 #include "cellModel.H"
41 
42 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
43 
44 Foam::fluentFvMesh::fluentFvMesh(const IOobject& io)
45 :
46  fvMesh(io)
47 {}
48 
49 
50 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
51 
53 {
54  // Make a directory called fluentInterface in the case
55  mkDir(time().rootPath()/time().caseName()/"fluentInterface");
56 
57  // Open a file for the mesh
58  std::ofstream fluentMeshFile
59  (
60  time().rootPath()
61  / time().caseName()
62  / "fluentInterface"
63  / time().caseName() + ".msh"
64  );
65 
66  Info<< "Writing Fluent Mesh" << endl;
67 
68  fluentMeshFile
69  << "(0 \"OpenFOAM to Fluent Mesh File\")" << nl << nl
70  << "(0 \"Dimension:\")" << nl
71  << "(2 3)" << nl << nl
72  << "(0 \"Grid dimensions:\")" << nl;
73 
74  // Writing number of points
75  fluentMeshFile
76  << "(10 (0 1 ";
77 
78  // Writing hex
79  fluentMeshFile.setf(ios::hex, ios::basefield);
80 
81  fluentMeshFile
82  << nPoints() << " 0 3))" << std::endl;
83 
84  // Writing number of cells
85  fluentMeshFile
86  << "(12 (0 1 "
87  << nCells() << " 0 0))" << std::endl;
88 
89  // Writing number of faces
90  label nFcs = nFaces();
91 
92  fluentMeshFile
93  << "(13 (0 1 ";
94 
95  // Still writing hex
96  fluentMeshFile
97  << nFcs << " 0 0))" << std::endl << std::endl;
98 
99  // Return to dec
100  fluentMeshFile.setf(ios::dec, ios::basefield);
101 
102  // Writing points
103  fluentMeshFile
104  << "(10 (3 1 ";
105 
106  fluentMeshFile.setf(ios::hex, ios::basefield);
107  fluentMeshFile
108  << nPoints() << " 1 3)"
109  << std::endl << "(" << std::endl;
110 
111  fluentMeshFile.precision(10);
112  fluentMeshFile.setf(ios::scientific);
113 
114  for (const auto& p : points())
115  {
116  fluentMeshFile
117  << " " << p.x() << " " << p.y() << " " << p.z() << '\n';
118  }
119 
120  fluentMeshFile
121  << "))" << std::endl << std::endl;
122 
123  const labelUList& own = owner();
124  const labelUList& nei = neighbour();
125  const auto& fcs = faces();
126 
127  // Writing (mixed) internal faces
128  fluentMeshFile
129  << "(13 (2 1 "
130  << own.size() << " 2 0)" << std::endl << "(" << std::endl;
131 
132  forAll(own, facei)
133  {
134  const auto& l = fcs[facei];
135 
136  fluentMeshFile << " ";
137  fluentMeshFile << l.size() << " ";
138 
139  forAll(l, lI)
140  {
141  fluentMeshFile << l[lI] + 1 << " ";
142  }
143 
144  fluentMeshFile << nei[facei] + 1 << " ";
145  fluentMeshFile << own[facei] + 1 << std::endl;
146  }
147 
148  fluentMeshFile << "))" << std::endl;
149 
150  label nWrittenFaces = own.size();
151 
152  // Writing boundary faces
153  forAll(boundary(), patchi)
154  {
155  const faceUList& patchFaces = boundaryMesh()[patchi];
156 
157  const labelUList& patchFaceCells = boundaryMesh()[patchi].faceCells();
158 
159  // The face group will be offset by 10 from the patch label
160 
161  // Write header
162  fluentMeshFile
163  << "(13 (" << patchi + 10 << " " << nWrittenFaces + 1
164  << " " << nWrittenFaces + patchFaces.size() << " ";
165 
166  nWrittenFaces += patchFaces.size();
167 
168  // Write patch type
169  if (isA<wallFvPatch>(boundary()[patchi]))
170  {
171  fluentMeshFile << 3;
172  }
173  else if
174  (
175  isA<symmetryPlaneFvPatch>(boundary()[patchi])
176  || isA<symmetryFvPatch>(boundary()[patchi])
177  )
178  {
179  fluentMeshFile << 7;
180  }
181  else
182  {
183  fluentMeshFile << 4;
184  }
185 
186  fluentMeshFile
187  <<" 0)" << std::endl << "(" << std::endl;
188 
189  forAll(patchFaces, facei)
190  {
191  const auto& l = patchFaces[facei];
192 
193  fluentMeshFile << " ";
194  fluentMeshFile << l.size() << " ";
195 
196  // Note: In Fluent, all boundary faces point inwards, which is
197  // opposite from the OpenFOAM convention.
198  // Turn them around on printout
199  forAllReverse(l, lI)
200  {
201  fluentMeshFile << l[lI] + 1 << " ";
202  }
203 
204  fluentMeshFile << patchFaceCells[facei] + 1 << " 0" << std::endl;
205  }
206 
207  fluentMeshFile << "))" << std::endl;
208  }
209 
210  // Writing cells
211  fluentMeshFile
212  << "(12 (1 1 " << nCells() << " 1 0)" << nl
213  << '(';
214 
215  const cellModel& hex = cellModel::ref(cellModel::HEX);
216  const cellModel& prism = cellModel::ref(cellModel::PRISM);
217  const cellModel& pyr = cellModel::ref(cellModel::PYR);
218  const cellModel& tet = cellModel::ref(cellModel::TET);
219 
220  const cellShapeList& cells = cellShapes();
221 
222  label nHex = 0;
223  label nPrism = 0;
224  label nPyr = 0;
225  label nTet = 0;
226  label nPoly = 0;
227 
228  int nElemPerLine = 25; // Start with linebreak and indent
229 
230  forAll(cells, celli)
231  {
232  if (nElemPerLine == 25)
233  {
234  // 25 elements per line with initial indent (readability)
235  fluentMeshFile << "\n ";
236  nElemPerLine = 0;
237  }
238  else if (!(nElemPerLine % 5))
239  {
240  // Format in blocks of 5 (readability)
241  fluentMeshFile << token::SPACE;
242  }
243  fluentMeshFile << token::SPACE;
244  ++nElemPerLine;
245 
246 
247  if (cells[celli].model() == tet)
248  {
249  fluentMeshFile << 2;
250  ++nTet;
251  }
252  else if (cells[celli].model() == hex)
253  {
254  fluentMeshFile << 4;
255  ++nHex;
256  }
257  else if (cells[celli].model() == pyr)
258  {
259  fluentMeshFile << 5;
260  ++nPyr;
261  }
262  else if (cells[celli].model() == prism)
263  {
264  fluentMeshFile << 6;
265  ++nPrism;
266  }
267  else
268  {
269  fluentMeshFile << 7;
270  ++nPoly;
271  }
272  }
273 
274  fluentMeshFile
275  << nl << "))" << nl;
276 
277  // Return to dec
278  fluentMeshFile.setf(ios::dec, ios::basefield);
279 
280  // Writing patch types
281  fluentMeshFile << "(39 (1 fluid fluid-1)())" << std::endl;
282  fluentMeshFile << "(39 (2 interior interior-1)())" << std::endl;
283 
284  // Writing boundary patch types
285  forAll(boundary(), patchi)
286  {
287  fluentMeshFile
288  << "(39 (" << patchi + 10 << " ";
289 
290  // Write patch type
291  if (isA<wallFvPatch>(boundary()[patchi]))
292  {
293  fluentMeshFile << "wall ";
294  }
295  else if
296  (
297  isA<symmetryPlaneFvPatch>(boundary()[patchi])
298  || isA<symmetryFvPatch>(boundary()[patchi])
299  )
300  {
301  fluentMeshFile << "symmetry ";
302  }
303  else
304  {
305  fluentMeshFile << "pressure-outlet ";
306  }
307 
308  fluentMeshFile
309  << boundary()[patchi].name() << ")())" << std::endl;
310  }
311 
312  // Report some information.
313  // NB: conversion is serial-only, so no need to reduce the values
314  Info<< "Mesh had cells of these type:" << nl
315  << " hexahedra: " << nHex << nl
316  << " prisms: " << nPrism << nl
317  << " pyramids: " << nPyr << nl
318  << " tetrahedra: " << nTet << nl
319  << " polyhedra: " << nPoly << endl;
320 }
321 
322 
323 // ************************************************************************* //
faceListList boundary
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
IOstream & hex(IOstream &io)
Definition: IOstream.H:579
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:518
List< cellShape > cellShapeList
List of cellShape.
Definition: cellShapeList.H:32
std::ios_base::fmtflags setf(std::ios_base::fmtflags f)
Set stream flag(s), return old stream flags.
Definition: IOstream.H:506
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
static const cellModel & ref(const modelType model)
Look up reference to cellModel by enumeration. Fatal on failure.
Definition: cellModels.C:150
fluentFvMesh(const IOobject &io)
Construct from IOobject.
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:620
const cellShapeList & cells
const pointField & points
UList< face > faceUList
UList of faces.
Definition: faceListFwd.H:43
label nPoints
Space [isspace].
Definition: token.H:144
const auto & io
cellShapeList cellShapes
void writeFluentMesh() const
Write Fluent mesh.
messageStream Info
Information stream (stdout output on master, null elsewhere)
IOstream & dec(IOstream &io)
Definition: IOstream.H:573
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:416
volScalarField & p
IOstream & scientific(IOstream &io)
Definition: IOstream.H:597
virtual int precision() const =0
Get precision of output field.