PDRarraysCalc.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) 2016 Shell Research Ltd.
9  Copyright (C) 2019-2020 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 "PDRarrays.H"
30 #include "PDRblock.H"
31 #include "PDRpatchDef.H"
32 #include "PDRmeshArrays.H"
33 #include "PDRparams.H"
34 
35 #include "PDRsetFields.H"
36 
37 #include "bitSet.H"
38 #include "DynamicList.H"
39 #include "dimensionSet.H"
40 #include "symmTensor.H"
41 #include "SquareMatrix.H"
42 #include "IjkField.H"
43 #include "MinMax.H"
44 #include "volFields.H"
45 #include "OFstream.H"
46 #include "OSspecific.H"
47 
48 #ifndef FULLDEBUG
49 #ifndef NDEBUG
50 #define NDEBUG
51 #endif
52 #endif
53 #include <cassert>
54 
55 using namespace Foam;
56 
57 HashTable<string> fieldNotes
58 ({
59  { "Lobs", "" },
60  { "Aw", "surface area per unit volume" },
61  { "CR", "" },
62  { "CT", "" },
63  { "N", "" },
64  { "ns", "" },
65  { "Nv", "" },
66  { "nsv", "" },
67  { "Bv", "area blockage" },
68  { "B", "area blockage" },
69  { "betai", "" },
70  { "Blong", "longitudinal blockage" },
71  { "Ep", "1/Lobs" },
72 });
73 
74 
75 // calc_fields
76 
77 
78 // Local Functions
79 /*
80 // calc_drag_etc
81 make_header
82 tail_field
83 write_scalarField
84 write_uniformField
85 write_symmTensorField
86 write_pU_fields
87 write_blocked_face_list
88 write_blockedCellsSet
89 */
90 
91 // Somewhat similar to what the C-fprintf would have had
92 static constexpr unsigned outputPrecision = 8;
93 
94 void calc_drag_etc
95 (
96  double brs, double brr, bool blocked,
97  double surr_br, double surr_dr,
98  scalar* drags_p, scalar* dragr_p,
99  double count,
100  scalar* cbdi_p,
101  double cell_vol
102 );
103 
104 
105 void write_scalarField
106 (
107  const word& fieldName, const IjkField<scalar>& fld,
108  const scalar& deflt, const scalarMinMax& limits, const char *wall_bc,
109  const PDRmeshArrays& meshIndexing,
111  const dimensionSet& dims, const fileName& casepath
112 );
113 
114 void write_uniformField
115 (
116  const word& fieldName, const scalar& deflt, const char *wall_bc,
117  const PDRmeshArrays& meshIndexing,
119  const dimensionSet& dims, const fileName& casepath
120 );
121 
122 void write_pU_fields
123 (
124  const PDRmeshArrays& meshIndexing,
126  const fileName& casepath
127 );
128 
129 void write_symmTensorField
130 (
131  const word& fieldName, const IjkField<symmTensor>& fld,
132  const symmTensor& deflt, const char *wall_bc,
133  const PDRmeshArrays& meshIndexing,
135  const dimensionSet& dims, const fileName& casepath
136 );
137 
138 void write_symmTensorFieldV
139 (
140  const word& fieldName, const IjkField<vector>& fld,
141  const symmTensor& deflt, const char *wall_bc,
142  const PDRmeshArrays& meshIndexing,
144  const dimensionSet& dims, const fileName& casepath
145 );
146 
147 void write_blocked_face_list
148 (
149  const IjkField<vector>& face_block,
150  const IjkField<labelVector>& face_patch,
151  const IjkField<scalar>& obs_count,
152  IjkField<vector>& sub_count,
153  IjkField<Vector<direction>>& n_blocked_faces,
154  const PDRmeshArrays& meshIndexing,
156  double limit_par, const fileName& casepath
157 );
158 
159 void write_blockedCellsSet
160 (
161  const IjkField<scalar>& fld,
162  const PDRmeshArrays& meshIndexing, double limit_par,
163  const IjkField<Vector<direction>>& n_blocked_faces,
164  const fileName& casepath,
165  const word& listName
166 );
167 
168 
169 // The average values of surrounding an array position
170 static inline scalar averageSurrounding
171 (
172  const SquareMatrix<scalar>& mat,
173  const label i,
174  const label j
175 )
176 {
177  return
178  (
179  mat(i,j) + mat(i,j+1) + mat(i,j+2)
180  + mat(i+1,j) /* centre */ + mat(i+1,j+2)
181  + mat(i+2,j) + mat(i+2,j+1) + mat(i+2,j+2)
182  ) / 8.0; // Average
183 }
184 
185 
186 // Helper
187 template<class Type>
188 static inline Ostream& putUniform(Ostream& os, const word& key, const Type& val)
189 {
190  os.writeKeyword(key) << word("uniform") << token::SPACE
191  << val << token::END_STATEMENT << nl;
192  return os;
193 }
194 
195 
196 static void make_header
197 (
198  Ostream& os,
199  const fileName& location,
200  const word& clsName,
201  const word& object
202 )
203 {
204  string note = fieldNotes(object);
205 
207 
208  os << "FoamFile\n{\n"
209  << " version 2.0;\n"
210  << " format ascii;\n"
211  << " class " << clsName << ";\n";
212 
213  if (!note.empty())
214  {
215  os << " note " << note << ";\n";
216  }
217 
218  if (!location.empty())
219  {
220  os << " location " << location << ";\n";
221  }
222 
223  os << " object " << object << ";\n"
224  << "}\n";
225 
226  IOobject::writeDivider(os) << nl;
227 }
228 
229 
231 (
232  PDRarrays& arr,
233  const PDRmeshArrays& meshIndexing,
234  const fileName& casepath,
236 )
237 {
238  if (isNull(arr.block()))
239  {
241  << "No PDRblock set" << nl
242  << exit(FatalError);
243  }
244 
245  const PDRblock& pdrBlock = arr.block();
246 
247  const labelVector& cellDims = meshIndexing.cellDims;
248  const labelVector& faceDims = meshIndexing.faceDims;
249 
250  const int xdim = faceDims.x();
251  const int ydim = faceDims.y();
252  const int zdim = faceDims.z();
253  const scalar maxCT = pars.maxCR * pars.cb_r;
254 
255 
256  // Later used to store the total effective blockage ratio per cell/direction
257  IjkField<symmTensor>& drag_s = arr.drag_s;
258 
259  IjkField<vector>& drag_r = arr.drag_r;
260 
261  const IjkField<vector>& area_block_s = arr.area_block_s;
262  const IjkField<vector>& area_block_r = arr.area_block_r;
263  const IjkField<Vector<bool>>& dirn_block = arr.dirn_block;
264 
265  const IjkField<vector>& betai_inv1 = arr.betai_inv1;
266 
267  IjkField<scalar>& obs_count = arr.obs_count;
268  IjkField<vector>& sub_count = arr.sub_count; // ns. Later used to hold longitudinal blockage
269  const IjkField<vector>& grating_count = arr.grating_count;
270 
271  IjkField<scalar>& v_block = arr.v_block;
272  IjkField<scalar>& surf = arr.surf;
273 
274  // Lobs. Later used for initial Ep
275  IjkField<scalar>& obs_size = arr.obs_size;
276 
277  Info<< "Calculating fields" << nl;
278 
279  // Local scratch arrays
280 
281  // The turbulance generation field CT.
282  // Later used to to hold the beta_i in tensor form
283  IjkField<vector> cbdi(cellDims, Zero);
284 
285 
286  // For 2D addressing it is convenient to just use the max dimension
287  // and avoid resizing when handling each direction.
288 
289  // Dimension of the cells and a layer of surrounding halo cells
290  const labelVector surrDims = (faceDims + labelVector::uniform(2));
291 
292  // Max addressing dimensions
293  const label maxDim = cmptMax(surrDims);
294 
295  // Blockage-ratio correction to the drag
296  //
297  // neiBlock:
298  // 2-D for averaging the blockage ratio of neighbouring cells.
299  // It extends one cell outside the domain in each direction,
300  // so the indices are offset by 1.
301  // neiDrag:
302  // 2-D array for averaging the drag ratio of neighbouring cells
303 
304  SquareMatrix<scalar> neiBlock(maxDim, Zero);
305  SquareMatrix<scalar> neiDrag(maxDim, Zero);
306 
307  // X blockage, drag
308 
309  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
310  {
311  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
312  {
313  for (label iz = 0; iz <= zdim; ++iz)
314  {
315  const label izz =
316  (iz == 0 ? 0 : iz == zdim ? zdim - 2 : iz - 1);
317 
318  neiBlock(iy+1, iz) =
319  (
320  area_block_s(ix,iy,izz).x()
321  + area_block_r(ix,iy,izz).x()
322  );
323 
324  neiDrag(iy+1, iz) =
325  (
326  drag_s(ix,iy,izz).xx() * pars.cd_s
327  + drag_r(ix,iy,izz).x() * pars.cd_r
328  );
329  }
330  }
331  for (label iz = 0; iz < surrDims.z(); ++iz)
332  {
333  if (pars.yCyclic)
334  {
335  // Cyclic in y
336  neiBlock(0, iz) = neiBlock(cellDims.y(), iz);
337  neiDrag(0, iz) = neiDrag(cellDims.y(), iz);
338  neiBlock(ydim, iz) = neiBlock(1, iz);
339  neiDrag(ydim, iz) = neiDrag(1, iz);
340  }
341  else
342  {
343  neiBlock(0, iz) = neiBlock(1, iz);
344  neiDrag(0, iz) = neiDrag(1, iz);
345  neiBlock(ydim, iz) = neiBlock(cellDims.y(), iz);
346  neiDrag(ydim, iz) = neiDrag(cellDims.y(), iz);
347  }
348  }
349 
350  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
351  {
352  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
353  {
354  const scalar cell_vol = pdrBlock.V(ix,iy,iz);
355 
356  const scalar surr_br = averageSurrounding(neiBlock, iy, iz);
357  const scalar surr_dr = averageSurrounding(neiDrag, iy, iz);
358 
359  calc_drag_etc
360  (
361  area_block_s(ix,iy,iz).x(),
362  area_block_r(ix,iy,iz).x(),
363  dirn_block(ix,iy,iz).x(),
364  surr_br, surr_dr,
365  &(drag_s(ix,iy,iz).xx()),
366  &(drag_r(ix,iy,iz).x()),
367  obs_count(ix,iy,iz),
368  &(cbdi(ix,iy,iz).x()),
369  cell_vol
370  );
371  }
372  }
373  }
374 
375 
376  // Y blockage, drag
377 
378  neiBlock = Zero;
379  neiDrag = Zero;
380 
381  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
382  {
383  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
384  {
385  for (label ix = 0; ix <= xdim; ++ix)
386  {
387  const label ixx =
388  (ix == 0 ? 0 : ix == xdim ? xdim - 2 : ix - 1);
389 
390  neiBlock(iz+1, ix) =
391  (
392  area_block_s(ixx,iy,iz).y()
393  + area_block_r(ixx,iy,iz).y()
394  );
395  neiDrag(iz+1, ix) =
396  (
397  drag_s(ixx,iy,iz).yy() * pars.cd_s
398  + drag_r(ixx,iy,iz).y() * pars.cd_r
399  );
400  }
401  }
402  for (label ix = 0; ix < surrDims.x(); ++ix)
403  {
404  neiBlock(0, ix) = neiBlock(1, ix);
405  neiDrag(0, ix) = neiDrag(1, ix);
406  neiBlock(zdim, ix) = neiBlock(cellDims.z(), ix);
407  neiDrag(zdim, ix) = neiDrag(cellDims.z(), ix);
408  }
409 
410  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
411  {
412  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
413  {
414  const scalar cell_vol = pdrBlock.V(ix,iy,iz);
415 
416  const scalar surr_br = averageSurrounding(neiBlock, iz, ix);
417  const scalar surr_dr = averageSurrounding(neiDrag, iz, ix);
418 
419  calc_drag_etc
420  (
421  area_block_s(ix,iy,iz).y(),
422  area_block_r(ix,iy,iz).y(),
423  dirn_block(ix,iy,iz).y(),
424  surr_br, surr_dr,
425  &(drag_s(ix,iy,iz).yy()),
426  &(drag_r(ix,iy,iz).y()),
427  obs_count(ix,iy,iz),
428  &(cbdi(ix,iy,iz).y()),
429  cell_vol
430  );
431  }
432  }
433  }
434 
435 
436  // Z blockage, drag
437 
438  neiBlock = Zero;
439  neiDrag = Zero;
440 
441  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
442  {
443  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
444  {
445  for (label iy = 0; iy <= ydim; ++iy)
446  {
447  label iyy;
448 
449  if (pars.yCyclic)
450  {
451  iyy = (iy == 0 ? ydim - 2 : iy == ydim ? 0 : iy - 1);
452  }
453  else
454  {
455  iyy = (iy == 0 ? 0 : iy == ydim ? ydim - 2 : iy - 1);
456  }
457 
458  neiBlock(ix+1, iy) =
459  (
460  area_block_s(ix,iyy,iz).z()
461  + area_block_r(ix,iyy,iz).z()
462  );
463  neiDrag(ix+1, iy) =
464  (
465  drag_s(ix,iyy,iz).zz() * pars.cd_s
466  + drag_r(ix,iyy,iz).z() * pars.cd_r
467  );
468  }
469  }
470  for (label iy = 0; iy < surrDims.y(); ++iy)
471  {
472  neiBlock(0, iy) = neiBlock(1, iy);
473  neiDrag(0, iy) = neiDrag(1, iy);
474  neiBlock(xdim, iy) = neiBlock(cellDims.x(), iy);
475  neiDrag(xdim, iy) = neiDrag(cellDims.x(), iy);
476  }
477 
478  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
479  {
480  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
481  {
482  const scalar cell_vol = pdrBlock.V(ix,iy,iz);
483 
484  const scalar surr_br = averageSurrounding(neiBlock, ix, iy);
485  const scalar surr_dr = averageSurrounding(neiDrag, ix, iy);
486 
487  calc_drag_etc
488  (
489  area_block_s(ix,iy,iz).z(),
490  area_block_r(ix,iy,iz).z(),
491  dirn_block(ix,iy,iz).z(),
492  surr_br, surr_dr,
493  &(drag_s(ix,iy,iz).zz()),
494  &(drag_r(ix,iy,iz).z()),
495  obs_count(ix,iy,iz),
496  &(cbdi(ix,iy,iz).z()),
497  cell_vol
498  );
499  }
500  }
501  }
502 
503  neiBlock.clear();
504  neiDrag.clear();
505 
506 
507  // Calculate other parameters
508 
509  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
510  {
511  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
512  {
513  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
514  {
515  const scalar dx = pdrBlock.dx(ix);
516  const scalar dy = pdrBlock.dy(iy);
517  const scalar dz = pdrBlock.dz(iz);
518  const scalar cell_vol = pdrBlock.V(ix, iy, iz);
519  const scalar cell_size = pdrBlock.width(ix, iy, iz);
520 
521  drag_s(ix,iy,iz).xy() *= pars.cd_s;
522  drag_s(ix,iy,iz).xz() *= pars.cd_s;
523  drag_s(ix,iy,iz).yz() *= pars.cd_s;
524 
525  if (drag_s(ix,iy,iz).xx() > pars.maxCR) { drag_s(ix,iy,iz).xx() = pars.maxCR; } ;
526  if (drag_s(ix,iy,iz).yy() > pars.maxCR) { drag_s(ix,iy,iz).yy() = pars.maxCR; } ;
527  if (drag_s(ix,iy,iz).zz() > pars.maxCR) { drag_s(ix,iy,iz).zz() = pars.maxCR; } ;
528 
529  if (cbdi(ix,iy,iz).x() > maxCT ) { cbdi(ix,iy,iz).x() = maxCT; } ;
530  if (cbdi(ix,iy,iz).y() > maxCT ) { cbdi(ix,iy,iz).y() = maxCT; } ;
531  if (cbdi(ix,iy,iz).z() > maxCT ) { cbdi(ix,iy,iz).z() = maxCT; } ;
532 
533  surf(ix,iy,iz) /= cell_vol;
534 
535  /* Calculate length scale of obstacles in each cell
536  Result is stored in surf. */
537 
538  {
539  const scalar vb = v_block(ix,iy,iz);
540 
541  if
542  (
543  (
544  ((area_block_s(ix,iy,iz).x() + area_block_r(ix,iy,iz).x()) < MIN_AB_FOR_SIZE)
545  && ((area_block_s(ix,iy,iz).y() + area_block_r(ix,iy,iz).y()) < MIN_AB_FOR_SIZE)
546  && ((area_block_s(ix,iy,iz).z() + area_block_r(ix,iy,iz).z()) < MIN_AB_FOR_SIZE)
547  )
548  || ( vb > MAX_VB_FOR_SIZE )
549  || ((obs_count(ix,iy,iz) + cmptSum(grating_count(ix,iy,iz))) < MIN_COUNT_FOR_SIZE)
550  || ( surf(ix,iy,iz) <= 0.0 )
551  )
552  {
553  obs_size(ix,iy,iz) = cell_size * pars.empty_lobs_fac;
554  }
555  else
556  {
557  /* A small sliver of a large cylinder ina cell can give large surface area
558  but low volume, hence snall "size". Therefore the vol/area formulation
559  is only fully implemented when count is at least COUNT_FOR_SIZE.*/
560  double nn, lobs, lobsMax;
561  nn = obs_count(ix,iy,iz) - sub_count(ix,iy,iz).x() + grating_count(ix,iy,iz).x();
562  if ( nn < 1.0 ) { nn = 1.0; }
563  lobsMax = (area_block_s(ix,iy,iz).x() + area_block_r(ix,iy,iz).x()) / nn * std::sqrt( dy * dz );
564  nn = obs_count(ix,iy,iz) - sub_count(ix,iy,iz).y() + grating_count(ix,iy,iz).y();
565  if ( nn < 1.0 ) { nn = 1.0; }
566  lobs = (area_block_s(ix,iy,iz).y() + area_block_r(ix,iy,iz).y()) / nn * std::sqrt( dz * dx );
567  if ( lobs > lobsMax )
568  {
569  lobsMax = lobs;
570  }
571 
572  nn = obs_count(ix,iy,iz) - sub_count(ix,iy,iz).z() + grating_count(ix,iy,iz).z();
573  if ( nn < 1.0 ) { nn = 1.0; }
574  lobs = (area_block_s(ix,iy,iz).z() + area_block_r(ix,iy,iz).z()) / nn * std::sqrt( dx * dy );
575  if ( lobs > lobsMax )
576  {
577  lobsMax = lobs;
578  }
579 
580  obs_size(ix,iy,iz) = lobsMax;
581  }
582  }
583 
584  /* The formulation correctly deals with triple intersections. For quadruple intersections
585  and worse, there are very many second level overlaps and the resulting volume can be large
586  positive. However, many or all of these may be eliminated because of the minimum volume of
587  overlap blocks. Then the result can be negative volume - constrain accordingly
588  */
589 
590  if (v_block(ix,iy,iz) < 0)
591  {
592  v_block(ix,iy,iz) = 0;
593  }
594  else if (v_block(ix,iy,iz) > 1)
595  {
596  v_block(ix,iy,iz) = 1;
597  }
598 
599  /* We can get -ve sub_count (ns) if two pipes/bars intersect and the dominat direction
600  of the (-ve) intersection block is not the same as either of the intersecting obstacles.
601  Also, if we have two hirizontal abrs intersecting, the overlap block can have vertical
602  edges in a cell where the original bars do not. This can give -ve N and ns.
603  Negative N is removed by write_scalar. */
604 
605  for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
606  {
607  if (sub_count(ix,iy,iz)[cmpt] < 0)
608  {
609  sub_count(ix,iy,iz)[cmpt] = 0;
610  }
611  }
612 
613  v_block(ix,iy,iz) = 1.0 - v_block(ix,iy,iz); // Now porosity
614  }
615  }
616  }
617 
618 
619 //*** Now we start writing the fields *********//
620 
621  /* v_block is now porosity
622  The maximum value does not override the default value placed in the external cells,
623  so pars.cong_max_betav can be set just below 1 to mark the congested-region cells
624  for use by the adaptive mesh refinement. */
625 
626  IjkField<Vector<direction>> n_blocked_faces
627  (
628  faceDims,
630  );
631 
632  write_blocked_face_list
633  (
634  arr.face_block, arr.face_patch,
635  obs_count, sub_count, n_blocked_faces,
636  meshIndexing, patches,
637  pars.blockedFacePar, casepath
638  );
639  write_blockedCellsSet
640  (
641  arr.v_block,
642  meshIndexing, pars.blockedCellPoros, n_blocked_faces,
643  casepath, "blockedCellsSet"
644  );
645 
646  write_scalarField
647  (
648  "betav", arr.v_block, 1, {0, pars.cong_max_betav}, "zeroGradient",
649  meshIndexing, patches,
650  dimless, casepath
651  );
652 
653  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
654  {
655  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
656  {
657  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
658  {
659  const scalar cell_vol = pdrBlock.V(ix, iy, iz);
660 
661  /* After the correction to set the number of obstacles normal to a blocked face
662  to be zero, we can have N and all the components of ns the same. Then there
663  are no obstacles in the cell as the number in each direction is n minus ns component),
664  but N is not zero. This can cause problems. We reduce all four numbers by the same amount,
665  which is OK as only the difference is used except when N is checked to se if there are
666  any obstacles in then cell. */
667 
668  scalar nmin = cmptMin(sub_count(ix,iy,iz));
669 
670  sub_count(ix,iy,iz).x() -= nmin;
671  sub_count(ix,iy,iz).y() -= nmin;
672  sub_count(ix,iy,iz).z() -= nmin;
673 
674  obs_count(ix,iy,iz) -= nmin;
675 
676  assert(obs_count(ix,iy,iz) > -1);
677  if ( pars.new_fields )
678  {
679  /* New fields Nv and nsv are intensive quantities that stay unchanged as a cell is subdivided
680  We do not divide by cell volume because we assume that typical obstacle
681  is a cylinder passing through the cell */
682  const scalar cell_23 = ::pow(cell_vol, 2.0/3.0);
683  obs_count(ix,iy,iz) /= cell_23;
684  sub_count(ix,iy,iz) /= cell_23;
685  }
686  }
687  }
688  }
689 
690 
691  {
692  Info<< "Writing field files" << nl;
693 
694  // obs_size is now the integral scale of the generated turbulence
695  write_scalarField
696  (
697  "Lobs", arr.obs_size, DEFAULT_LOBS, {0, 10}, "zeroGradient",
698  meshIndexing, patches,
699  dimLength, casepath
700  );
701  // surf is now surface area per unit volume
702  write_scalarField
703  (
704  "Aw", arr.surf, 0, {0, 1000}, "zeroGradient",
705  meshIndexing, patches,
706  inv(dimLength), casepath
707  );
708  write_symmTensorField
709  (
710  "CR", arr.drag_s, Zero, "zeroGradient",
711  meshIndexing, patches, inv(dimLength), casepath
712  );
713  write_symmTensorFieldV
714  (
715  "CT", cbdi, Zero, "zeroGradient",
716  meshIndexing, patches,
717  inv(dimLength), casepath
718  );
719  if ( pars.new_fields )
720  {
721  // These have been divided by cell volume ^ (2/3)
722  write_scalarField
723  (
724  "Nv", arr.obs_count, 0, {0, 1000}, "zeroGradient",
725  meshIndexing, patches,
726  dimless, casepath
727  );
728  write_symmTensorFieldV
729  (
730  "nsv", arr.sub_count, Zero, "zeroGradient",
731  meshIndexing, patches,
732  dimless, casepath
733  );
734  }
735  else
736  {
737  write_scalarField
738  (
739  "N", arr.obs_count, 0, {0, 1000}, "zeroGradient",
740  meshIndexing, patches,
741  dimless, casepath
742  );
743  write_symmTensorFieldV
744  (
745  "ns", arr.sub_count, Zero, "zeroGradient",
746  meshIndexing, patches, dimless, casepath
747  );
748  }
749 
750  // Compute some further variables; store in already used arrays
751  // Re-use the drag array
752  drag_s = Zero;
753 
754  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
755  {
756  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
757  {
758  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
759  {
760  // Effective blockage ratio per cell/direction
761  vector eff_block =
762  (
763  area_block_s(ix,iy,iz) * pars.cd_s/pars.cd_r
764  + area_block_r(ix,iy,iz)
765  );
766 
767  // Convert from B to Bv
768  if (pars.new_fields)
769  {
770  eff_block /= pdrBlock.width(ix, iy, iz);
771  }
772 
773  // Effective blockage is zero when faces are blocked
774  for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
775  {
776  if (dirn_block(ix,iy,iz)[cmpt] || eff_block[cmpt] < 0)
777  {
778  eff_block[cmpt] = 0;
779  }
780  }
781 
782  // Use the drag array to store the total effective blockage ratio per cell/direction
783  // - off-diagonal already zeroed
784  drag_s(ix,iy,iz).xx() = eff_block.x();
785  drag_s(ix,iy,iz).yy() = eff_block.y();
786  drag_s(ix,iy,iz).zz() = eff_block.z();
787 
788  cbdi(ix,iy,iz).x() = 1.0 / (betai_inv1(ix,iy,iz).x() + 1.0);
789  cbdi(ix,iy,iz).y() = 1.0 / (betai_inv1(ix,iy,iz).y() + 1.0);
790  cbdi(ix,iy,iz).z() = 1.0 / (betai_inv1(ix,iy,iz).z() + 1.0);
791 
792  if (cbdi(ix,iy,iz).z() < 0 || cbdi(ix,iy,iz).z() > 1.0)
793  {
795  << "beta_i problem. z-betai_inv1=" << betai_inv1(ix,iy,iz).z()
796  << " beta_i=" << cbdi(ix,iy,iz).z()
797  << nl;
798  }
799 
800  //Use the obs_size array to store Ep
801  //We use Ep/(Xp-0.999) as length scale to avoid divide by zero,
802  // so this is OK for initial Xp=1.
803  obs_size(ix,iy,iz) = 0.001 / obs_size(ix,iy,iz);
804 
805  // Use the count array to store the combustion flag ( --1 everywhere in rectangular cells).
806  obs_count(ix,iy,iz) = 1.0;
807  }
808  }
809  }
810 
811  // drag array holds area blockage
812  if ( pars.new_fields )
813  {
814  write_symmTensorField
815  (
816  "Bv", arr.drag_s, Zero, "zeroGradient",
817  meshIndexing, patches,
818  dimless, casepath
819  );
820  }
821  else
822  {
823  write_symmTensorField
824  (
825  "B", arr.drag_s, Zero, "zeroGradient",
826  meshIndexing, patches,
827  dimless, casepath
828  );
829  }
830 
831  // cbdi array holds beta_i
832  write_symmTensorFieldV
833  (
834  "betai", cbdi, symmTensor::I, "zeroGradient",
835  meshIndexing, patches,
836  dimless, casepath
837  );
838 
839  // The longitudinal blockage
840  write_symmTensorFieldV
841  (
842  "Blong", arr.along_block, Zero, "zeroGradient",
843  meshIndexing, patches,
844  dimless, casepath
845  );
846 
847  // obs_size array now contains 1/Lobs
848  write_scalarField
849  (
850  "Ep", arr.obs_size, DEFAULT_EP, {0, 10}, "zeroGradient",
851  meshIndexing, patches,
852  inv(dimLength), casepath
853  );
854  write_uniformField
855  (
856  "b", 1.0, "zeroGradient",
857  meshIndexing, patches,
858  dimless, casepath
859  );
860  write_uniformField
861  (
862  "k", DEFAULT_K, K_WALL_FN,
863  meshIndexing, patches,
864  sqr(dimVelocity),
865  casepath
866  );
867 
868  write_uniformField
869  (
870  "epsilon", DEFAULT_EPS, EPS_WALL_FN,
871  meshIndexing, patches,
872  sqr(dimVelocity)/dimTime, casepath
873  );
874  write_uniformField
875  (
876  "ft", 0, "zeroGradient",
877  meshIndexing, patches,
878  dimless, casepath
879  );
880  write_uniformField
881  (
882  "Su", DEFAULT_SU, "zeroGradient",
883  meshIndexing, patches,
884  dimVelocity, casepath
885  );
886  write_uniformField
887  (
888  "T", DEFAULT_T, "zeroGradient",
889  meshIndexing, patches,
890  dimTemperature, casepath
891  );
892  write_uniformField
893  (
894  "Tu", DEFAULT_T, "zeroGradient",
895  meshIndexing, patches,
896  dimTemperature, casepath
897  );
898  write_uniformField
899  (
900  "Xi", 1, "zeroGradient",
901  meshIndexing, patches,
902  dimless, casepath
903  );
904  write_uniformField
905  (
906  "Xp", 1, "zeroGradient",
907  meshIndexing, patches,
908  dimless, casepath
909  );
910  write_uniformField
911  (
912  "GRxp", 0, "zeroGradient",
913  meshIndexing, patches,
914  inv(dimTime), casepath
915  );
916  write_uniformField
917  (
918  "GRep", 0, "zeroGradient",
919  meshIndexing, patches,
920  inv(dimLength*dimTime), casepath
921  );
922  write_uniformField
923  (
924  "RPers", 0, "zeroGradient",
925  meshIndexing, patches,
926  inv(dimTime), casepath
927  );
928  write_pU_fields(meshIndexing, patches, casepath);
929 
930  write_uniformField
931  (
932  "alphat", 0, ALPHAT_WALL,
933  meshIndexing, patches,
935  casepath
936  );
937  write_uniformField
938  (
939  "nut", 0, NUT_WALL_FN,
940  meshIndexing, patches,
941  dimViscosity, casepath
942  );
943  // combustFlag is 1 in rectangular region, 0 or 1 elsewhere
944  // (although user could set it to another value)
945  if (equal(pars.outerCombFac, 1))
946  {
947  write_uniformField
948  (
949  "combustFlag", 1, "zeroGradient",
950  meshIndexing, patches,
951  dimless, casepath
952  );
953  }
954  else
955  {
956  write_scalarField
957  (
958  "combustFlag", arr.obs_count, pars.outerCombFac, {0, 1}, "zeroGradient",
959  meshIndexing, patches,
960  dimless, casepath
961  );
962  }
963  if ( pars.deluge )
964  {
965  write_uniformField
966  (
967  "H2OPS", 0, "zeroGradient",
968  meshIndexing, patches,
969  dimless, casepath
970  );
971  write_uniformField
972  (
973  "AIR", 0, "zeroGradient",
974  meshIndexing, patches,
975  dimless, casepath
976  );
977  write_uniformField
978  (
979  "Ydefault", 0, "zeroGradient",
980  meshIndexing, patches,
981  dimless, casepath
982  );
983  write_uniformField
984  (
985  "eRatio", 1, "zeroGradient",
986  meshIndexing, patches,
987  dimless, casepath
988  );
989  write_uniformField
990  (
991  "sprayFlag", 1, "zeroGradient",
992  meshIndexing, patches,
993  dimless, casepath
994  );
995  }
996  }
997 }
998 
999 
1001 (
1002  const fileName& casepath,
1003  const PDRmeshArrays& meshIndexing,
1005 )
1006 {
1007  calculateAndWrite(*this, meshIndexing, casepath, patches);
1008 }
1009 
1010 
1011 void calc_drag_etc
1012 (
1013  double brs, double brr, bool blocked,
1014  double surr_br, double surr_dr,
1015  scalar* drags_p, scalar* dragr_p,
1016  double count,
1017  scalar* cbdi_p,
1018  double cell_vol
1019 )
1020 {
1021  // Total blockage ratio
1022  scalar br = brr + brs;
1023 
1024  // Idealise obstacle arrangement as sqrt(count) rows.
1025  // Make br the blockage ratio for each row.
1026  if (count > 1.0) { br /= std::sqrt(count); }
1027 
1028  const scalar alpha =
1029  (
1030  br < 0.99
1031  ? (1.0 - 0.5 * br) / (1.0 - br) / (1.0 - br)
1032  : GREAT
1033  );
1034 
1035  // For the moment keep separate the two contributions to the blockage-corrected drag
1036  /* An isolated long obstcale will have two of the surronding eight cells with the same blockage,
1037  so surr_br would be br/4. In this case no correction. Rising to full correction when
1038  all surrounding cells have the same blockage. */
1039  const scalar expon =
1040  (
1041  br > 0.0
1042  ? min(max((surr_br / br - 0.25) * 4.0 / 3.0, scalar(0)), scalar(1))
1043  : 0.0
1044  );
1045 
1046  const scalar alpha_r = ::pow(alpha, 0.5 + 0.5 * expon);
1047  const scalar alpha_s = ::pow(alpha, expon);
1048 
1049  *dragr_p *= alpha_r;
1050  *drags_p *= ::pow(alpha_s, 1.09);
1051  *cbdi_p = ( pars.cb_r * pars.cd_r * *dragr_p + pars.cb_s * pars.cd_s * *drags_p );
1052  if ( *cbdi_p < 0.0 ) { *cbdi_p = 0.0; }
1053 
1054  // Finally sum the drag.
1055  *drags_p = ( *drags_p * pars.cd_s + *dragr_p * pars.cd_r );
1056  if ( *drags_p < 0.0 ) { *drags_p = 0.0; }
1057  /* If well-blocked cells are surrounded by empty cells, the flow just goes round
1058  and the drag parameters have little effect. So, for any cells much more empty
1059  than the surrounding cells, we put some CR in there as well. */
1060  if ( (surr_dr * 0.25) > *drags_p )
1061  {
1062  *drags_p = surr_dr * 0.25;
1063  *cbdi_p = *drags_p * (pars.cb_r + pars.cb_s ) * 0.5;
1064  // Don't know whether surr. stuff was round or sharp; use average of cb factors
1065  }
1066  if ( blocked ) { *cbdi_p = 0.0; *drags_p = 0.0; *dragr_p = 0.0; }
1067 }
1068 
1069 
1071 {
1072  if (isNull(block()))
1073  {
1075  << nl
1076  << "No blockage information - PDRblock is not set" << nl;
1077  return;
1078  }
1079 
1080  const PDRblock& pdrBlock = block();
1081 
1082  scalar totArea = 0;
1083  scalar totCount = 0;
1084  scalar totVolBlock = 0;
1085 
1086  vector totBlock(Zero);
1087  vector totDrag(Zero);
1088 
1089  for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz)
1090  {
1091  for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy)
1092  {
1093  for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix)
1094  {
1095  const labelVector ijk(ix,iy,iz);
1096 
1097  totVolBlock += v_block(ijk) * pdrBlock.V(ijk);
1098  totArea += surf(ijk);
1099 
1100  totCount += max(0, obs_count(ijk));
1101 
1102  totDrag.x() += max(0, drag_s(ijk).xx());
1103  totDrag.y() += max(0, drag_s(ijk).yy());
1104  totDrag.z() += max(0, drag_s(ijk).zz());
1105 
1106  for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
1107  {
1108  totBlock[cmpt] += max(0, area_block_s(ijk)[cmpt]);
1109  totBlock[cmpt] += max(0, area_block_r(ijk)[cmpt]);
1110  }
1111  }
1112  }
1113  }
1114 
1115  Info<< nl
1116  << "Volume blockage: " << totVolBlock << nl
1117  << "Total drag: " << totDrag << nl
1118  << "Total count: " << totCount << nl
1119  << "Total area blockage: " << totBlock << nl
1120  << "Total surface area: " << totArea << nl;
1121 }
1122 
1123 
1124 // ------------------------------------------------------------------------- //
1125 
1126 // Another temporary measure
1127 template<class Type>
1128 static void tail_field
1129 (
1130  Ostream& os,
1131  const Type& deflt,
1132  const char* wall_bc,
1134 )
1135 {
1136  // seaGround
1137  {
1138  os.beginBlock("seaGround");
1139  os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl;
1140  putUniform(os, "value", deflt);
1141  os.endBlock();
1142  }
1143 
1144  forAll(patches, patchi)
1145  {
1146  const word& patchName = patches[patchi].patchName;
1147 
1148  if (PDRpatchDef::BLOCKED_FACE == patchi)
1149  {
1150  // blockedFaces
1151  os.beginBlock(patchName);
1152 
1153  // No wall functions for blockedFaces patch unless selected
1155  {
1156  os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl;
1157  putUniform(os, "value", deflt);
1158  }
1159  else
1160  {
1161  os.writeEntry("type", "zeroGradient");
1162  }
1163 
1164  os.endBlock();
1165  }
1166  else if (patches[patchi].patchType == 0)
1167  {
1168  os.beginBlock(patchName);
1169 
1170  os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl;
1171  putUniform(os, "value", deflt);
1172 
1173  os.endBlock();
1174  }
1175  else
1176  {
1177  os.beginBlock(word(patchName + "Wall"));
1178  os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl;
1179  putUniform(os, "value", deflt);
1180  os.endBlock();
1181 
1182  os.beginBlock(word(patchName + "Cyclic_half0"));
1183  os.writeEntry("type", "cyclic");
1184  os.endBlock();
1185 
1186  os.beginBlock(word(patchName + "Cyclic_half1"));
1187  os.writeEntry("type", "cyclic");
1188  os.endBlock();
1189  }
1190  }
1191 
1192  if (pars.yCyclic)
1193  {
1194  os.beginBlock("Cyclic_half0");
1195  os.writeEntry("type", "cyclic");
1196  os.endBlock();
1197 
1198  os.beginBlock("Cyclic_half1");
1199  os.writeEntry("type", "cyclic");
1200  os.endBlock();
1201  }
1202  else
1203  {
1204  os.beginBlock("ySymmetry");
1205  os.writeEntry("type", "symmetryPlane");
1206  os.endBlock();
1207  }
1208 
1209  if ( pars.two_d )
1210  {
1211  os.beginBlock("z_boundaries");
1212  os.writeEntry("type", "empty");
1213  os.endBlock();
1214  }
1215  if ( pars.outer_orthog )
1216  {
1217  os.beginBlock("outer_inner");
1218  os.writeEntry("type", "cyclicAMI");
1219  os.writeEntry("neighbourPatch", "inner_outer");
1220  os.endBlock();
1221 
1222  os.beginBlock("inner_outer");
1223  os.writeEntry("type", "cyclicAMI");
1224  os.writeEntry("neighbourPatch", "outer_inner");
1225  os.endBlock();
1226  }
1227 }
1228 
1229 
1230 // ------------------------------------------------------------------------- //
1231 
1232 void write_scalarField
1233 (
1234  const word& fieldName, const IjkField<scalar>& fld,
1235  const scalar& deflt, const scalarMinMax& limits, const char *wall_bc,
1236  const PDRmeshArrays& meshIndexing,
1237  const UList<PDRpatchDef>& patches,
1238  const dimensionSet& dims, const fileName& casepath
1239 )
1240 {
1241  fileName path = (casepath / pars.timeName / fieldName);
1242  OFstream os(path);
1243  os.precision(outputPrecision);
1244 
1245  make_header(os, "", volScalarField::typeName, fieldName);
1246 
1247  os.writeEntry("dimensions", dims);
1248 
1249  os << nl;
1250  os.writeKeyword("internalField")
1251  << "nonuniform List<scalar>" << nl
1252  << meshIndexing.nCells() << nl << token::BEGIN_LIST << nl;
1253 
1254  for (label celli=0; celli < meshIndexing.nCells(); ++celli)
1255  {
1256  const labelVector& cellIdx = meshIndexing.cellIndex[celli];
1257 
1258  if (cmptMin(cellIdx) < 0)
1259  {
1260  os << deflt << nl;
1261  continue;
1262  }
1263 
1264  os << limits.clip(fld(cellIdx)) << nl;
1265  }
1266 
1268 
1269  os << nl;
1270  os.beginBlock("boundaryField");
1271 
1272  // outer
1273  {
1274  os.beginBlock("outer");
1275 
1276  os.writeEntry("type", "inletOutlet");
1277  putUniform(os, "inletValue", deflt);
1278  putUniform(os, "value", deflt);
1279 
1280  os.endBlock();
1281  }
1282 
1283  tail_field(os, deflt, wall_bc, patches);
1284 
1285  os.endBlock(); // boundaryField
1286 
1288 }
1289 
1290 
1291 // ------------------------------------------------------------------------- //
1292 
1293 void write_uniformField
1294 (
1295  const word& fieldName, const scalar& deflt, const char *wall_bc,
1296  const PDRmeshArrays& meshIndexing,
1297  const UList<PDRpatchDef>& patches,
1298  const dimensionSet& dims, const fileName& casepath
1299 )
1300 {
1301  OFstream os(casepath / pars.timeName / fieldName);
1302  os.precision(outputPrecision);
1303 
1304  make_header(os, "", volScalarField::typeName, fieldName);
1305 
1306  os.writeEntry("dimensions", dims);
1307 
1308  os << nl;
1309  putUniform(os, "internalField", deflt);
1310 
1311  os << nl;
1312  os.beginBlock("boundaryField");
1313 
1314  // outer
1315  {
1316  os.beginBlock("outer");
1317  if (fieldName == "alphat" || fieldName == "nut")
1318  {
1319  // Different b.c. for alphat & nut
1320  os.writeEntry("type", "calculated");
1321  }
1322  else
1323  {
1324  os.writeEntry("type", "inletOutlet");
1325  putUniform(os, "inletValue", deflt);
1326  }
1327 
1328  putUniform(os, "value", deflt);
1329  os.endBlock();
1330  }
1331 
1332  tail_field(os, deflt, wall_bc, patches);
1333 
1334  os.endBlock(); // boundaryField
1335 
1337 }
1338 
1339 
1340 // ------------------------------------------------------------------------- //
1341 
1342 void write_pU_fields
1343 (
1344  const PDRmeshArrays& meshIndexing,
1345  const UList<PDRpatchDef>& patches,
1346  const fileName& casepath
1347 )
1348 {
1349  // Velocity field
1350  {
1351  OFstream os(casepath / pars.timeName / "U");
1352  os.precision(outputPrecision);
1353 
1354  make_header(os, "", volVectorField::typeName, "U");
1355 
1356  os.writeEntry("dimensions", dimVelocity);
1357 
1358  os << nl;
1359  putUniform(os, "internalField", vector::zero);
1360 
1361  os << nl;
1362  os.beginBlock("boundaryField");
1363 
1364  // "outer"
1365  {
1366  os.beginBlock("outer");
1367  os.writeEntry("type", "inletOutlet");
1368  putUniform(os, "inletValue", vector::zero);
1369  os.endBlock();
1370  }
1371 
1372  // seaGround
1373  {
1374  os.beginBlock("seaGround");
1375  os.writeEntry("type", "zeroGradient");
1376  os.endBlock();
1377  }
1378 
1379  // Patch 0 is the blocked faces' and 1 is mergingFaces for ignition cell
1380  for (label patchi = 0; patchi < 3; ++patchi)
1381  {
1382  os.beginBlock(patches[patchi].patchName);
1383  os.writeKeyword("type") << pars.UPatchBc.c_str()
1384  << token::END_STATEMENT << nl;
1385  os.endBlock();
1386  }
1387 
1388  for (label patchi = 3; patchi < patches.size(); ++patchi)
1389  {
1390  const PDRpatchDef& p = patches[patchi];
1391  const word& patchName = p.patchName;
1392 
1393  if (p.patchType == 0)
1394  {
1395  os.beginBlock(patchName);
1396 
1397  os.writeEntry("type", "timeVaryingMappedFixedValue");
1398  os.writeEntry("fileName", "<case>" / (patchName + ".dat"));
1399  os.writeEntry("outOfBounds", "clamp");
1400  putUniform(os, "value", vector::zero);
1401  os.endBlock();
1402  }
1403  else
1404  {
1405  os.beginBlock(word(patchName + "Wall"));
1406  os.writeEntry("type", "activePressureForceBaffleVelocity");
1407 
1408  os.writeEntry("cyclicPatch", word(patchName + "Cyclic_half0"));
1409  os.writeEntry("openFraction", 0); // closed
1410  os.writeEntry("openingTime", p.blowoffTime);
1411  os.writeEntry("minThresholdValue", p.blowoffPress);
1412  os.writeEntry("maxOpenFractionDelta", 0.1);
1413  os.writeEntry("forceBased", "false");
1414  os.writeEntry("opening", "true");
1415 
1416  putUniform(os, "value", vector::zero);
1417  os.endBlock();
1418 
1419  os.beginBlock(word(patchName + "Cyclic_half0"));
1420  os.writeEntry("type", "cyclic");
1421  putUniform(os, "value", vector::zero);
1422  os.endBlock();
1423 
1424  os.beginBlock(word(patchName + "Cyclic_half1"));
1425  os.writeEntry("type", "cyclic");
1426  putUniform(os, "value", vector::zero);
1427  os.endBlock();
1428  }
1429  }
1430 
1431  if (pars.yCyclic)
1432  {
1433  os.beginBlock("yCyclic_half0");
1434  os.writeEntry("type", "cyclic");
1435  os.endBlock();
1436 
1437  os.beginBlock("yCyclic_half1");
1438  os.writeEntry("type", "cyclic");
1439  os.endBlock();
1440  }
1441  else
1442  {
1443  os.beginBlock("ySymmetry");
1444  os.writeEntry("type", "symmetryPlane");
1445  os.endBlock();
1446  }
1447 
1448  if ( pars.outer_orthog )
1449  {
1450  os.beginBlock("outer_inner");
1451  os.writeEntry("type", "cyclicAMI");
1452  os.writeEntry("neighbourPatch", "inner_outer");
1453  os.endBlock();
1454 
1455  os.beginBlock("inner_outer");
1456  os.writeEntry("type", "cyclicAMI");
1457  os.writeEntry("neighbourPatch", "outer_inner");
1458  }
1459 
1460  os.endBlock(); // boundaryField
1461 
1463  }
1464 
1465 
1466  // Pressure field
1467  {
1468  const scalar deflt = DEFAULT_P;
1469  const char *wall_bc = "zeroGradient;\n\trho\trho";
1470 
1471  OFstream os(casepath / pars.timeName / "p");
1472  os.precision(outputPrecision);
1473 
1474  make_header(os, "", volScalarField::typeName, "p");
1475 
1476  os.writeEntry("dimensions", dimPressure);
1477 
1478  os << nl;
1479  putUniform(os, "internalField", deflt);
1480 
1481  os << nl;
1482  os.beginBlock("boundaryField");
1483 
1484  // "outer"
1485  {
1486  os.beginBlock("outer");
1487  os.writeEntry("type", "waveTransmissive");
1488  os.writeEntry("gamma", 1.3);
1489  os.writeEntry("fieldInf", deflt);
1490  os.writeEntry("lInf", 5);
1491  putUniform(os, "value", deflt);
1492  os.endBlock();
1493  }
1494 
1495  tail_field(os, deflt, wall_bc, patches);
1496 
1497  os.endBlock(); // boundaryField
1498 
1500  }
1501 }
1502 
1503 
1504 // ------------------------------------------------------------------------- //
1505 
1506 void write_symmTensorField
1507 (
1508  const word& fieldName,
1509  const IjkField<symmTensor>& fld,
1510  const symmTensor& deflt, const char *wall_bc,
1511  const PDRmeshArrays& meshIndexing,
1512  const UList<PDRpatchDef>& patches,
1513  const dimensionSet& dims, const fileName& casepath
1514 )
1515 {
1516  OFstream os(casepath / pars.timeName / fieldName);
1517  os.precision(outputPrecision);
1518 
1519  make_header(os, "", volSymmTensorField::typeName, fieldName);
1520 
1521  os.writeEntry("dimensions", dims);
1522 
1523  os << nl;
1524  os.writeKeyword("internalField")
1525  << "nonuniform List<symmTensor>" << nl
1526  << meshIndexing.nCells() << nl << token::BEGIN_LIST << nl;
1527 
1528  for (label celli=0; celli < meshIndexing.nCells(); ++celli)
1529  {
1530  const labelVector& cellIdx = meshIndexing.cellIndex[celli];
1531 
1532  if (cmptMin(cellIdx) < 0)
1533  {
1534  os << deflt << nl;
1535  continue;
1536  }
1537 
1538  os << fld(cellIdx) << nl;
1539  }
1541 
1542  os << nl;
1543  os.beginBlock("boundaryField");
1544 
1545  // outer
1546  {
1547  os.beginBlock("outer");
1548 
1549  os.writeEntry("type", "inletOutlet");
1550  putUniform(os, "inletValue", deflt);
1551  putUniform(os, "value", deflt);
1552 
1553  os.endBlock();
1554  }
1555 
1556  tail_field(os, deflt, wall_bc, patches);
1557 
1558  os.endBlock(); // boundaryField
1559 
1561 }
1562 
1563 
1564 // Write a volSymmTensorField but with vectors as input.
1565 // The off-diagonals are zero.
1566 void write_symmTensorFieldV
1567 (
1568  const word& fieldName,
1569  const IjkField<vector>& fld,
1570  const symmTensor& deflt, const char *wall_bc,
1571  const PDRmeshArrays& meshIndexing,
1572  const UList<PDRpatchDef>& patches,
1573  const dimensionSet& dims, const fileName& casepath
1574 )
1575 {
1576  OFstream os(casepath / pars.timeName / fieldName);
1577  os.precision(outputPrecision);
1578 
1579  make_header(os, "", volSymmTensorField::typeName, fieldName);
1580 
1581  os.writeEntry("dimensions", dims);
1582 
1583  os << nl;
1584  os.writeKeyword("internalField")
1585  << "nonuniform List<symmTensor>" << nl
1586  << meshIndexing.nCells() << nl << token::BEGIN_LIST << nl;
1587 
1589 
1590  for (label celli=0; celli < meshIndexing.nCells(); ++celli)
1591  {
1592  const labelVector& cellIdx = meshIndexing.cellIndex[celli];
1593 
1594  if (cmptMin(cellIdx) < 0)
1595  {
1596  os << deflt << nl;
1597  continue;
1598  }
1599 
1600  const vector& vec = fld(cellIdx);
1601 
1602  val.xx() = vec.x();
1603  val.yy() = vec.y();
1604  val.zz() = vec.z();
1605 
1606  os << val << nl;
1607  }
1609 
1610  os << nl;
1611  os.beginBlock("boundaryField");
1612 
1613  // outer
1614  {
1615  os.beginBlock("outer");
1616 
1617  os.writeEntry("type", "inletOutlet");
1618  putUniform(os, "inletValue", deflt);
1619  putUniform(os, "value", deflt);
1620 
1621  os.endBlock();
1622  }
1623 
1624  tail_field(os, deflt, wall_bc, patches);
1625 
1626  os.endBlock(); // boundaryField
1627 
1629 }
1630 
1631 
1632 // ------------------------------------------------------------------------- //
1633 
1634 void write_blocked_face_list
1635 (
1636  const IjkField<vector>& face_block,
1637  const IjkField<labelVector>& face_patch,
1638  const IjkField<scalar>& obs_count, IjkField<vector>& sub_count,
1639  IjkField<Vector<direction>>& n_blocked_faces,
1640  const PDRmeshArrays& meshIndexing,
1641  const UList<PDRpatchDef>& patches,
1642  double limit_par, const fileName& casepath
1643 )
1644 {
1645  /* Create the lists of face numbers for faces that have already been defined as
1646  belonging to (inlet) patches), and others that are found to be blocked.
1647  Then write these out to set files, */
1648 
1649  const labelVector& cellDims = meshIndexing.cellDims;
1650 
1651  Map<bitSet> usedFaces;
1652 
1653  Info<< "Number of patches: " << patches.size() << nl;
1654 
1655  for (label facei=0; facei < meshIndexing.nFaces(); ++facei)
1656  {
1657  // The related i-j-k face index for the mesh face
1658  const labelVector& faceIdx = meshIndexing.faceIndex[facei];
1659 
1660  if (cmptMin(faceIdx) < 0)
1661  {
1662  continue;
1663  }
1664 
1665  const label ix = faceIdx.x();
1666  const label iy = faceIdx.y();
1667  const label iz = faceIdx.z();
1668  const direction orient = meshIndexing.faceOrient[facei];
1669 
1670  label patchId = -1;
1671  scalar val(Zero);
1672 
1673  /* A bit messy to be changing sub_count here. but there is a problem of generation
1674  of subgrid flame area Xp when the flame approaches a blocked wall. the fix is to make
1675  the normal component of "n" zero in the cells adjacent to the blocked face. That component
1676  of n is zero when that component of sub_count i.e. ns) equals count (i.e. N). */
1677  {
1678  switch (orient)
1679  {
1680  case vector::X:
1681  {
1682  // face_block is the face blockage;
1683  // face_patch is the patch number on the face (if any)
1684  val = face_block(faceIdx).x();
1685  patchId = face_patch(faceIdx).x();
1686 
1687  if
1688  (
1689  val > limit_par
1690  && iy < cellDims[vector::Y]
1691  && iz < cellDims[vector::Z]
1692  )
1693  {
1694  // n_blocked_faces:
1695  // count of x-faces blocked for this cell
1696 
1697  if (ix < cellDims[vector::X])
1698  {
1699  ++n_blocked_faces(ix,iy,iz).x();
1700  sub_count(ix,iy,iz).x() = obs_count(ix,iy,iz);
1701  }
1702 
1703  if (ix > 0)
1704  {
1705  // And the neighbouring cell
1706  ++n_blocked_faces(ix-1,iy,iz).x();
1707  sub_count(ix-1,iy,iz).x() = obs_count(ix-1,iy,iz);
1708  }
1709  }
1710  }
1711  break;
1712 
1713  case vector::Y:
1714  {
1715  val = face_block(faceIdx).y();
1716  patchId = face_patch(faceIdx).y();
1717 
1718  if
1719  (
1720  val > limit_par
1721  && iz < cellDims[vector::Z]
1722  && ix < cellDims[vector::X]
1723  )
1724  {
1725  // n_blocked_faces:
1726  // count of y-faces blocked for this cell
1727 
1728  if (iy < cellDims[vector::Y])
1729  {
1730  ++n_blocked_faces(ix,iy,iz).y();
1731  sub_count(ix,iy,iz).y() = obs_count(ix,iy,iz);
1732  }
1733 
1734  if (iy > 0)
1735  {
1736  // And the neighbouring cell
1737  ++n_blocked_faces(ix,iy-1,iz).y();
1738  sub_count(ix,iy-1,iz).y() = obs_count(ix,iy-1,iz);
1739  }
1740  }
1741  }
1742  break;
1743 
1744  case vector::Z:
1745  {
1746  val = face_block(faceIdx).z();
1747  patchId = face_patch(faceIdx).z();
1748 
1749  if
1750  (
1751  val > limit_par
1752  && ix < cellDims[vector::X]
1753  && iy < cellDims[vector::Y]
1754  )
1755  {
1756  // n_blocked_faces:
1757  // count of z-faces blocked for this cell
1758 
1759  if (iz < cellDims[vector::Z])
1760  {
1761  ++n_blocked_faces(ix,iy,iz).z();
1762  sub_count(ix,iy,iz).z() = obs_count(ix,iy,iz);
1763  }
1764 
1765  if (iz > 0)
1766  {
1767  // And the neighbouring cell
1768  ++n_blocked_faces(ix,iy,iz-1).z();
1769  sub_count(ix,iy,iz-1).z() = obs_count(ix,iy,iz-1);
1770  }
1771  }
1772  }
1773  break;
1774  }
1775 
1776  if (patchId > 0)
1777  {
1778  // If this face is on a defined patch add to list
1779  usedFaces(patchId).set(facei);
1780  }
1781  else if (val > limit_par)
1782  {
1783  // Add to blocked faces list
1784  usedFaces(PDRpatchDef::BLOCKED_FACE).set(facei);
1785  }
1786  }
1787  }
1788 
1789  // Write in time or constant dir
1790  const bool hasPolyMeshTimeDir = isDir(casepath/pars.timeName/"polyMesh");
1791 
1792  const fileName setsDir =
1793  (
1794  casepath
1795  / (hasPolyMeshTimeDir ? pars.timeName : word("constant"))
1796  / fileName("polyMesh/sets")
1797  );
1798 
1799  if (!isDir(setsDir))
1800  {
1801  mkDir(setsDir);
1802  }
1803 
1804 
1805  // Create as blockedFaces Set file for each patch, including
1806  // basic blocked faces
1807  forAll(patches, patchi)
1808  {
1809  const word& patchName = patches[patchi].patchName;
1810 
1811  OFstream os(setsDir / (patchName + "Set"));
1812 
1813  make_header(os, "polyMesh/sets", "faceSet", patchName);
1814 
1815  // Check for blocked faces
1816  const auto& fnd = usedFaces.cfind(patchi);
1817 
1818  if (fnd.good() && (*fnd).any())
1819  {
1820  os << nl << (*fnd).toc() << nl;
1821  }
1822  else
1823  {
1824  os << nl << labelList() << nl;
1825  }
1826 
1828  }
1829 
1830  // Create the PDRMeshDict, listing the blocked faces sets and their patch names
1831 
1832  {
1833  DynamicList<word> panelNames;
1834 
1835  OFstream os(casepath / "system/PDRMeshDict");
1836 
1837  make_header(os, "system", "dictionary", "PDRMeshDict");
1838 
1839  os.writeEntry("blockedCells", "blockedCellsSet");
1840  os << nl << "blockedFaces" << nl << token::BEGIN_LIST << nl;
1841 
1842  for (const PDRpatchDef& p : patches)
1843  {
1844  const word& patchName = p.patchName;
1845  const word setName = patchName + "Set";
1846 
1847  if (p.patchType == 0) // Patch
1848  {
1849  os << " " << token::BEGIN_LIST
1850  << setName << token::SPACE
1851  << patchName << token::END_LIST
1852  << nl;
1853  }
1854  else if (p.patchType > 0) // Panel
1855  {
1856  panelNames.append(setName);
1857  }
1858  }
1859 
1860  os << token::END_LIST << token::END_STATEMENT << nl << nl;
1861  os.beginBlock("coupledFaces");
1862 
1863  for (const PDRpatchDef& p : patches)
1864  {
1865  const word& patchName = p.patchName;
1866  const word setName = patchName + "Set";
1867 
1868  if (p.patchType > 0) // Panel
1869  {
1870  os.beginBlock(setName);
1871  os.writeEntry("wallPatch", word(patchName + "Wall"));
1872  os.writeEntry("cyclicMasterPatch", word(patchName + "Cyclic_half0"));
1873  os.endBlock();
1874  }
1875  }
1876  os.endBlock() << nl;
1877 
1878  os.writeEntry("defaultPatch", "blockedFaces");
1879 
1881 
1882  // Write panelList
1883  OFstream(casepath / "panelList")()
1884  << panelNames << token::END_STATEMENT << nl;
1885  }
1886 }
1887 
1888 
1889 void write_blockedCellsSet
1890 (
1891  const IjkField<scalar>& fld,
1892  const PDRmeshArrays& meshIndexing,
1893  double limit_par,
1894  const IjkField<Vector<direction>>& n_blocked_faces,
1895  const fileName& casepath,
1896  const word& listName
1897 )
1898 {
1899  if (listName.empty())
1900  {
1901  return;
1902  }
1903 
1904  // Write in time or constant dir
1905  const bool hasPolyMeshTimeDir = isDir(casepath/pars.timeName/"polyMesh");
1906 
1907  const fileName path =
1908  (
1909  casepath
1910  / (hasPolyMeshTimeDir ? pars.timeName : word("constant"))
1911  / fileName("polyMesh/sets")
1912  / listName
1913  );
1914 
1915  if (!isDir(path.path()))
1916  {
1917  mkDir(path.path());
1918  }
1919 
1920  bitSet blockedCell;
1921 
1922  for (label celli=0; celli < meshIndexing.nCells(); ++celli)
1923  {
1924  const labelVector& cellIdx = meshIndexing.cellIndex[celli];
1925 
1926  if (cmptMin(cellIdx) < 0)
1927  {
1928  continue;
1929  }
1930 
1931  if (fld(cellIdx) < limit_par)
1932  {
1933  blockedCell.set(celli);
1934  continue;
1935  }
1936 
1937  const Vector<direction>& blocked = n_blocked_faces(cellIdx);
1938 
1939  const label n_bfaces = cmptSum(blocked);
1940 
1941  label n_bpairs = 0;
1942 
1943  if (n_bfaces > 1)
1944  {
1945  for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
1946  {
1947  if (blocked[cmpt] > 1) ++n_bpairs;
1948  }
1949 
1950  #if 0
1951  // Extra debugging
1952  Info<<"block " << celli << " from "
1953  << blocked << " -> ("
1954  << n_bfaces << ' ' << n_bpairs
1955  << ')' << nl;
1956  #endif
1957  }
1958 
1959  if
1960  (
1961  n_bfaces >= pars.nFacesToBlockC
1962  || n_bpairs >= pars.nPairsToBlockC
1963  )
1964  {
1965  blockedCell.set(celli);
1966  }
1967  }
1968 
1969 
1970  OFstream os(path);
1971  make_header(os, "constant/polyMesh/sets", "cellSet", listName);
1972 
1973  if (blockedCell.any())
1974  {
1975  os << blockedCell.toc();
1976  }
1977  else
1978  {
1979  os << labelList();
1980  }
1981 
1982  os << token::END_STATEMENT << nl;
1983 
1985 }
1986 
1987 
1988 // ************************************************************************* //
Foam::PDRmeshArrays::faceIndex
List< labelVector > faceIndex
For each face, the corresponding i-j-k address.
Definition: PDRmeshArrays.H:82
ALPHAT_WALL
#define ALPHAT_WALL
Definition: PDRsetFields.H:71
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
Foam::PDRparams::nFacesToBlockC
int nFacesToBlockC
Definition: PDRparams.H:83
volFields.H
Foam::PDRblock::width
scalar width(const label i, const label j, const label k) const
Characteristic cell size at i,j,k position.
Definition: PDRblockI.H:287
NUT_WALL_FN
#define NUT_WALL_FN
Definition: PDRsetFields.H:73
Foam::dimPressure
const dimensionSet dimPressure
Foam::PDRblock::dz
scalar dz(const label k) const
Cell size in z-direction at k position.
Definition: PDRblockI.H:194
PDRsetFields.H
Preparation of fields for PDRFoam.
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
Foam::block
Creates a single block of cells from point coordinates, numbers of cells in each direction and an exp...
Definition: block.H:58
Foam::SymmTensor< scalar >
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::Vector< scalar >::Z
Definition: Vector.H:81
PDRpatchDef.H
Foam::PDRparams::timeName
word timeName
Definition: PDRparams.H:63
Foam::Vector< scalar >::Y
Definition: Vector.H:81
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::VectorSpace< Vector< label >, label, 3 >::uniform
static Vector< label > uniform(const label &s)
Return a VectorSpace with all elements = s.
Definition: VectorSpaceI.H:164
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::PDRarrays::drag_s
IjkField< symmTensor > drag_s
Tensorial drag from sharp obstacles.
Definition: PDRarrays.H:113
Foam::PDRmeshArrays::cellDims
labelVector cellDims
The cell i-j-k addressing range.
Definition: PDRmeshArrays.H:73
Foam::PDRparams::empty_lobs_fac
scalar empty_lobs_fac
Lobs in empty cell is this * cube root of cell volume.
Definition: PDRparams.H:109
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:53
Foam::PDRblock::dy
scalar dy(const label j) const
Cell size in y-direction at j position.
Definition: PDRblockI.H:182
Foam::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:186
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::dimVelocity
const dimensionSet dimVelocity
Foam::DynamicList< word >
Foam::IOobject::writeBanner
static Ostream & writeBanner(Ostream &os, bool noHint=false)
Write the standard OpenFOAM file/dictionary banner.
Definition: IOobjectWriteHeader.C:45
Foam::IOobject::writeEndDivider
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
Definition: IOobjectWriteHeader.C:109
Foam::constant::atomic::alpha
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Definition: readThermalProperties.H:212
Foam::pars
Foam::PDRparams pars
Globals for program parameters (ugly hack)
Foam::bitSet::any
bool any() const
True if any bits in this bitset are set.
Definition: bitSetI.H:460
Foam::PDRarrays::v_block
IjkField< scalar > v_block
Volume blockage.
Definition: PDRarrays.H:74
Foam::PDRparams::two_d
bool two_d
Definition: PDRparams.H:69
Foam::PDRparams::blockedCellPoros
scalar blockedCellPoros
Cells with porosity less than this are blocked.
Definition: PDRparams.H:120
MAX_VB_FOR_SIZE
#define MAX_VB_FOR_SIZE
Definition: PDRsetFields.H:83
Foam::PDRparams::deluge
bool deluge
Definition: PDRparams.H:72
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:563
MinMax.H
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: lumpedPointController.H:69
Foam::PDRparams::cb_r
scalar cb_r
Definition: PDRparams.H:94
Foam::Ostream::beginBlock
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:91
Foam::expon
const double expon
Definition: doubleFloat.H:63
Foam::dimensionSet
Dimension set for the base types.
Definition: dimensionSet.H:65
Foam::PDRparams::blockedFacePar
scalar blockedFacePar
Faces with area blockage greater than this are blocked.
Definition: PDRparams.H:123
bitSet.H
EPS_WALL_FN
#define EPS_WALL_FN
Definition: PDRsetFields.H:70
Foam::PDRparams::cd_r
scalar cd_r
Definition: PDRparams.H:97
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
IjkField.H
Foam::PDRmeshArrays::faceDims
labelVector faceDims
The face i-j-k addressing range.
Definition: PDRmeshArrays.H:76
Foam::Ostream::precision
virtual int precision() const =0
Get precision of output field.
Foam::PDRarrays::calculateAndWrite
static void calculateAndWrite(PDRarrays &arr, const PDRmeshArrays &meshIndexing, const fileName &casepath, const UList< PDRpatchDef > &patches)
Foam::PDRarrays::blockageSummary
void blockageSummary() const
Summary of the blockages.
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
DEFAULT_T
#define DEFAULT_T
Definition: PDRsetFields.H:61
K_WALL_FN
#define K_WALL_FN
Definition: PDRsetFields.H:69
OFstream.H
Foam::PDRmeshArrays::nFaces
label nFaces() const
The number of faces.
Definition: PDRmeshArrays.H:107
Foam::cmptMin
void cmptMin(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:302
Foam::PDRparams::nPairsToBlockC
int nPairsToBlockC
Definition: PDRparams.H:87
Foam::PDRparams::cb_s
scalar cb_s
Definition: PDRparams.H:95
Foam::cmptMax
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:253
Foam::PDRarrays::face_block
IjkField< vector > face_block
Definition: PDRarrays.H:93
Foam::dimTime
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:54
Foam::PDRarrays::dirn_block
IjkField< Vector< bool > > dirn_block
A total directional blockage in the cell.
Definition: PDRarrays.H:89
Foam::bitSet::toc
labelList toc() const
The indices of the on bits as a sorted labelList.
Definition: bitSet.C:527
Foam::PDRmeshArrays::nCells
label nCells() const
The number of cells.
Definition: PDRmeshArrays.H:101
Foam::PDRblock::dx
scalar dx(const label i) const
Cell size in x-direction at i position.
Definition: PDRblockI.H:170
symmTensor.H
Foam::PDRmeshArrays::faceOrient
List< direction > faceOrient
For each face, the x/y/z orientation.
Definition: PDRmeshArrays.H:85
Foam::inv
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:73
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::PDRarrays::sub_count
IjkField< vector > sub_count
Number of obstacles parallel to specified direction.
Definition: PDRarrays.H:106
Foam::PDRarrays::along_block
IjkField< vector > along_block
Definition: PDRarrays.H:97
Foam::SymmTensor::I
static const SymmTensor I
Definition: SymmTensor.H:78
Foam::Vector< scalar >::X
Definition: Vector.H:81
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::ijkAddressing::size
label size() const
Return the total i*j*k size.
Definition: ijkAddressingI.H:81
Foam::PDRarrays::obs_size
IjkField< scalar > obs_size
Obstacle size in cell.
Definition: PDRarrays.H:80
Foam::PDRarrays
Work array definitions for PDR fields.
Definition: PDRarrays.H:63
Foam::PDRparams::cd_s
scalar cd_s
Definition: PDRparams.H:98
Foam::PDRmeshArrays::cellIndex
List< labelVector > cellIndex
For each cell, the corresponding i-j-k address.
Definition: PDRmeshArrays.H:79
Foam::token::END_STATEMENT
End entry [isseparator].
Definition: token.H:122
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:75
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::MinMax::clip
const T & clip(const T &val) const
Definition: MinMaxI.H:223
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
PDRblock.H
dimensionSet.H
MIN_COUNT_FOR_SIZE
#define MIN_COUNT_FOR_SIZE
Definition: PDRsetFields.H:85
Foam::PDRpatchDef::BLOCKED_FACE
Definition: PDRpatchDef.H:60
DEFAULT_K
#define DEFAULT_K
Definition: PDRsetFields.H:59
Foam::dimViscosity
const dimensionSet dimViscosity
Foam::Ostream::endBlock
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:109
Foam::FatalError
error FatalError
Foam::PDRparams::blockedFacesWallFn
bool blockedFacesWallFn
Definition: PDRparams.H:75
Foam::PDRblock::V
scalar V(const label i, const label j, const label k) const
Cell volume at i,j,k position.
Definition: PDRblockI.H:270
DEFAULT_EP
#define DEFAULT_EP
Definition: PDRsetFields.H:66
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::dimMass
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
Foam::cmptSum
Cmpt cmptSum(const SphericalTensor< Cmpt > &st)
Return the sum of components of a SphericalTensor.
Definition: SphericalTensorI.H:164
Foam::Ostream::writeKeyword
virtual Ostream & writeKeyword(const keyType &kw)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:57
Foam::PDRblock
A single block x-y-z rectilinear mesh addressable as i,j,k with simplified creation....
Definition: PDRblock.H:149
Foam::IjkField< scalar >
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::PDRarrays::surf
IjkField< scalar > surf
Surface area in cell.
Definition: PDRarrays.H:77
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:87
Foam::PDRparams::maxCR
scalar maxCR
Upper limit on CR (CT also gets limited)
Definition: PDRparams.H:126
PDRmeshArrays.H
Foam::HashTable
A HashTable similar to std::unordered_map.
Definition: HashTable.H:105
Foam::PDRparams::yCyclic
bool yCyclic
Definition: PDRparams.H:70
Foam::PDRarrays::area_block_r
IjkField< vector > area_block_r
Summed area blockage (directional) from round obstacles.
Definition: PDRarrays.H:86
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
Foam::PDRparams::outerCombFac
scalar outerCombFac
Value for outer region.
Definition: PDRparams.H:112
Foam::SquareMatrix< scalar >
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
DEFAULT_SU
#define DEFAULT_SU
Definition: PDRsetFields.H:63
Foam::PDRparams::UPatchBc
string UPatchBc
"fixedValue;value uniform (0 0 0)"
Definition: PDRparams.H:64
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:74
Foam::PDRarrays::betai_inv1
IjkField< vector > betai_inv1
Definition: PDRarrays.H:99
Foam::IOobject::writeDivider
static Ostream & writeDivider(Ostream &os)
Write the standard file section divider.
Definition: IOobjectWriteHeader.C:99
Foam::Vector
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:62
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::token::SPACE
Space [isspace].
Definition: token.H:118
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
Foam::PDRpatchDef
Bookkeeping for patch definitions.
Definition: PDRpatchDef.H:53
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::PDRarrays::obs_count
IjkField< scalar > obs_count
Number of obstacles in cell.
Definition: PDRarrays.H:103
Foam::direction
uint8_t direction
Definition: direction.H:47
Foam::PDRarrays::grating_count
IjkField< vector > grating_count
Definition: PDRarrays.H:110
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::dimTemperature
const dimensionSet dimTemperature(0, 0, 0, 1, 0, 0, 0)
Definition: dimensionSets.H:55
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:232
Foam::token::END_LIST
End list [isseparator].
Definition: token.H:124
DEFAULT_EPS
#define DEFAULT_EPS
Definition: PDRsetFields.H:60
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
PDRparams.H
Foam::PDRparams::new_fields
bool new_fields
Definition: PDRparams.H:73
Foam::isNull
bool isNull(const T *ptr)
True if ptr is a pointer (of type T) to the nullObject.
Definition: nullObject.H:192
DynamicList.H
Foam::PDRmeshArrays
OpenFOAM/PDRblock addressing information.
Definition: PDRmeshArrays.H:65
patchId
label patchId(-1)
DEFAULT_LOBS
#define DEFAULT_LOBS
Definition: PDRsetFields.H:64
MIN_AB_FOR_SIZE
#define MIN_AB_FOR_SIZE
Definition: PDRsetFields.H:82
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::PDRarrays::area_block_s
IjkField< vector > area_block_s
Summed area blockage (directional) from sharp obstacles.
Definition: PDRarrays.H:83
SquareMatrix.H
Foam::PDRarrays::face_patch
IjkField< labelVector > face_patch
Face field for (directional) for patch Id.
Definition: PDRarrays.H:143
Foam::token::BEGIN_LIST
Begin list [isseparator].
Definition: token.H:123
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::equal
bool equal(const T &s1, const T &s2)
Compare two values for equality.
Definition: doubleFloat.H:46
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::MinMax< scalar >
DEFAULT_P
#define DEFAULT_P
Definition: PDRsetFields.H:62
PDRarrays.H
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
static constexpr direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:101
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643
y
scalar y
Definition: LISASMDCalcMethod1.H:14
Foam::PDRarrays::drag_r
IjkField< vector > drag_r
Directional drag from round obstacles.
Definition: PDRarrays.H:116
Foam::PDRparams::outer_orthog
bool outer_orthog
Definition: PDRparams.H:77
Foam::PDRarrays::block
const PDRblock & block() const
Reference to PDRblock.
Definition: PDRarrays.H:168