diff --git a/applications/utilities/preProcessing/PDRsetFields/Make/files b/applications/utilities/preProcessing/PDRsetFields/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..af1c28d4cac7137de05c3721a97c34bd8eb45ed3 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/Make/files @@ -0,0 +1,19 @@ +PDRsetFields.C + +PDRarrays.C +PDRarraysAnalyse.C +PDRarraysCalc.C +PDRmeshArrays.C +PDRparams.C +PDRpatchDef.C +PDRlegacyMeshSpec.C +PDRutilsIntersect.C +PDRutilsOverlap.C + +obstacles/PDRobstacle.C +obstacles/PDRobstacleIO.C +obstacles/PDRobstacleTypes.C +obstacles/PDRobstacleLegacyIO.C +obstacles/PDRobstacleLegacyRead.C + +EXE = $(FOAM_APPBIN)/PDRsetFields diff --git a/applications/utilities/preProcessing/PDRsetFields/Make/options b/applications/utilities/preProcessing/PDRsetFields/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..eb9d10ceb00b7cb5e2ddd3b92ef7187f44800fac --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/Make/options @@ -0,0 +1,14 @@ +EXE_INC = \ + -Iobstacles \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude \ + -I$(LIB_SRC)/surfMesh/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/mesh/blockMesh/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lfileFormats \ + -lsurfMesh \ + -lmeshTools \ + -lblockMesh diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRarrays.C b/applications/utilities/preProcessing/PDRsetFields/PDRarrays.C new file mode 100644 index 0000000000000000000000000000000000000000..f15cd52fd63f176be1bd3e113bce99c7401bf4aa --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRarrays.C @@ -0,0 +1,141 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRarrays.H" +#include "PDRblock.H" + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Smaller helper to resize matrix and assign to Zero +template<class T> +inline void resizeMatrix(SquareMatrix<T>& mat, const label n) +{ + mat.setSize(n); + mat = Zero; +} + + +// Smaller helper to resize i-j-k field and assign to uniform value, +// normally Zero +template<class T> +inline void resizeField +( + IjkField<T>& fld, + const labelVector& ijk, + const T& val = T(Zero) +) +{ + fld.resize(ijk); + fld = val; +} + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::PDRarrays::PDRarrays() +: + pdrBlock_(std::cref<PDRblock>(PDRblock::null())) +{} + + +Foam::PDRarrays::PDRarrays(const PDRblock& pdrBlock) +: + PDRarrays() +{ + reset(pdrBlock); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::PDRarrays::reset(const PDRblock& pdrBlock) +{ + pdrBlock_ = std::cref<PDRblock>(pdrBlock); + + // Resize all the major arrays, which are grouped in the structure arrp + // All the relevant dimensions are in PDRblock + + // Cell-based addressing + const labelVector cellDims = pdrBlock.sizes(); + + // Face or point-based addressing + const labelVector faceDims(cellDims + labelVector::one); + + // Max addressing dimensions for 2D arrays, with some extra space + // These will be used for any combination of x,y,z, + // so need to be dimensioned to the maximum size in both directions + const label maxDim = cmptMax(pdrBlock.sizes()) + 2; + + resizeField(v_block, cellDims); + resizeField(surf, cellDims); + + resizeField(area_block_s, cellDims); + resizeField(area_block_r, cellDims); + resizeField(dirn_block, cellDims); + + resizeField(face_block, faceDims); + + resizeField(along_block, cellDims); + + resizeField(betai_inv1, cellDims); + + resizeField(obs_count, cellDims); + resizeField(sub_count, cellDims); + resizeField(grating_count, cellDims); + + resizeField(drag_s, cellDims); + resizeField(drag_r, cellDims); + + resizeField(obs_size, cellDims); + + for (auto& list : overlap_1d) + { + list.resize(maxDim); + list = Zero; + } + + resizeMatrix(aboverlap, maxDim); + resizeMatrix(abperim, maxDim); + resizeMatrix(a_lblock, maxDim); + resizeMatrix(b_lblock, maxDim); + resizeMatrix(ac_lblock, maxDim); + resizeMatrix(bc_lblock, maxDim); + resizeMatrix(c_count, maxDim); + resizeMatrix(c_drag, maxDim); + + resizeField(face_patch, faceDims, labelVector::uniform(-1)); + resizeField(hole_in_face, faceDims); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRarrays.H b/applications/utilities/preProcessing/PDRsetFields/PDRarrays.H new file mode 100644 index 0000000000000000000000000000000000000000..908b45a37f99d4c4848e6f38da17d46f60702487 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRarrays.H @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::PDRarrays + +Description + Work array definitions for PDR fields + +SourceFiles + PDRarrays.C + PDRarraysCalc.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRarrays_H +#define PDRarrays_H + +#include "symmTensor.H" +#include "symmTensor2D.H" +#include "SquareMatrix.H" +#include "IjkField.H" +#include <functional> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class PDRblock; +class PDRmeshArrays; +class PDRobstacle; +class PDRpatchDef; + + +/*---------------------------------------------------------------------------*\ + Class PDRarrays Declaration +\*---------------------------------------------------------------------------*/ + +class PDRarrays +{ + //- Reference to PDRblock + std::reference_wrapper<const PDRblock> pdrBlock_; + +public: + + // Data Members + // Entries used for analysis and when writing fields + + //- Volume blockage + IjkField<scalar> v_block; + + //- Surface area in cell + IjkField<scalar> surf; + + //- Obstacle size in cell + IjkField<scalar> obs_size; + + //- Summed area blockage (directional) from sharp obstacles + IjkField<vector> area_block_s; + + //- Summed area blockage (directional) from round obstacles + IjkField<vector> area_block_r; + + //- A total directional blockage in the cell + IjkField<Vector<bool>> dirn_block; + + //- Face area blockage for face, + //- summed from cell centre-plane to cell centre-plane + IjkField<vector> face_block; + + //- Longitudinal area blockage from obstacles that extend all the way + //- through the cell in a given direction. + IjkField<vector> along_block; + + IjkField<vector> betai_inv1; + + //- Number of obstacles in cell. + // Can be non-integer if an obstacle does not pass all way through cell + IjkField<scalar> obs_count; + + //- Number of obstacles parallel to specified direction + IjkField<vector> sub_count; + + //- Addition to count to account for grating comprises many bars + //- (to get Lobs right) + IjkField<vector> grating_count; + + //- Tensorial drag from sharp obstacles + IjkField<symmTensor> drag_s; + + //- Directional drag from round obstacles + IjkField<vector> drag_r; + + + // Next arrays are for 2D calculations of intersection + + // One-dimensional scratch areas for cell overlaps + Vector<List<scalar>> overlap_1d; + + // In two dimensions, area of cell covered by circle + SquareMatrix<scalar> aboverlap; + + // In two dimensions, length of perimeter of circle witthin cell + SquareMatrix<scalar> abperim; + + // For offset cells, i.e. face blockage + SquareMatrix<scalar> a_lblock, b_lblock; + + // For centred cells + SquareMatrix<scalar> ac_lblock, bc_lblock; + + // The count in the cells + SquareMatrix<scalar> c_count; + + //- Cell-centred drag + SquareMatrix<symmTensor2D> c_drag; + + //- Face field for (directional) for patch Id + IjkField<labelVector> face_patch; + + //- Face field for (directional) hole in face + IjkField<Vector<bool>> hole_in_face; + + + // Constructors + + //- Construct null + PDRarrays(); + + //- Construct and reset + explicit PDRarrays(const PDRblock& pdrBlock); + + + //- Destructor + ~PDRarrays() = default; + + + // Member Functions + + //- Reset PDRblock reference, resize and zero arrays + void reset(const PDRblock& pdrBlock); + + //- Reference to PDRblock + const PDRblock& block() const + { + return pdrBlock_.get(); + } + + //- Summary of the blockages + // For diagnostics and general overview + void blockageSummary() const; + + //- Add cylinder blockage + void addCylinder(const PDRobstacle& obs); + + //- Add general (non-cylinder) blockage + void addBlockage + ( + const PDRobstacle& obs, + DynamicList<PDRpatchDef>& patches, + const int volumeSign + ); + + + static void calculateAndWrite + ( + PDRarrays& arr, + const PDRmeshArrays& meshIndexing, + const fileName& casepath, + const UList<PDRpatchDef>& patches + ); + + void calculateAndWrite + ( + const fileName& casepath, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches + ); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRarraysAnalyse.C b/applications/utilities/preProcessing/PDRsetFields/PDRarraysAnalyse.C new file mode 100644 index 0000000000000000000000000000000000000000..a72c769ab1fb379ccea8c1f5c667f9cd0dcf61f8 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRarraysAnalyse.C @@ -0,0 +1,1099 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRsetFields.H" +#include "PDRobstacle.H" +#include "PDRpatchDef.H" +#include "PDRutils.H" +#include "PDRutilsInternal.H" +#include "ListOps.H" + +#include <cstdlib> +#include <cstdio> +#include <cstring> + +#ifndef FULLDEBUG +#define NDEBUG +#endif +#include <cassert> + +using namespace Foam; +using namespace Foam::PDRutils; + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +// Cell blockage. +// +// Use simple sum, because this will eventually be divided by a notional +// number of rows to give a per-row blockage ratio +// +// b is the (fractional) area blockage. f is 1 or 0.5 to split between ends +// Thus if b isclose to 1, the obstacle is totally blocking the cell in this direction, +// and we could modify the behaviour if we wish. +inline static void add_blockage_c +( + scalar& a, + bool& blocked, + const scalar b, + const scalar f = 1.0 +) +{ + a += b * f; + if (b > pars.blockageNoCT) + { + blocked = true; + } +} + + +// Face blockage +// +// Adds more area blockage to existing amount by assuming partial overlap, +// i.e. multiplying porosities. +// +// Simple addition if the existing amount is negative, because negative +// blocks (summed first) should just cancel out part of positive blocks. +inline static void add_blockage_f +( + scalar& a, + const scalar b, + bool isHole +) +{ + if (a > 0.0) + { + // Both positive + a = 1.0 - (1.0 - a) * (1.0 - b); + } + else if (b < pars.blockedFacePar || isHole) + { + // Add until it eventually becomes positive + a += b; + } + else + { + // If one obstacle blocks face, face is blocked, regardless of + // overlap calculations, unless an input negative obstacle makes a + // hole in it + a = b; + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::PDRarrays::addCylinder(const PDRobstacle& obs) +{ + if (equal(obs.vbkge, 0)) + { + return; + } + + if (isNull(block())) + { + FatalErrorInFunction + << "No PDRblock set" << nl + << exit(FatalError); + } + + const PDRblock& pdrBlock = block(); + const PDRblock::location& xgrid = pdrBlock.grid().x(); + const PDRblock::location& ygrid = pdrBlock.grid().y(); + const PDRblock::location& zgrid = pdrBlock.grid().z(); + + scalarList& xoverlap = overlap_1d.x(); + scalarList& yoverlap = overlap_1d.y(); + scalarList& zoverlap = overlap_1d.z(); + + int cxmin, cxmax, cymin, cymax, czmin, czmax; + int cfxmin, cfxmax, cfymin, cfymax, cfzmin, cfzmax; + + scalar rad_a, rad_b; + vector area_block(Zero); + + if (obs.typeId == PDRobstacle::CYLINDER) + { + rad_a = rad_b = 0.5*obs.dia(); + } + else + { + rad_a = 0.5*(obs.wa * ::cos(obs.theta()) + obs.wb * ::sin(obs.theta())); + rad_b = 0.5*(obs.wa * ::sin(obs.theta()) + obs.wb * ::cos(obs.theta())); + } + + switch (obs.orient) + { + case vector::Z: + { + // Determine the part of the grid (potentially) covered by this obstacle. + one_d_overlap + ( + obs.x() - rad_a, obs.x() + rad_a, + pdrBlock.grid().x(), + xoverlap, &cxmin, &cxmax, &cfxmin, &cfxmax + ); assert(cxmax >=0); + + one_d_overlap + ( + obs.y() - rad_b, obs.y() + rad_b, + pdrBlock.grid().y(), + yoverlap, &cymin, &cymax, &cfymin, &cfymax + ); assert(cymax >=0); + + one_d_overlap + ( + obs.z(), obs.z() + obs.len(), + pdrBlock.grid().z(), + zoverlap, &czmin, &czmax, &cfzmin, &cfzmax + ); assert(czmax >=0); + + // The area of intersection with each 2D cell in an x-y plane. + // a corresponds to x, and b to y. + circle_overlap + ( + obs.x(), obs.y(), obs.dia(), + obs.theta(), obs.wa, obs.wb, + pdrBlock.grid().x(), cxmin, cfxmax, + pdrBlock.grid().y(), cymin, cfymax, + aboverlap, abperim, a_lblock, ac_lblock, c_count, c_drag, + b_lblock, bc_lblock + ); + + + for (label ix = cxmin; ix <= cfxmax; ix++) + { + for (label iy = cymin; iy <= cfymax; iy++) + { + for (label iz = czmin; iz <= cfzmax; iz++) + { + const scalar vol_block = aboverlap(ix,iy) * zoverlap[iz]; + v_block(ix,iy,iz) += vol_block; + surf(ix,iy,iz) += abperim(ix,iy) * zoverlap[iz] * zgrid.width(iz); + + // In the 2D case, the ends of the cylinder appear to + // be in the cell even when not, making surf and + // obs_size wrong. So leave out ends. + + if (!pars.two_d && (iz == czmin || iz == czmax)) + { + // End cells + const scalar both_ends_fac = (czmin == czmax ? 2.0 : 1.0); + + surf(ix,iy,iz) += aboverlap(ix,iy) + * xgrid.width(ix) * ygrid.width(iy) * both_ends_fac; + } + + const scalar temp = c_count(ix,iy) * zoverlap[iz]; + + obs_count(ix,iy,iz) += temp; + sub_count(ix,iy,iz).z() += temp; + + if (!pars.two_d && (iz == czmin || iz == czmax)) + { + // End faces + const scalar both_ends_fac = (czmin == czmax ? 2.0 : 1.0); + + sub_count(ix,iy,iz).z() -= temp * both_ends_fac / 2.0; + } + + // Keep the blockage and drag of round obst separate + // from the sharp for the moment because different + // blockage ratio corrections will be needed later. + // + // Only the relevant diagonal elements of drag + // are stored; other are zero. + + area_block.x() = ac_lblock(ix,iy) * zoverlap[iz]; + area_block.y() = bc_lblock(ix,iy) * zoverlap[iz]; + + // Do not want blockage and drag across the end + // except at perimeter. + if (aboverlap(ix,iy) < pars.blockedFacePar) + { + if (obs.typeId == PDRobstacle::CYLINDER) + { + drag_r(ix,iy,iz).x() += c_drag(ix,iy).xx() * zoverlap[iz] / xgrid.width(ix) / ygrid.width(iy); + drag_r(ix,iy,iz).y() += c_drag(ix,iy).yy() * zoverlap[iz] / xgrid.width(ix) / ygrid.width(iy); + + add_blockage_c(area_block_r(ix,iy,iz).x(), dirn_block(ix,iy,iz).x(), area_block.x(), 1.0); + add_blockage_c(area_block_r(ix,iy,iz).y(), dirn_block(ix,iy,iz).y(), area_block.y(), 1.0); + } + else + { + drag_s(ix,iy,iz).xx() += c_drag(ix,iy).xx() * zoverlap[iz] / xgrid.width(ix) / ygrid.width(iy); + drag_s(ix,iy,iz).yy() += c_drag(ix,iy).yy() * zoverlap[iz] / xgrid.width(ix) / ygrid.width(iy); + + add_blockage_c(area_block_s(ix,iy,iz).x(), dirn_block(ix,iy,iz).x(), area_block.x(), 1.0); + add_blockage_c(area_block_s(ix,iy,iz).y(), dirn_block(ix,iy,iz).y(), area_block.y(), 1.0); + } + } + // Here we accumulate 1/betai - 1. + betai_inv1(ix,iy,iz).x() += vol_block / (1.0 - area_block.x() + floatSMALL); + betai_inv1(ix,iy,iz).y() += vol_block / (1.0 - area_block.y() + floatSMALL); + betai_inv1(ix,iy,iz).z() += vol_block / (1.0 - aboverlap(ix,iy) + floatSMALL); + + // The off-diagonal elements of drag are stored in "drag" for BOTH round and sharp ostacles + drag_s(ix,iy,iz).xy() += c_drag(ix,iy).xy() * zoverlap[iz] / xgrid.width(ix) / ygrid.width(iy); + + add_blockage_f(face_block(ix,iy,iz).x(), a_lblock(ix,iy) * zoverlap[iz], hole_in_face(ix,iy,iz).x()); + add_blockage_f(face_block(ix,iy,iz).y(), b_lblock(ix,iy) * zoverlap[iz], hole_in_face(ix,iy,iz).y()); + } + + // Face blockage in the z direction + if (czmin == czmax) + { + // Does not span cell. Block nearest face. + add_blockage_f(face_block(ix,iy,cfzmax).z(), aboverlap(ix,iy), hole_in_face(ix,iy,cfzmax).z()); + } + else + { + // In at least two cells. + // Block first and last faces overlapped + add_blockage_f(face_block(ix,iy,czmin+1).z(), aboverlap(ix,iy), hole_in_face(ix,iy,czmin+1).z()); + if (czmax > czmin+1) + { + add_blockage_f(face_block(ix,iy,czmax).z(), aboverlap(ix,iy), hole_in_face(ix,iy,czmax).z()); + } + } + + // z_block is used to work out the blockage ratio for each + // "row" of sub-grid obstacles so this cylinder should + // not have any eeffct in cells that it completely spans. + // Hence statement commented out below and replaced by + // two lines after this loop. That longitudinal clockage + // goes into new array z_aling_block + + for (label iz = czmin+1; iz < czmax; ++iz) + { + // Internal only + along_block(ix,iy,iz).z() += aboverlap(ix,iy); + } + + // Longitudinal drag only applies at ends of cylinder. + // If cylinder spans more than 1 cell, apply half at each + // end. + + drag_s(ix,iy,czmin).zz() += aboverlap(ix,iy) * xgrid.width(ix) * ygrid.width(iy) / 2.0; + drag_s(ix,iy,czmax).zz() += aboverlap(ix,iy) * xgrid.width(ix) * ygrid.width(iy) / 2.0; + + add_blockage_c(area_block_s(ix,iy,czmin).z(), dirn_block(ix,iy,czmin).z(), aboverlap(ix,iy), 0.5); + add_blockage_c(area_block_s(ix,iy,czmax).z(), dirn_block(ix,iy,czmax).z(), aboverlap(ix,iy), 0.5); + } + } + + break; + } + + case vector::X: // orientation + { + // x-direction cylinder. a,b are y,z. + one_d_overlap + ( + obs.x(), obs.x() + obs.len(), + pdrBlock.grid().x(), + xoverlap, &cxmin, &cxmax, &cfxmin, &cfxmax + ); assert(cxmax >=0); + + one_d_overlap + ( + obs.y() - rad_a, obs.y() + rad_a, + pdrBlock.grid().y(), + yoverlap, &cymin, &cymax, &cfymin, &cfymax + ); assert(cymax >=0); + + one_d_overlap + ( + obs.z() - rad_b, obs.z() + rad_b, + pdrBlock.grid().z(), + zoverlap, &czmin, &czmax, &cfzmin, &cfzmax + ); assert(czmax >=0); + + circle_overlap + ( + obs.y(), obs.z(), obs.dia(), + obs.theta(), obs.wa, obs.wb, + pdrBlock.grid().y(), cymin, cfymax, + pdrBlock.grid().z(), czmin, cfzmax, + aboverlap, abperim, a_lblock, ac_lblock, c_count, c_drag, + b_lblock, bc_lblock + ); + + + for (label iy = cymin; iy <= cfymax; iy++) + { + for (label iz = czmin; iz <= cfzmax; iz++) + { + for (label ix = cxmin; ix <= cxmax; ix++) + { + const scalar vol_block = aboverlap(iy,iz) * xoverlap[ix]; + v_block(ix,iy,iz) += vol_block; + surf(ix,iy,iz) += abperim(iy,iz) * xoverlap[ix] * xgrid.width(ix); + + if (ix == cxmin || ix == cxmax) + { + // End cells + const scalar both_ends_fac = (cxmin == cxmax ? 2.0 : 1.0); + + surf(ix,iy,iz) += aboverlap(iy,iz) + * ygrid.width(iy) * zgrid.width(iz) * both_ends_fac; + } + + const scalar temp = c_count(iy,iz) * xoverlap[ix]; + obs_count(ix,iy,iz) += temp; + sub_count(ix,iy,iz).x() += temp; + + if (ix == cfxmin || ix == cfxmax) + { + // End faces + const scalar both_ends_fac = (cfxmin == cfxmax ? 2.0 : 1.0); + + sub_count(ix,iy,iz).x() -= temp * both_ends_fac / 2.0; + } + + area_block.y() = ac_lblock(iy,iz) * xoverlap[ix]; + area_block.z() = bc_lblock(iy,iz) * xoverlap[ix]; + + // Do not want blockage and drag across the end + // except at perimeter. + if (aboverlap(iy,iz) < pars.blockedFacePar) + { + if (obs.typeId == PDRobstacle::CYLINDER) + { + drag_r(ix,iy,iz).y() += c_drag(iy,iz).xx() * xoverlap[ix] / ygrid.width(iy) / zgrid.width(iz); + drag_r(ix,iy,iz).z() += c_drag(iy,iz).yy() * xoverlap[ix] / ygrid.width(iy) / zgrid.width(iz); + + add_blockage_c(area_block_r(ix,iy,iz).y(), dirn_block(ix,iy,iz).y(), area_block.y(), 1.0); + add_blockage_c(area_block_r(ix,iy,iz).z(), dirn_block(ix,iy,iz).z(), area_block.z(), 1.0); + } + else + { + drag_s(ix,iy,iz).yy() += c_drag(iy,iz).xx() * xoverlap[ix] / ygrid.width(iy) / zgrid.width(iz); + drag_s(ix,iy,iz).zz() += c_drag(iy,iz).yy() * xoverlap[ix] / ygrid.width(iy) / zgrid.width(iz); + + add_blockage_c(area_block_s(ix,iy,iz).y(), dirn_block(ix,iy,iz).y(), area_block.y(), 1.0); + add_blockage_c(area_block_s(ix,iy,iz).z(), dirn_block(ix,iy,iz).z(), area_block.z(), 1.0); + } + } + betai_inv1(ix,iy,iz).y() += vol_block / (1.0 - area_block.y() + floatSMALL); + betai_inv1(ix,iy,iz).z() += vol_block / (1.0 - area_block.z() + floatSMALL); + betai_inv1(ix,iy,iz).x() += vol_block / (1.0 - aboverlap(iy,iz) + floatSMALL); + + // The off-diagonal elements of drag are stored in "drag" for BOTH round and sharp ostacles + drag_s(ix,iy,iz).yz() += c_drag(iy,iz).xy() * xoverlap[ix] / ygrid.width(iy) / zgrid.width(iz); + + add_blockage_f(face_block(ix,iy,iz).y(), a_lblock(iy,iz) * xoverlap[ix], hole_in_face(ix,iy,iz).y()); + add_blockage_f(face_block(ix,iy,iz).z(), b_lblock(iy,iz) * xoverlap[ix], hole_in_face(ix,iy,iz).z()); + } + if (cxmin == cxmax) + { + // Does not span cell. Block nearest face. + add_blockage_f(face_block(cfxmax,iy,iz).x(), aboverlap(iy,iz), hole_in_face(cfxmax,iy,iz).x()); + } + else + { + // In at least two cells. + // Block first and last faces overlapped + add_blockage_f(face_block(cxmin+1,iy,iz).x(), aboverlap(iy,iz), hole_in_face(cxmin+1,iy,iz).x()); + if (cxmax > cxmin+1) + { + add_blockage_f(face_block(cxmax,iy,iz).x(), aboverlap(iy,iz), hole_in_face(cxmax,iy,iz).x()); + } + } + + for (label ix = cxmin+1; ix < cxmax; ++ix) + { + // Internal only + along_block(ix,iy,iz).x() += aboverlap(iy,iz); + } + drag_s(cxmin,iy,iz).xx() += aboverlap(iy,iz) * ygrid.width(iy) * zgrid.width(iz) / 2.0; + drag_s(cxmax,iy,iz).xx() += aboverlap(iy,iz) * ygrid.width(iy) * zgrid.width(iz) / 2.0; + + add_blockage_c(area_block_s(cxmin,iy,iz).x(), dirn_block(cxmin,iy,iz).x(), aboverlap(iy,iz), 0.5); + add_blockage_c(area_block_s(cxmax,iy,iz).x(), dirn_block(cxmax,iy,iz).x(), aboverlap(iy,iz), 0.5); + } + } + + break; + } + + case vector::Y: // orientation + { + // y-direction cylinder. a,b are z,x. + one_d_overlap + ( + obs.x() - rad_b, obs.x() + rad_b, + pdrBlock.grid().x(), + xoverlap, &cxmin, &cxmax, &cfxmin, &cfxmax + ); assert(cxmax >=0); + + one_d_overlap + ( + obs.y(), obs.y() + obs.len(), + pdrBlock.grid().y(), + yoverlap, &cymin, &cymax, &cfymin, &cfymax + ); assert(cymax >=0); + + one_d_overlap + ( + obs.z() - rad_a, obs.z() + rad_a, + pdrBlock.grid().z(), + zoverlap, &czmin, &czmax, &cfzmin, &cfzmax + ); assert(czmax >=0); + + circle_overlap + ( + obs.z(), obs.x(), obs.dia(), + obs.theta(), obs.wa, obs.wb, + pdrBlock.grid().z(), czmin, cfzmax, + pdrBlock.grid().x(), cxmin, cfxmax, + aboverlap, abperim, a_lblock, ac_lblock, c_count, c_drag, + b_lblock, bc_lblock + ); + + + for (label iz = czmin; iz <= cfzmax; iz++) + { + for (label ix = cxmin; ix <= cfxmax; ix++) + { + for (label iy = cymin; iy <= cymax; iy++) + { + const scalar vol_block = aboverlap(iz,ix) * yoverlap[iy]; + v_block(ix,iy,iz) += vol_block; + surf(ix,iy,iz) += abperim(iz,ix) * yoverlap[iy] * ygrid.width(iy); + + if (iy == cymin || iy == cymax) + { + // End cells + const scalar both_ends_fac = (cymin == cymax ? 2.0 : 1.0); + + surf(ix,iy,iz) += aboverlap(iz,ix) + * zgrid.width(iz) * xgrid.width(ix) * both_ends_fac; + } + + const scalar temp = c_count(iz,ix) * yoverlap[iy]; + + obs_count(ix,iy,iz) += temp; + sub_count(ix,iy,iz).y() += temp; + + if (iy == cfymin || iy == cfymax) + { + // End faces + const scalar both_ends_fac = (cfymin == cfymax ? 2.0 : 1.0); + + sub_count(ix,iy,iz).y() -= temp * both_ends_fac / 2.0; + } + + area_block.z() = ac_lblock(iz,ix) * yoverlap[iy]; + area_block.x() = bc_lblock(iz,ix) * yoverlap[iy]; + + // Do not want blockage and drag across the end + // except at perimeter. + if (aboverlap(iz,ix) < pars.blockedFacePar) + { + if (obs.typeId == PDRobstacle::CYLINDER) + { + drag_r(ix,iy,iz).z() += c_drag(iz,ix).xx() * yoverlap[iy] / zgrid.width(iz) / xgrid.width(ix); + drag_r(ix,iy,iz).x() += c_drag(iz,ix).yy() * yoverlap[iy] / zgrid.width(iz) / xgrid.width(ix); + + add_blockage_c(area_block_r(ix,iy,iz).z(), dirn_block(ix,iy,iz).z(), area_block.z(), 1.0); + add_blockage_c(area_block_r(ix,iy,iz).x(), dirn_block(ix,iy,iz).x(), area_block.x(), 1.0); + } + else + { + drag_s(ix,iy,iz).zz() += c_drag(iz,ix).xx() * yoverlap[iy] / zgrid.width(iz) / xgrid.width(ix); + drag_s(ix,iy,iz).xx() += c_drag(iz,ix).yy() * yoverlap[iy] / zgrid.width(iz) / xgrid.width(ix); + + add_blockage_c(area_block_s(ix,iy,iz).z(), dirn_block(ix,iy,iz).z(), area_block.z(), 1.0); + add_blockage_c(area_block_s(ix,iy,iz).x(), dirn_block(ix,iy,iz).x(), area_block.x(), 1.0); + } + } + betai_inv1(ix,iy,iz).z() += vol_block / (1.0 - area_block.z() + floatSMALL); + betai_inv1(ix,iy,iz).x() += vol_block / (1.0 - area_block.x() + floatSMALL); + betai_inv1(ix,iy,iz).y() += vol_block / (1.0 - aboverlap(iz,ix) + floatSMALL); + + // The off-diagonal elements of drag are stored in "drag" for BOTH round and sharp obstacles + drag_s(ix,iy,iz).xz() += c_drag(iz,ix).xy() * yoverlap[iy] / zgrid.width(iz) / xgrid.width(ix); + + add_blockage_f(face_block(ix,iy,iz).z(), a_lblock(iz,ix) * yoverlap[iy], hole_in_face(ix,iy,iz).z()); + add_blockage_f(face_block(ix,iy,iz).x(), b_lblock(iz,ix) * yoverlap[iy], hole_in_face(ix,iy,iz).x()); + } + if (cymin == cymax) + { + // Does not span cell. Block nearest face. + add_blockage_f(face_block(ix,cfymax,iz).y(), aboverlap(iz,ix), hole_in_face(ix,cfymax,iz).y()); + } + else + { + // In at least two cells. + // Block first and last faces overlapped + add_blockage_f(face_block(ix,cymin+1,iz).y(), aboverlap(iz,ix), hole_in_face(ix,cymin+1,iz).y()); + if (cymax > cymin+1) + { + add_blockage_f(face_block(ix,cymax,iz).y(), aboverlap(iz,ix), hole_in_face(ix,cymax,iz).y()); + } + } + + for (label iy = cymin+1; iy < cymax; ++iy) + { + // Internal only + along_block(ix,iy,iz).y() += aboverlap(iz,ix); + } + + drag_s(ix,cymin,iz).yy() += aboverlap(iz,ix) * zgrid.width(iz) * xgrid.width(ix) / 2.0; + drag_s(ix,cymax,iz).yy() += aboverlap(iz,ix) * zgrid.width(iz) * xgrid.width(ix) / 2.0; + + add_blockage_c(area_block_s(ix,cymin,iz).y(), dirn_block(ix,cymin,iz).y(), aboverlap(iz,ix), 0.5); + add_blockage_c(area_block_s(ix,cymax,iz).y(), dirn_block(ix,cymax,iz).y(), aboverlap(iz,ix), 0.5); + } + } + + break; + } + + default: // orientation + { + Info<< "Unexpected orientation " << int(obs.orient) << nl; + break; + } + } +} + + +void Foam::PDRarrays::addBlockage +( + const PDRobstacle& obs, + DynamicList<PDRpatchDef>& patches, + const int volumeSign +) +{ + // The volumeSign indicates whether this pass is for negative or positive + // obstacles. Both if 0. + if + ( + equal(obs.vbkge, 0) + || (volumeSign < 0 && obs.vbkge >= 0) + || (volumeSign > 0 && obs.vbkge < 0) + ) + { + return; + } + + if (isNull(block())) + { + FatalErrorInFunction + << "No PDRblock set" << nl + << exit(FatalError); + } + + const PDRblock& pdrBlock = block(); + const PDRblock::location& xgrid = pdrBlock.grid().x(); + const PDRblock::location& ygrid = pdrBlock.grid().y(); + const PDRblock::location& zgrid = pdrBlock.grid().z(); + + scalarList& xoverlap = overlap_1d.x(); + scalarList& yoverlap = overlap_1d.y(); + scalarList& zoverlap = overlap_1d.z(); + + + // 0 will be used later for faces found to be blocked. + // 2 is used for wall-function faces. + label patchNum = PDRpatchDef::LAST_PREDEFINED; + + // Only the part of the panel that covers full cell faces will be used + // so later should keep the panel in the list plus a hole (-ve obstacle) for + // part that will become blowoff b.c. + + int indir = 0; + + // Panel or patch + const bool isPatch = + ( + (obs.typeId == PDRobstacle::LOUVRE_BLOWOFF && obs.blowoff_type > 0) + || (obs.typeId == PDRobstacle::RECT_PATCH) + ); + + if (isPatch) + { + const auto& identifier = obs.identifier; + + const auto spc = identifier.find_first_of(" \t\n\v\f\r"); + + const word patchName = word::validate(identifier.substr(0, spc)); + + patchNum = ListOps::find + ( + patches, + [=](const PDRpatchDef& p){ return patchName == p.patchName; }, + 1 // skip 0 (blocked face) + ); + + if (patchNum < 1) + { + // The patch name was not already in the list + patchNum = patches.size(); + + patches.append(PDRpatchDef(patchName)); + } + + + PDRpatchDef& p = patches[patchNum]; + + if (obs.typeId == PDRobstacle::RECT_PATCH) + { + indir = obs.inlet_dirn; + p.patchType = 0; + } + else + { + p.patchType = obs.blowoff_type; + p.blowoffPress = obs.blowoff_press; + p.blowoffTime = obs.blowoff_time; + if (obs.span.x() < 1e-5) + { + indir = 1; + } + else if (obs.span.y() < 1e-5) + { + indir = 2; + } + else if (obs.span.z() < 1e-5) + { + indir = 3; + } + else + { + FatalErrorInFunction + << "Blowoff panel should have zero thickness" << nl + << exit(FatalError); + } + } + } + + int cxmin, cxmax, cfxmin, cfxmax; + one_d_overlap + ( + obs.x(), obs.x() + obs.span.x(), + pdrBlock.grid().x(), + xoverlap, &cxmin, &cxmax, &cfxmin, &cfxmax + ); assert(cxmax >=0); + + int cymin, cymax, cfymin, cfymax; + one_d_overlap + ( + obs.y(), obs.y() + obs.span.y(), + pdrBlock.grid().y(), + yoverlap, &cymin, &cymax, &cfymin, &cfymax + ); assert(cymax >=0); + + int czmin, czmax, cfzmin, cfzmax; + one_d_overlap + ( + obs.z(), obs.z() + obs.span.z(), + pdrBlock.grid().z(), + zoverlap, &czmin, &czmax, &cfzmin, &cfzmax + ); assert(czmax >=0); + + two_d_overlap(xoverlap, cxmin, cxmax, yoverlap, cymin, cymax, aboverlap); + + + const scalar vbkge = obs.vbkge; + const scalar xbkge = obs.xbkge; + const scalar ybkge = obs.ybkge; + const scalar zbkge = obs.zbkge; + + // Compensate for double-counting of drag if two edges in same cell + const vector double_f + ( + ((cxmin == cxmax) ? 0.5 : 1.0), + ((cymin == cymax) ? 0.5 : 1.0), + ((czmin == czmax) ? 0.5 : 1.0) + ); + + for (label ix = cxmin; ix <= cfxmax; ix++) + { + const scalar xov = xoverlap[ix]; + + scalar area, cell_area, temp; + + for (label iy = cymin; iy <= cfymax; iy++) + { + const scalar yov = yoverlap[iy]; + + for (label iz = czmin; iz <= cfzmax; iz++) + { + const scalar zov = zoverlap[iz]; + + if + ( + isPatch + && + ( + (indir == -1 && ix == cfxmin) + || (indir == 1 && ix == cfxmax) + || (indir == -2 && iy == cfymin) + || (indir == 2 && iy == cfymax) + || (indir == -3 && iz == cfzmin) + || (indir == 3 && iz == cfzmax) + ) + ) + { + /* Type RECT_PATCH (16) exists to set all faces it covers to be in a particular patch + usually an inlet or outlet. + ?? If the face not on a cell boundary, this will move it to the lower-cordinate + face of the relevant cell. It should be at the face of teh volume blocked by + the obstacle. But, if that is not at a cell boundary, the obstacle will be + putting blockage in front of teh vent, so we should be checking that it is + at a cell boundary. */ + + switch (indir) // Face orientation + { + // X + case -1: + case 1: + if (yov * zov > pars.blockedFacePar) + { + face_patch(ix,iy,iz).x() = patchNum; + } + break; + + // Y + case -2: + case 2: + if (zov * xov > pars.blockedFacePar) + { + face_patch(ix,iy,iz).y() = patchNum; + } + break; + + // Z + case -3: + case 3: + if (xov * yov > pars.blockedFacePar) + { + face_patch(ix,iy,iz).z() = patchNum; + } + break; + } + } // End of code for patch + + + const scalar vol_block = aboverlap(ix,iy) * zov * vbkge; + v_block(ix,iy,iz) += vol_block; + + // These are the face blockages + if ((ix > cxmin && ix <= cxmax) || (cxmin == cxmax && ix == cfxmax)) + { + temp = yov * zov * xbkge; + + // Has -ve volumeSign only when processing user-defined + // -ve blocks + if (volumeSign < 0) + { + hole_in_face(ix,iy,iz).x() = true; + } + add_blockage_f(face_block(ix,iy,iz).x(), temp, hole_in_face(ix,iy,iz).x()); + if (temp > pars.blockedFacePar && ! hole_in_face(ix,iy,iz).x() && !isPatch) + { + // Put faces of block in wall patch + face_patch(ix,iy,iz).x() = PDRpatchDef::WALL_PATCH; + } + } + if ((iy > cymin && iy <= cymax) || (cymin == cymax && iy == cfymax)) + { + temp = zov * xov * ybkge; + if (volumeSign < 0) + { + hole_in_face(ix,iy,iz).y() = true; + } + add_blockage_f(face_block(ix,iy,iz).y(), temp, hole_in_face(ix,iy,iz).y()); + if (temp > pars.blockedFacePar && ! hole_in_face(ix,iy,iz).y() && !isPatch) + { + face_patch(ix,iy,iz).y() = PDRpatchDef::WALL_PATCH; + } + } + if ((iz > czmin && iz <= czmax) || (czmin == czmax && iz == cfzmax)) + { + temp = xov * yov * zbkge; + if (volumeSign < 0) + { + hole_in_face(ix,iy,iz).z() = true; + } + add_blockage_f(face_block(ix,iy,iz).z(), temp, hole_in_face(ix,iy,iz).z()); + if (temp > pars.blockedFacePar && ! hole_in_face(ix,iy,iz).z() && !isPatch) + { + face_patch(ix,iy,iz).z() = PDRpatchDef::WALL_PATCH; + } + } + + // These are the interior blockages + /* As for cylinders, blockage that extends longitudinally all the way through the cell + should not be in x_block etc., but it does go into new arrays along_block etc. */ + area = yov * zov * xbkge; // Note this is fraction of cell c-s area + if (ix < cxmin || ix > cxmax) + {} + else if (ix > cxmin && ix < cxmax && xbkge >= 1.0) + { + along_block(ix,iy,iz).x() += area; + betai_inv1(ix,iy,iz).x() += vol_block / (1.0 - area + floatSMALL); + } + else if (ix == cxmin || ix == cxmax) + { + // If front and back of the obstacle are not in the + // same cell, put half in each + const scalar double_f = (cxmin == cxmax ? 1.0 : 0.5); + + add_blockage_c(area_block_s(ix,iy,iz).x(), dirn_block(ix,iy,iz).x(), area, double_f); + cell_area = (ygrid.width(iy) * zgrid.width(iz)); + surf(ix,iy,iz) += double_f * area * cell_area; + betai_inv1(ix,iy,iz).x() += vol_block / (1.0 - area + floatSMALL); + + // To get Lobs right for a grating, allow for the fact that it is series of bars by having additional count + if (obs.typeId == PDRobstacle::GRATING && obs.orient == vector::X) + { + // * cell_area to make dimensional, then / std::sqrt(cell_area) to get width + temp = area * std::sqrt(cell_area) / obs.slat_width - 1.0; + if (temp > 0.0) { grating_count(ix,iy,iz).x() += temp; } + } + } + + /* As for cylinders, blockage that extends longitudinally all the way through the cell + should not be in x_block etc., but it does go into new arrays along_block etc. */ + area = zov * xov * ybkge; + if (iy < cymin || iy > cymax) + {} + else if (iy > cymin && iy < cymax && ybkge >= 1.0) + { + along_block(ix,iy,iz).y() += area; + betai_inv1(ix,iy,iz).y() += vol_block / (1.0 - area + floatSMALL); + } + else if (iy == cymin || iy == cymax) + { + // If front and back of the obstacle are not in the + // same cell, put half in each + const scalar double_f = (cymin == cymax ? 1.0 : 0.5); + + add_blockage_c(area_block_s(ix,iy,iz).y(), dirn_block(ix,iy,iz).y(), area, double_f); + cell_area = (zgrid.width(iz) * xgrid.width(ix)); + surf(ix,iy,iz) += double_f * area * cell_area; + betai_inv1(ix,iy,iz).y() += vol_block / (1.0 - area + floatSMALL); + + if (obs.typeId == PDRobstacle::GRATING && obs.orient == vector::Y) + { + // * cell_area to make dimensional, then / std::sqrt(cell_area) to get width + temp = area * std::sqrt(cell_area) / obs.slat_width - 1.0; + if (temp > 0.0) { grating_count(ix,iy,iz).y() += temp; } + } + } + + area = xov * yov * zbkge; + if (iz < czmin || iz > czmax) + {} + else if (iz > czmin && iz < czmax && zbkge >= 1.0) + { + along_block(ix,iy,iz).z() += area; + betai_inv1(ix,iy,iz).z() += vol_block / (1.0 - area + floatSMALL); + } + else if (iz == czmin || iz == czmax) + { + // If front and back of the obstacle are not in the + // same cell, put half in each + const scalar double_f = (czmin == czmax ? 1.0 : 0.5); + + add_blockage_c(area_block_s(ix,iy,iz).z(), dirn_block(ix,iy,iz).z(), area, double_f); + cell_area = (xgrid.width(ix) * ygrid.width(iy)); + surf(ix,iy,iz) += double_f * area * cell_area; + betai_inv1(ix,iy,iz).z() += vol_block / (1.0 - area + floatSMALL); + + if (obs.typeId == PDRobstacle::GRATING && obs.orient == vector::Z) + { + // * cell_area to make dimensional, then / std::sqrt(cell_area) to get width + temp = area * std::sqrt(cell_area) / obs.slat_width - 1.0; + if (temp > 0.0) { grating_count(ix,iy,iz).z() += temp; } + } + } + } + } + } + + if (obs.typeId == PDRobstacle::RECT_PATCH) + { + // Was only needed to set face_patch values + return; + } + + + /* A narrow obstacle completely crossing the cell adds 1 to the count for the transverse directions + If all four edges are not in the relevant cell, we take 1/4 for each edge that is in. + If it does not totally cross the cell, then the count is reduced proportionately + If it is porous, then the count is reduced proportionately. + ?? Should it be? At least this is consistent with effect going smoothly to zero as porosity approaches 1 ?? + + Note that more than 1 can be added for one obstacle, if sides and ends are in the cell. + + We do all the x-aligned edges first, both for y-blockage and z-blockage. */ + + /* Intersection obstacles can have more edges than the intersecting obstacles that + generated them, so not good to incorporate these in N and drag. */ + + for (label ix = cxmin; ix <= cxmax; ix++) + { + // Factor of 0.25 because 4 edges to be done + scalar olap25 = 0.25 * xoverlap[ix]; + + const scalar temp = + ((pars.noIntersectN && vbkge < 0.334) ? 0 : (olap25 * vbkge)); + + obs_count(ix,cymin,czmin) += temp; + obs_count(ix,cymax,czmin) += temp; + obs_count(ix,cymin,czmax) += temp; + obs_count(ix,cymax,czmax) += temp; + + sub_count(ix,cymin,czmin).x() += temp; + sub_count(ix,cymax,czmin).x() += temp; + sub_count(ix,cymin,czmax).x() += temp; + sub_count(ix,cymax,czmax).x() += temp; + + // The 0.25 becomes 0.5 to allow for front/back faces in drag direction + olap25 *= 2.0; + + drag_s(ix,cymin,czmin).yy() += zoverlap[czmin] * double_f.z() * olap25 * ybkge / ygrid.width(cymin); + drag_s(ix,cymax,czmin).yy() += zoverlap[czmin] * double_f.z() * olap25 * ybkge / ygrid.width(cymax); + drag_s(ix,cymin,czmax).yy() += zoverlap[czmax] * double_f.z() * olap25 * ybkge / ygrid.width(cymin); + drag_s(ix,cymax,czmax).yy() += zoverlap[czmax] * double_f.z() * olap25 * ybkge / ygrid.width(cymax); + + drag_s(ix,cymin,czmin).zz() += yoverlap[cymin] * double_f.y() * olap25 * zbkge / zgrid.width(czmin); + drag_s(ix,cymax,czmin).zz() += yoverlap[cymax] * double_f.y() * olap25 * zbkge / zgrid.width(czmin); + drag_s(ix,cymin,czmax).zz() += yoverlap[cymin] * double_f.y() * olap25 * zbkge / zgrid.width(czmax); + drag_s(ix,cymax,czmax).zz() += yoverlap[cymax] * double_f.y() * olap25 * zbkge / zgrid.width(czmax); + + // Porous obstacles do not only have drag at edges + if (xbkge < 1.0) + { + for (label iy = cymin+1; iy < cymax; iy++) + { + for (label iz = czmin+1; iz < czmax; iz++) + { + // Internal only + drag_s(ix,iy,iz).xx() = xbkge / xgrid.width(ix); + } + } + } + } + + for (label iy = cymin; iy <= cymax; iy++) + { + scalar olap25 = 0.25 * yoverlap[iy]; + const scalar temp = + ((pars.noIntersectN && vbkge < 0.334) ? 0 : (olap25 * vbkge)); + + obs_count(cxmin,iy,czmin) += temp; + obs_count(cxmax,iy,czmin) += temp; + obs_count(cxmin,iy,czmax) += temp; + obs_count(cxmax,iy,czmax) += temp; + + sub_count(cxmin,iy,czmin).y() += temp; + sub_count(cxmax,iy,czmin).y() += temp; + sub_count(cxmin,iy,czmax).y() += temp; + sub_count(cxmax,iy,czmax).y() += temp; + + olap25 *= 2.0; + + if (iy > cymin && iy < cymax) // Avoid re-doing corners already done above + { + drag_s(cxmin,iy,czmin).zz() += xoverlap[cxmin] * double_f.x() * olap25 * zbkge / zgrid.width(czmin); + drag_s(cxmax,iy,czmin).zz() += xoverlap[cxmin] * double_f.x() * olap25 * zbkge / zgrid.width(czmin); + drag_s(cxmin,iy,czmax).zz() += xoverlap[cxmax] * double_f.x() * olap25 * zbkge / zgrid.width(czmax); + drag_s(cxmax,iy,czmax).zz() += xoverlap[cxmax] * double_f.x() * olap25 * zbkge / zgrid.width(czmax); + } + drag_s(cxmin,iy,czmin).xx() += zoverlap[czmin] * double_f.z() * olap25 * xbkge / xgrid.width(cxmin); + drag_s(cxmax,iy,czmin).xx() += zoverlap[czmax] * double_f.z() * olap25 * xbkge / xgrid.width(cxmax); + drag_s(cxmin,iy,czmax).xx() += zoverlap[czmin] * double_f.z() * olap25 * xbkge / xgrid.width(cxmin); + drag_s(cxmax,iy,czmax).xx() += zoverlap[czmax] * double_f.z() * olap25 * xbkge / xgrid.width(cxmax); + + // Porous obstacles do not only have drag at edges + if (ybkge < 1.0) + { + for (label iz = czmin+1; iz < czmax; iz++) + { + for (label ix = cxmin+1; ix < cxmax; ix++) + { + // Internal only + drag_s(ix,iy,iz).yy() = ybkge / ygrid.width(iy); + } + } + } + } + + for (label iz = czmin; iz <= czmax; iz++) + { + scalar olap25 = 0.25 * zoverlap[iz]; + const scalar temp = + ((pars.noIntersectN && vbkge < 0.334) ? 0 : (olap25 * vbkge)); + + obs_count(cxmin,cymin,iz) += temp; + obs_count(cxmin,cymax,iz) += temp; + obs_count(cxmax,cymin,iz) += temp; + obs_count(cxmax,cymax,iz) += temp; + + sub_count(cxmin,cymin,iz).z() += temp; + sub_count(cxmin,cymax,iz).z() += temp; + sub_count(cxmax,cymin,iz).z() += temp; + sub_count(cxmax,cymax,iz).z() += temp; + + olap25 *= 2.0; + + if (iz > czmin && iz < czmax) // Avoid re-doing corners already done above + { + drag_s(cxmin,cymin,iz).xx() += yoverlap[cymin] * double_f.y() * olap25 * xbkge / xgrid.width(cxmin); + drag_s(cxmax,cymin,iz).xx() += yoverlap[cymin] * double_f.y() * olap25 * xbkge / xgrid.width(cxmax); + drag_s(cxmin,cymax,iz).xx() += yoverlap[cymax] * double_f.y() * olap25 * xbkge / xgrid.width(cxmin); + drag_s(cxmax,cymax,iz).xx() += yoverlap[cymax] * double_f.y() * olap25 * xbkge / xgrid.width(cxmax); + + drag_s(cxmin,cymin,iz).yy() += xoverlap[cxmin] * double_f.x() * olap25 * ybkge / ygrid.width(cymin); + drag_s(cxmax,cymin,iz).yy() += xoverlap[cxmax] * double_f.x() * olap25 * ybkge / ygrid.width(cymin); + drag_s(cxmin,cymax,iz).yy() += xoverlap[cxmin] * double_f.x() * olap25 * ybkge / ygrid.width(cymax); + drag_s(cxmax,cymax,iz).yy() += xoverlap[cxmax] * double_f.x() * olap25 * ybkge / ygrid.width(cymax); + } + + // Porous obstacles do not only have drag at edges + if (zbkge < 1.0) + { + for (label ix = cxmin+1; ix < cxmax; ix++) + { + for (label iy = cymin+1; iy < cymax; iy++) + { + // Internal only + drag_s(ix,iy,iz).zz() = zbkge / zgrid.width(iz); + } + } + } + } +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRarraysCalc.C b/applications/utilities/preProcessing/PDRsetFields/PDRarraysCalc.C new file mode 100644 index 0000000000000000000000000000000000000000..e74ff71d7d688134fab1f98c7d9563609f56bfdd --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRarraysCalc.C @@ -0,0 +1,1984 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRarrays.H" +#include "PDRblock.H" +#include "PDRpatchDef.H" +#include "PDRmeshArrays.H" +#include "PDRparams.H" + +#include "PDRsetFields.H" + +#include "bitSet.H" +#include "DynamicList.H" +#include "dimensionSet.H" +#include "symmTensor.H" +#include "SquareMatrix.H" +#include "IjkField.H" +#include "MinMax.H" +#include "volFields.H" +#include "OFstream.H" +#include "OSspecific.H" + +#ifndef FULLDEBUG +#define NDEBUG +#endif +#include <cassert> + +using namespace Foam; + +HashTable<string> fieldNotes +({ + { "Lobs", "" }, + { "Aw", "surface area per unit volume" }, + { "CR", "" }, + { "CT", "" }, + { "N", "" }, + { "ns", "" }, + { "Nv", "" }, + { "nsv", "" }, + { "Bv", "area blockage" }, + { "B", "area blockage" }, + { "betai", "" }, + { "Blong", "longitudinal blockage" }, + { "Ep", "1/Lobs" }, +}); + + +// calc_fields + + +// Local Functions +/* +// calc_drag_etc +make_header +tail_field +write_scalarField +write_uniformField +write_symmTensorField +write_pU_fields +write_blocked_face_list +write_blockedCellsSet +*/ + +// Somewhat similar to what the C-fprintf would have had +static constexpr unsigned outputPrecision = 8; + +void calc_drag_etc +( + double brs, double brr, bool blocked, + double surr_br, double surr_dr, + scalar* drags_p, scalar* dragr_p, + double count, + scalar* cbdi_p, + double cell_vol +); + + +void write_scalarField +( + const word& fieldName, const IjkField<scalar>& fld, + const scalar& deflt, const scalarMinMax& limits, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +); + +void write_uniformField +( + const word& fieldName, const scalar& deflt, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +); + +void write_pU_fields +( + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const fileName& casepath +); + +void write_symmTensorField +( + const word& fieldName, const IjkField<symmTensor>& fld, + const symmTensor& deflt, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +); + +void write_symmTensorFieldV +( + const word& fieldName, const IjkField<vector>& fld, + const symmTensor& deflt, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +); + +void write_blocked_face_list +( + const IjkField<vector>& face_block, + const IjkField<labelVector>& face_patch, + const IjkField<scalar>& obs_count, + IjkField<vector>& sub_count, + IjkField<Vector<direction>>& n_blocked_faces, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + double limit_par, const fileName& casepath +); + +void write_blockedCellsSet +( + const IjkField<scalar>& fld, + const PDRmeshArrays& meshIndexing, double limit_par, + const IjkField<Vector<direction>>& n_blocked_faces, + const fileName& casepath, + const word& listName +); + + +// The average values of surrounding an array position +static inline scalar averageSurrounding +( + const SquareMatrix<scalar>& mat, + const label i, + const label j +) +{ + return + ( + mat(i,j) + mat(i,j+1) + mat(i,j+2) + + mat(i+1,j) /* centre */ + mat(i+1,j+2) + + mat(i+2,j) + mat(i+2,j+1) + mat(i+2,j+2) + ) / 8.0; // Average +} + + +// Helper +template<class Type> +static inline Ostream& putUniform(Ostream& os, const word& key, const Type& val) +{ + os.writeKeyword(key) << "uniform " << val << token::END_STATEMENT << nl; + return os; +} + + +static void make_header +( + Ostream& os, + const fileName& location, + const word& clsName, + const word& object +) +{ + string note = fieldNotes(object); + + IOobject::writeBanner(os); + + os << "FoamFile\n{\n" + << " version 2.0;\n" + << " format ascii;\n" + << " class " << clsName << ";\n"; + + if (!note.empty()) + { + os << " note " << note << ";\n"; + } + + if (!location.empty()) + { + os << " location " << location << ";\n"; + } + + os << " object " << object << ";\n" + << "}\n"; + + IOobject::writeDivider(os) << nl; +} + + +void Foam::PDRarrays::calculateAndWrite +( + PDRarrays& arr, + const PDRmeshArrays& meshIndexing, + const fileName& casepath, + const UList<PDRpatchDef>& patches +) +{ + if (isNull(arr.block())) + { + FatalErrorInFunction + << "No PDRblock set" << nl + << exit(FatalError); + } + + const PDRblock& pdrBlock = arr.block(); + + const labelVector& cellDims = meshIndexing.cellDims; + const labelVector& faceDims = meshIndexing.faceDims; + + const int xdim = faceDims.x(); + const int ydim = faceDims.y(); + const int zdim = faceDims.z(); + const scalar maxCT = pars.maxCR * pars.cb_r; + + + // Later used to store the total effective blockage ratio per cell/direction + IjkField<symmTensor>& drag_s = arr.drag_s; + + IjkField<vector>& drag_r = arr.drag_r; + + const IjkField<vector>& area_block_s = arr.area_block_s; + const IjkField<vector>& area_block_r = arr.area_block_r; + const IjkField<Vector<bool>>& dirn_block = arr.dirn_block; + + const IjkField<vector>& betai_inv1 = arr.betai_inv1; + + IjkField<scalar>& obs_count = arr.obs_count; + IjkField<vector>& sub_count = arr.sub_count; // ns. Later used to hold longitudinal blockage + const IjkField<vector>& grating_count = arr.grating_count; + + IjkField<scalar>& v_block = arr.v_block; + IjkField<scalar>& surf = arr.surf; + + // Lobs. Later used for initial Ep + IjkField<scalar>& obs_size = arr.obs_size; + + Info<< "Calculating fields" << nl; + + // Local scratch arrays + + // The turbulance generation field CT. + // Later used to to hold the beta_i in tensor form + IjkField<vector> cbdi(cellDims, Zero); + + + // For 2D addressing it is convenient to just use the max dimension + // and avoid resizing when handling each direction. + + // Dimension of the cells and a layer of surrounding halo cells + const labelVector surrDims = (faceDims + labelVector::uniform(2)); + + // Max addressing dimensions + const label maxDim = cmptMax(surrDims); + + // Blockage-ratio correction to the drag + // + // neiBlock: + // 2-D for averaging the blockage ratio of neighbouring cells. + // It extends one cell outside the domain in each direction, + // so the indices are offset by 1. + // neiDrag: + // 2-D array for averaging the drag ratio of neighbouring cells + + SquareMatrix<scalar> neiBlock(maxDim, Zero); + SquareMatrix<scalar> neiDrag(maxDim, Zero); + + // X blockage, drag + + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + for (label iz = 0; iz <= zdim; ++iz) + { + const label izz = + (iz == 0 ? 0 : iz == zdim ? zdim - 2 : iz - 1); + + neiBlock(iy+1, iz) = + ( + area_block_s(ix,iy,izz).x() + + area_block_r(ix,iy,izz).x() + ); + + neiDrag(iy+1, iz) = + ( + drag_s(ix,iy,izz).xx() * pars.cd_s + + drag_r(ix,iy,izz).x() * pars.cd_r + ); + } + } + for (label iz = 0; iz < surrDims.z(); ++iz) + { + if (pars.yCyclic) + { + // Cyclic in y + neiBlock(0, iz) = neiBlock(cellDims.y(), iz); + neiDrag(0, iz) = neiDrag(cellDims.y(), iz); + neiBlock(ydim, iz) = neiBlock(1, iz); + neiDrag(ydim, iz) = neiDrag(1, iz); + } + else + { + neiBlock(0, iz) = neiBlock(1, iz); + neiDrag(0, iz) = neiDrag(1, iz); + neiBlock(ydim, iz) = neiBlock(cellDims.y(), iz); + neiDrag(ydim, iz) = neiDrag(cellDims.y(), iz); + } + } + + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + const scalar cell_vol = pdrBlock.V(ix,iy,iz); + + const scalar surr_br = averageSurrounding(neiBlock, iy, iz); + const scalar surr_dr = averageSurrounding(neiDrag, iy, iz); + + calc_drag_etc + ( + area_block_s(ix,iy,iz).x(), + area_block_r(ix,iy,iz).x(), + dirn_block(ix,iy,iz).x(), + surr_br, surr_dr, + &(drag_s(ix,iy,iz).xx()), + &(drag_r(ix,iy,iz).x()), + obs_count(ix,iy,iz), + &(cbdi(ix,iy,iz).x()), + cell_vol + ); + } + } + } + + + // Y blockage, drag + + neiBlock = Zero; + neiDrag = Zero; + + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + for (label ix = 0; ix <= xdim; ++ix) + { + const label ixx = + (ix == 0 ? 0 : ix == xdim ? xdim - 2 : ix - 1); + + neiBlock(iz+1, ix) = + ( + area_block_s(ixx,iy,iz).y() + + area_block_r(ixx,iy,iz).y() + ); + neiDrag(iz+1, ix) = + ( + drag_s(ixx,iy,iz).yy() * pars.cd_s + + drag_r(ixx,iy,iz).y() * pars.cd_r + ); + } + } + for (label ix = 0; ix < surrDims.x(); ++ix) + { + neiBlock(0, ix) = neiBlock(1, ix); + neiDrag(0, ix) = neiDrag(1, ix); + neiBlock(zdim, ix) = neiBlock(cellDims.z(), ix); + neiDrag(zdim, ix) = neiDrag(cellDims.z(), ix); + } + + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + const scalar cell_vol = pdrBlock.V(ix,iy,iz); + + const scalar surr_br = averageSurrounding(neiBlock, iz, ix); + const scalar surr_dr = averageSurrounding(neiDrag, iz, ix); + + calc_drag_etc + ( + area_block_s(ix,iy,iz).y(), + area_block_r(ix,iy,iz).y(), + dirn_block(ix,iy,iz).y(), + surr_br, surr_dr, + &(drag_s(ix,iy,iz).yy()), + &(drag_r(ix,iy,iz).y()), + obs_count(ix,iy,iz), + &(cbdi(ix,iy,iz).y()), + cell_vol + ); + } + } + } + + + // Z blockage, drag + + neiBlock = Zero; + neiDrag = Zero; + + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + for (label iy = 0; iy <= ydim; ++iy) + { + label iyy; + + if (pars.yCyclic) + { + iyy = (iy == 0 ? ydim - 2 : iy == ydim ? 0 : iy - 1); + } + else + { + iyy = (iy == 0 ? 0 : iy == ydim ? ydim - 2 : iy - 1); + } + + neiBlock(ix+1, iy) = + ( + area_block_s(ix,iyy,iz).z() + + area_block_r(ix,iyy,iz).z() + ); + neiDrag(ix+1, iy) = + ( + drag_s(ix,iyy,iz).zz() * pars.cd_s + + drag_r(ix,iyy,iz).z() * pars.cd_r + ); + } + } + for (label iy = 0; iy < surrDims.y(); ++iy) + { + neiBlock(0, iy) = neiBlock(1, iy); + neiDrag(0, iy) = neiDrag(1, iy); + neiBlock(xdim, iy) = neiBlock(cellDims.x(), iy); + neiDrag(xdim, iy) = neiDrag(cellDims.x(), iy); + } + + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + const scalar cell_vol = pdrBlock.V(ix,iy,iz); + + const scalar surr_br = averageSurrounding(neiBlock, ix, iy); + const scalar surr_dr = averageSurrounding(neiDrag, ix, iy); + + calc_drag_etc + ( + area_block_s(ix,iy,iz).z(), + area_block_r(ix,iy,iz).z(), + dirn_block(ix,iy,iz).z(), + surr_br, surr_dr, + &(drag_s(ix,iy,iz).zz()), + &(drag_r(ix,iy,iz).z()), + obs_count(ix,iy,iz), + &(cbdi(ix,iy,iz).z()), + cell_vol + ); + } + } + } + + neiBlock.clear(); + neiDrag.clear(); + + + // Calculate other parameters + + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + const scalar dx = pdrBlock.dx(ix); + const scalar dy = pdrBlock.dy(iy); + const scalar dz = pdrBlock.dz(iz); + const scalar cell_vol = pdrBlock.V(ix, iy, iz); + const scalar cell_size = pdrBlock.width(ix, iy, iz); + + drag_s(ix,iy,iz).xy() *= pars.cd_s; + drag_s(ix,iy,iz).xz() *= pars.cd_s; + drag_s(ix,iy,iz).yz() *= pars.cd_s; + + if (drag_s(ix,iy,iz).xx() > pars.maxCR) { drag_s(ix,iy,iz).xx() = pars.maxCR; } ; + if (drag_s(ix,iy,iz).yy() > pars.maxCR) { drag_s(ix,iy,iz).yy() = pars.maxCR; } ; + if (drag_s(ix,iy,iz).zz() > pars.maxCR) { drag_s(ix,iy,iz).zz() = pars.maxCR; } ; + + if (cbdi(ix,iy,iz).x() > maxCT ) { cbdi(ix,iy,iz).x() = maxCT; } ; + if (cbdi(ix,iy,iz).y() > maxCT ) { cbdi(ix,iy,iz).y() = maxCT; } ; + if (cbdi(ix,iy,iz).z() > maxCT ) { cbdi(ix,iy,iz).z() = maxCT; } ; + + surf(ix,iy,iz) /= cell_vol; + + /* Calculate length scale of obstacles in each cell + Result is stored in surf. */ + + { + const scalar vb = v_block(ix,iy,iz); + + if + ( + ( + ((area_block_s(ix,iy,iz).x() + area_block_r(ix,iy,iz).x()) < MIN_AB_FOR_SIZE) + && ((area_block_s(ix,iy,iz).y() + area_block_r(ix,iy,iz).y()) < MIN_AB_FOR_SIZE) + && ((area_block_s(ix,iy,iz).z() + area_block_r(ix,iy,iz).z()) < MIN_AB_FOR_SIZE) + ) + || ( vb > MAX_VB_FOR_SIZE ) + || ((obs_count(ix,iy,iz) + cmptSum(grating_count(ix,iy,iz))) < MIN_COUNT_FOR_SIZE) + || ( surf(ix,iy,iz) <= 0.0 ) + ) + { + obs_size(ix,iy,iz) = cell_size * pars.empty_lobs_fac; + } + else + { + /* A small sliver of a large cylinder ina cell can give large surface area + but low volume, hence snall "size". Therefore the vol/area formulation + is only fully implemented when count is at least COUNT_FOR_SIZE.*/ + double nn, lobs, lobsMax; + nn = obs_count(ix,iy,iz) - sub_count(ix,iy,iz).x() + grating_count(ix,iy,iz).x(); + if ( nn < 1.0 ) { nn = 1.0; } + lobsMax = (area_block_s(ix,iy,iz).x() + area_block_r(ix,iy,iz).x()) / nn * std::sqrt( dy * dz ); + nn = obs_count(ix,iy,iz) - sub_count(ix,iy,iz).y() + grating_count(ix,iy,iz).y(); + if ( nn < 1.0 ) { nn = 1.0; } + lobs = (area_block_s(ix,iy,iz).y() + area_block_r(ix,iy,iz).y()) / nn * std::sqrt( dz * dx ); + if ( lobs > lobsMax ) + { + lobsMax = lobs; + } + + nn = obs_count(ix,iy,iz) - sub_count(ix,iy,iz).z() + grating_count(ix,iy,iz).z(); + if ( nn < 1.0 ) { nn = 1.0; } + lobs = (area_block_s(ix,iy,iz).z() + area_block_r(ix,iy,iz).z()) / nn * std::sqrt( dx * dy ); + if ( lobs > lobsMax ) + { + lobsMax = lobs; + } + + obs_size(ix,iy,iz) = lobsMax; + } + } + + /* The formulation correctly deals with triple intersections. For quadruple intersections + and worse, there are very many second level overlaps and the resulting volume can be large + positive. However, many or all of these may be eliminated because of the minimum volume of + overlap blocks. Then the result can be negative volume - constrain accordingly + */ + + if (v_block(ix,iy,iz) < 0) + { + v_block(ix,iy,iz) = 0; + } + else if (v_block(ix,iy,iz) > 1) + { + v_block(ix,iy,iz) = 1; + } + + /* We can get -ve sub_count (ns) if two pipes/bars intersect and the dominat direction + of the (-ve) intersection block is not the same as either of the intersecting obstacles. + Also, if we have two hirizontal abrs intersecting, the overlap block can have vertical + edges in a cell where the original bars do not. This can give -ve N and ns. + Negative N is removed by write_scalar. */ + + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + if (sub_count(ix,iy,iz)[cmpt] < 0) + { + sub_count(ix,iy,iz)[cmpt] = 0; + } + } + + v_block(ix,iy,iz) = 1.0 - v_block(ix,iy,iz); // Now porosity + } + } + } + + +//*** Now we start writing the fields *********// + + /* v_block is now porosity + The maximum value does not override the default value placed in the external cells, + so pars.cong_max_betav can be set just below 1 to mark the congested-region cells + for use by the adaptive mesh refinement. */ + + IjkField<Vector<direction>> n_blocked_faces + ( + faceDims, + Vector<direction>::uniform(0) + ); + + write_blocked_face_list + ( + arr.face_block, arr.face_patch, + obs_count, sub_count, n_blocked_faces, + meshIndexing, patches, + pars.blockedFacePar, casepath + ); + write_blockedCellsSet + ( + arr.v_block, + meshIndexing, pars.blockedCellPoros, n_blocked_faces, + casepath, "blockedCellsSet" + ); + + write_scalarField + ( + "betav", arr.v_block, 1, {0, pars.cong_max_betav}, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + const scalar cell_vol = pdrBlock.V(ix, iy, iz); + + /* After the correction to set the number of obstacles normal to a blocked face + to be zero, we can have N and all the components of ns the same. Then there + are no obstacles in the cell as the number in each direction is n minus ns component), + but N is not zero. This can cause problems. We reduce all four numbers by the same amount, + which is OK as only the difference is used except when N is checked to se if there are + any obstacles in then cell. */ + + scalar nmin = cmptMin(sub_count(ix,iy,iz)); + + sub_count(ix,iy,iz).x() -= nmin; + sub_count(ix,iy,iz).y() -= nmin; + sub_count(ix,iy,iz).z() -= nmin; + + obs_count(ix,iy,iz) -= nmin; + + assert(obs_count(ix,iy,iz) > -1); + if ( pars.new_fields ) + { + /* New fields Nv and nsv are intensive quantities that stay unchanged as a cell is subdivided + We do not divide by cell volume because we assume that typical obstacle + is a cylinder passing through the cell */ + const scalar cell_23 = ::pow(cell_vol, 2.0/3.0); + obs_count(ix,iy,iz) /= cell_23; + sub_count(ix,iy,iz) /= cell_23; + } + } + } + } + + + { + Info<< "Writing field files" << nl; + + // obs_size is now the integral scale of the generated turbulence + write_scalarField + ( + "Lobs", arr.obs_size, DEFAULT_LOBS, {0, 10}, "zeroGradient", + meshIndexing, patches, + dimLength, casepath + ); + // surf is now surface area per unit volume + write_scalarField + ( + "Aw", arr.surf, 0, {0, 1000}, "zeroGradient", + meshIndexing, patches, + inv(dimLength), casepath + ); + write_symmTensorField + ( + "CR", arr.drag_s, Zero, "zeroGradient", + meshIndexing, patches, inv(dimLength), casepath + ); + write_symmTensorFieldV + ( + "CT", cbdi, Zero, "zeroGradient", + meshIndexing, patches, + inv(dimLength), casepath + ); + if ( pars.new_fields ) + { + // These have been divided by cell volume ^ (2/3) + write_scalarField + ( + "Nv", arr.obs_count, 0, {0, 1000}, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_symmTensorFieldV + ( + "nsv", arr.sub_count, Zero, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + } + else + { + write_scalarField + ( + "N", arr.obs_count, 0, {0, 1000}, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_symmTensorFieldV + ( + "ns", arr.sub_count, Zero, "zeroGradient", + meshIndexing, patches, dimless, casepath + ); + } + + // Compute some further variables; store in already used arrays + // Re-use the drag array + drag_s = Zero; + + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + // Effective blockage ratio per cell/direction + vector eff_block = + ( + area_block_s(ix,iy,iz) * pars.cd_s/pars.cd_r + + area_block_r(ix,iy,iz) + ); + + // Convert from B to Bv + if (pars.new_fields) + { + eff_block /= pdrBlock.width(ix, iy, iz); + } + + // Effective blockage is zero when faces are blocked + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + if (dirn_block(ix,iy,iz)[cmpt] || eff_block[cmpt] < 0) + { + eff_block[cmpt] = 0; + } + } + + // Use the drag array to store the total effective blockage ratio per cell/direction + // - off-diagonal already zeroed + drag_s(ix,iy,iz).xx() = eff_block.x(); + drag_s(ix,iy,iz).yy() = eff_block.y(); + drag_s(ix,iy,iz).zz() = eff_block.z(); + + cbdi(ix,iy,iz).x() = 1.0 / (betai_inv1(ix,iy,iz).x() + 1.0); + cbdi(ix,iy,iz).y() = 1.0 / (betai_inv1(ix,iy,iz).y() + 1.0); + cbdi(ix,iy,iz).z() = 1.0 / (betai_inv1(ix,iy,iz).z() + 1.0); + + if (cbdi(ix,iy,iz).z() < 0 || cbdi(ix,iy,iz).z() > 1.0) + { + WarningInFunction + << "beta_i problem. z-betai_inv1=" << betai_inv1(ix,iy,iz).z() + << " beta_i=" << cbdi(ix,iy,iz).z() + << nl; + } + + //Use the obs_size array to store Ep + //We use Ep/(Xp-0.999) as length scale to avoid divide by zero, + // so this is OK for initial Xp=1. + obs_size(ix,iy,iz) = 0.001 / obs_size(ix,iy,iz); + + // Use the count array to store the combustion flag ( --1 everywhere in rectangular cells). + obs_count(ix,iy,iz) = 1.0; + } + } + } + + // drag array holds area blockage + if ( pars.new_fields ) + { + write_symmTensorField + ( + "Bv", arr.drag_s, Zero, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + } + else + { + write_symmTensorField + ( + "B", arr.drag_s, Zero, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + } + + // cbdi array holds beta_i + write_symmTensorFieldV + ( + "betai", cbdi, symmTensor::I, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + + // The longitudinal blockage + write_symmTensorFieldV + ( + "Blong", arr.along_block, Zero, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + + // obs_size array now contains 1/Lobs + write_scalarField + ( + "Ep", arr.obs_size, DEFAULT_EP, {0, 10}, "zeroGradient", + meshIndexing, patches, + inv(dimLength), casepath + ); + write_uniformField + ( + "b", 1.0, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "k", DEFAULT_K, K_WALL_FN, + meshIndexing, patches, + sqr(dimVelocity), + casepath + ); + + write_uniformField + ( + "epsilon", DEFAULT_EPS, EPS_WALL_FN, + meshIndexing, patches, + sqr(dimVelocity)/dimTime, casepath + ); + write_uniformField + ( + "ft", 0, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "Su", DEFAULT_SU, "zeroGradient", + meshIndexing, patches, + dimVelocity, casepath + ); + write_uniformField + ( + "T", DEFAULT_T, "zeroGradient", + meshIndexing, patches, + dimTemperature, casepath + ); + write_uniformField + ( + "Tu", DEFAULT_T, "zeroGradient", + meshIndexing, patches, + dimTemperature, casepath + ); + write_uniformField + ( + "Xi", 1, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "Xp", 1, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "GRxp", 0, "zeroGradient", + meshIndexing, patches, + inv(dimTime), casepath + ); + write_uniformField + ( + "GRep", 0, "zeroGradient", + meshIndexing, patches, + inv(dimLength*dimTime), casepath + ); + write_uniformField + ( + "RPers", 0, "zeroGradient", + meshIndexing, patches, + inv(dimTime), casepath + ); + write_pU_fields(meshIndexing, patches, casepath); + + write_uniformField + ( + "alphat", 0, ALPHAT_WALL, + meshIndexing, patches, + dimMass/(dimLength*dimTime), + casepath + ); + write_uniformField + ( + "mut", 0, MUT_WALL_FN, + meshIndexing, patches, + dimDynamicViscosity, casepath + ); + // combustFlag is 1 in rectangular region, 0 or 1 elsewhere + // (although user could set it to another value) + if (equal(pars.outerCombFac, 1)) + { + write_uniformField + ( + "combustFlag", 1, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + } + else + { + write_scalarField + ( + "combustFlag", arr.obs_count, pars.outerCombFac, {0, 1}, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + } + if ( pars.deluge ) + { + write_uniformField + ( + "H2OPS", 0, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "AIR", 0, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "Ydefault", 0, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "eRatio", 1, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + write_uniformField + ( + "sprayFlag", 1, "zeroGradient", + meshIndexing, patches, + dimless, casepath + ); + } + } +} + + +void Foam::PDRarrays::calculateAndWrite +( + const fileName& casepath, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches +) +{ + calculateAndWrite(*this, meshIndexing, casepath, patches); +} + + +void calc_drag_etc +( + double brs, double brr, bool blocked, + double surr_br, double surr_dr, + scalar* drags_p, scalar* dragr_p, + double count, + scalar* cbdi_p, + double cell_vol +) +{ + // Total blockage ratio + scalar br = brr + brs; + + // Idealise obstacle arrangement as sqrt(count) rows. + // Make br the blockage ratio for each row. + if (count > 1.0) { br /= std::sqrt(count); } + + const scalar alpha = + ( + br < 0.99 + ? (1.0 - 0.5 * br) / (1.0 - br) / (1.0 - br) + : GREAT + ); + + // For the moment keep separate the two contributions to the blockage-corrected drag + /* An isolated long obstcale will have two of the surronding eight cells with the same blockage, + so surr_br would be br/4. In this case no correction. Rising to full correction when + all surrounding cells have the same blockage. */ + const scalar expon = + ( + br > 0.0 + ? min(max((surr_br / br - 0.25) * 4.0 / 3.0, scalar(0)), scalar(1)) + : 0.0 + ); + + const scalar alpha_r = ::pow(alpha, 0.5 + 0.5 * expon); + const scalar alpha_s = ::pow(alpha, expon); + + *dragr_p *= alpha_r; + *drags_p *= ::pow(alpha_s, 1.09); + *cbdi_p = ( pars.cb_r * pars.cd_r * *dragr_p + pars.cb_s * pars.cd_s * *drags_p ); + if ( *cbdi_p < 0.0 ) { *cbdi_p = 0.0; } + + // Finally sum the drag. + *drags_p = ( *drags_p * pars.cd_s + *dragr_p * pars.cd_r ); + if ( *drags_p < 0.0 ) { *drags_p = 0.0; } + /* If well-blocked cells are surrounded by empty cells, the flow just goes round + and the drag parameters have little effect. So, for any cells much more empty + than the surrounding cells, we put some CR in there as well. */ + if ( (surr_dr * 0.25) > *drags_p ) + { + *drags_p = surr_dr * 0.25; + *cbdi_p = *drags_p * (pars.cb_r + pars.cb_s ) * 0.5; + // Don't know whether surr. stuff was round or sharp; use average of cb factors + } + if ( blocked ) { *cbdi_p = 0.0; *drags_p = 0.0; *dragr_p = 0.0; } +} + + +void Foam::PDRarrays::blockageSummary() const +{ + if (isNull(block())) + { + WarningInFunction + << nl + << "No blockage information - PDRblock is not set" << nl; + return; + } + + const PDRblock& pdrBlock = block(); + + scalar totArea = 0; + scalar totCount = 0; + scalar totVolBlock = 0; + + vector totBlock(Zero); + vector totDrag(Zero); + + for (label iz = 0; iz < pdrBlock.size(vector::Z); ++iz) + { + for (label iy = 0; iy < pdrBlock.size(vector::Y); ++iy) + { + for (label ix = 0; ix < pdrBlock.size(vector::X); ++ix) + { + const labelVector ijk(ix,iy,iz); + + totVolBlock += v_block(ijk) * pdrBlock.V(ijk); + totArea += surf(ijk); + + totCount += max(0, obs_count(ijk)); + + totDrag.x() += max(0, drag_s(ijk).xx()); + totDrag.y() += max(0, drag_s(ijk).yy()); + totDrag.z() += max(0, drag_s(ijk).zz()); + + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + totBlock[cmpt] += max(0, area_block_s(ijk)[cmpt]); + totBlock[cmpt] += max(0, area_block_r(ijk)[cmpt]); + } + } + } + } + + Info<< nl + << "Volume blockage: " << totVolBlock << nl + << "Total drag: " << totDrag << nl + << "Total count: " << totCount << nl + << "Total area blockage: " << totBlock << nl + << "Total surface area: " << totArea << nl; +} + + +// ------------------------------------------------------------------------- // + +// Another temporary measure +template<class Type> +static void tail_field +( + Ostream& os, + const Type& deflt, + const char* wall_bc, + const UList<PDRpatchDef>& patches +) +{ + // seaGround + { + os.beginBlock("seaGround"); + os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl; + putUniform(os, "value", deflt); + os.endBlock(); + } + + forAll(patches, patchi) + { + const word& patchName = patches[patchi].patchName; + + if (PDRpatchDef::BLOCKED_FACE == patchi) + { + // blockedFaces + os.beginBlock(patchName); + + // No wall functions for blockedFaces patch unless selected + if (pars.blockedFacesWallFn) + { + os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl; + putUniform(os, "value", deflt); + } + else + { + os.writeEntry("type", "zeroGradient"); + } + + os.endBlock(); + } + else if (patches[patchi].patchType == 0) + { + os.beginBlock(patchName); + + os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl; + putUniform(os, "value", deflt); + + os.endBlock(); + } + else + { + os.beginBlock(word(patchName + "Wall")); + os.writeKeyword("type") << wall_bc << token::END_STATEMENT << nl; + putUniform(os, "value", deflt); + os.endBlock(); + + os.beginBlock(word(patchName + "Cyclic_half0")); + os.writeEntry("type", "cyclic"); + os.endBlock(); + + os.beginBlock(word(patchName + "Cyclic_half1")); + os.writeEntry("type", "cyclic"); + os.endBlock(); + } + } + + if (pars.yCyclic) + { + os.beginBlock("Cyclic_half0"); + os.writeEntry("type", "cyclic"); + os.endBlock(); + + os.beginBlock("Cyclic_half1"); + os.writeEntry("type", "cyclic"); + os.endBlock(); + } + else + { + os.beginBlock("ySymmetry"); + os.writeEntry("type", "symmetryPlane"); + os.endBlock(); + } + + if ( pars.two_d ) + { + os.beginBlock("z_boundaries"); + os.writeEntry("type", "empty"); + os.endBlock(); + } + if ( pars.outer_orthog ) + { + os.beginBlock("outer_inner"); + os.writeEntry("type", "cyclicAMI"); + os.writeEntry("neighbourPatch", "inner_outer"); + os.endBlock(); + + os.beginBlock("inner_outer"); + os.writeEntry("type", "cyclicAMI"); + os.writeEntry("neighbourPatch", "outer_inner"); + os.endBlock(); + } +} + + +// ------------------------------------------------------------------------- // + +void write_scalarField +( + const word& fieldName, const IjkField<scalar>& fld, + const scalar& deflt, const scalarMinMax& limits, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +) +{ + fileName path = (casepath / pars.timeName / fieldName); + OFstream os(path); + os.precision(outputPrecision); + + make_header(os, "", volScalarField::typeName, fieldName); + + os.writeEntry("dimensions", dims); + + os << nl; + os.writeKeyword("internalField") + << "nonuniform List<scalar>" << nl + << meshIndexing.nCells() << nl << token::BEGIN_LIST << nl; + + for (label celli=0; celli < meshIndexing.nCells(); ++celli) + { + const labelVector& cellIdx = meshIndexing.cellIndex[celli]; + + if (cmptMin(cellIdx) < 0) + { + os << deflt << nl; + continue; + } + + os << limits.clip(fld(cellIdx)) << nl; + } + + os << token::END_LIST << token::END_STATEMENT << nl; + + os << nl; + os.beginBlock("boundaryField"); + + // outer + { + os.beginBlock("outer"); + + os.writeEntry("type", "inletOutlet"); + putUniform(os, "inletValue", deflt); + putUniform(os, "value", deflt); + + os.endBlock(); + } + + tail_field(os, deflt, wall_bc, patches); + + os.endBlock(); // boundaryField + + IOobject::writeEndDivider(os); +} + + +// ------------------------------------------------------------------------- // + +void write_uniformField +( + const word& fieldName, const scalar& deflt, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +) +{ + OFstream os(casepath / pars.timeName / fieldName); + os.precision(outputPrecision); + + make_header(os, "", volScalarField::typeName, fieldName); + + os.writeEntry("dimensions", dims); + + os << nl; + putUniform(os, "internalField", deflt); + + os << nl; + os.beginBlock("boundaryField"); + + // outer + { + os.beginBlock("outer"); + if (fieldName == "alphat" || fieldName == "mut") + { + // Different b.c. for alphat & mut + os.writeEntry("type", "calculated"); + } + else + { + os.writeEntry("type", "inletOutlet"); + putUniform(os, "inletValue", deflt); + } + + putUniform(os, "value", deflt); + os.endBlock(); + } + + tail_field(os, deflt, wall_bc, patches); + + os.endBlock(); // boundaryField + + IOobject::writeEndDivider(os); +} + + +// ------------------------------------------------------------------------- // + +void write_pU_fields +( + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const fileName& casepath +) +{ + // Velocity field + { + OFstream os(casepath / pars.timeName / "Ubet"); + os.precision(outputPrecision); + + make_header(os, "", volVectorField::typeName, "Ubet"); + + os.writeEntry("dimensions", dimVelocity); + + os << nl; + putUniform(os, "internalField", vector::zero); + + os << nl; + os.beginBlock("boundaryField"); + + // "outer" + { + os.beginBlock("outer"); + os.writeEntry("type", "inletOutlet"); + putUniform(os, "inletValue", vector::zero); + os.endBlock(); + } + + // seaGround + { + os.beginBlock("seaGround"); + os.writeEntry("type", "zeroGradient"); + os.endBlock(); + } + + // Patch 0 is the blocked faces' and 1 is mergingFaces for ignition cell + for (label patchi = 0; patchi < 3; ++patchi) + { + os.beginBlock(patches[patchi].patchName); + os.writeKeyword("type") << pars.UPatchBc.c_str() + << token::END_STATEMENT << nl; + os.endBlock(); + } + + for (label patchi = 3; patchi < patches.size(); ++patchi) + { + const PDRpatchDef& p = patches[patchi]; + const word& patchName = p.patchName; + + if (p.patchType == 0) + { + os.beginBlock(patchName); + + os.writeEntry("type", "timeVaryingMappedFixedValue"); + os.writeEntry("fileName", "<case>" / (patchName + ".dat")); + os.writeEntry("outOfBounds", "clamp"); + putUniform(os, "value", vector::zero); + os.endBlock(); + } + else + { + os.beginBlock(word(patchName + "Wall")); + os.writeEntry("type", "activePressureForceBaffleVelocity"); + + os.writeEntry("cyclicPatch", word(patchName + "Cyclic_half0")); + os.writeEntry("openFraction", 0); // closed + os.writeEntry("openingTime", p.blowoffTime); + os.writeEntry("maxOpenFractionDelta", 0.1); + os.writeEntry("forceBased", "false"); + os.writeEntry("opening", "true"); + + putUniform(os, "value", vector::zero); + os.endBlock(); + + os.beginBlock(word(patchName + "Cyclic_half0")); + os.writeEntry("type", "cyclic"); + putUniform(os, "value", vector::zero); + os.endBlock(); + + os.beginBlock(word(patchName + "Cyclic_half1")); + os.writeEntry("type", "cyclic"); + putUniform(os, "value", vector::zero); + os.endBlock(); + } + } + + if (pars.yCyclic) + { + os.beginBlock("yCyclic_half0"); + os.writeEntry("type", "cyclic"); + os.endBlock(); + + os.beginBlock("yCyclic_half1"); + os.writeEntry("type", "cyclic"); + os.endBlock(); + } + else + { + os.beginBlock("ySymmetry"); + os.writeEntry("type", "symmetryPlane"); + os.endBlock(); + } + + if ( pars.outer_orthog ) + { + os.beginBlock("outer_inner"); + os.writeEntry("type", "cyclicAMI"); + os.writeEntry("neighbourPatch", "inner_outer"); + os.endBlock(); + + os.beginBlock("inner_outer"); + os.writeEntry("type", "cyclicAMI"); + os.writeEntry("neighbourPatch", "outer_inner"); + } + + os.endBlock(); // boundaryField + + IOobject::writeEndDivider(os); + } + + + // Pressure field + { + const scalar deflt = DEFAULT_P; + const char *wall_bc = "zeroGradient;\n\trho\trho"; + + OFstream os(casepath / pars.timeName / "p"); + os.precision(outputPrecision); + + make_header(os, "", volScalarField::typeName, "p"); + + os.writeEntry("dimensions", dimPressure); + + os << nl; + putUniform(os, "internalField", deflt); + + os << nl; + os.beginBlock("boundaryField"); + + // "outer" + { + os.beginBlock("outer"); + os.writeEntry("type", "waveTransmissive"); + os.writeEntry("gamma", 1.3); + os.writeEntry("fieldInf", deflt); + os.writeEntry("lInf", 5); + putUniform(os, "value", deflt); + os.endBlock(); + } + + tail_field(os, deflt, wall_bc, patches); + + os.endBlock(); // boundaryField + + IOobject::writeEndDivider(os); + } +} + + +// ------------------------------------------------------------------------- // + +void write_symmTensorField +( + const word& fieldName, + const IjkField<symmTensor>& fld, + const symmTensor& deflt, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +) +{ + OFstream os(casepath / pars.timeName / fieldName); + os.precision(outputPrecision); + + make_header(os, "", volSymmTensorField::typeName, fieldName); + + os.writeEntry("dimensions", dims); + + os << nl; + os.writeKeyword("internalField") + << "nonuniform List<symmTensor>" << nl + << meshIndexing.nCells() << nl << token::BEGIN_LIST << nl; + + for (label celli=0; celli < meshIndexing.nCells(); ++celli) + { + const labelVector& cellIdx = meshIndexing.cellIndex[celli]; + + if (cmptMin(cellIdx) < 0) + { + os << deflt << nl; + continue; + } + + os << fld(cellIdx) << nl; + } + os << token::END_LIST << token::END_STATEMENT << nl; + + os << nl; + os.beginBlock("boundaryField"); + + // outer + { + os.beginBlock("outer"); + + os.writeEntry("type", "inletOutlet"); + putUniform(os, "inletValue", deflt); + putUniform(os, "value", deflt); + + os.endBlock(); + } + + tail_field(os, deflt, wall_bc, patches); + + os.endBlock(); // boundaryField + + IOobject::writeEndDivider(os); +} + + +// Write a volSymmTensorField but with vectors as input. +// The off-diagonals are zero. +void write_symmTensorFieldV +( + const word& fieldName, + const IjkField<vector>& fld, + const symmTensor& deflt, const char *wall_bc, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + const dimensionSet& dims, const fileName& casepath +) +{ + OFstream os(casepath / pars.timeName / fieldName); + os.precision(outputPrecision); + + make_header(os, "", volSymmTensorField::typeName, fieldName); + + os.writeEntry("dimensions", dims); + + os << nl; + os.writeKeyword("internalField") + << "nonuniform List<symmTensor>" << nl + << meshIndexing.nCells() << nl << token::BEGIN_LIST << nl; + + symmTensor val(symmTensor::zero); + + for (label celli=0; celli < meshIndexing.nCells(); ++celli) + { + const labelVector& cellIdx = meshIndexing.cellIndex[celli]; + + if (cmptMin(cellIdx) < 0) + { + os << deflt << nl; + continue; + } + + const vector& vec = fld(cellIdx); + + val.xx() = vec.x(); + val.yy() = vec.y(); + val.zz() = vec.z(); + + os << val << nl; + } + os << token::END_LIST << token::END_STATEMENT << nl; + + os << nl; + os.beginBlock("boundaryField"); + + // outer + { + os.beginBlock("outer"); + + os.writeEntry("type", "inletOutlet"); + putUniform(os, "inletValue", deflt); + putUniform(os, "value", deflt); + + os.endBlock(); + } + + tail_field(os, deflt, wall_bc, patches); + + os.endBlock(); // boundaryField + + IOobject::writeEndDivider(os); +} + + +// ------------------------------------------------------------------------- // + +void write_blocked_face_list +( + const IjkField<vector>& face_block, + const IjkField<labelVector>& face_patch, + const IjkField<scalar>& obs_count, IjkField<vector>& sub_count, + IjkField<Vector<direction>>& n_blocked_faces, + const PDRmeshArrays& meshIndexing, + const UList<PDRpatchDef>& patches, + double limit_par, const fileName& casepath +) +{ + /* Create the lists of face numbers for faces that have already been defined as + belonging to (inlet) patches), and others that are found to be blocked. + Then write these out to set files, */ + + const labelVector& cellDims = meshIndexing.cellDims; + + Map<bitSet> usedFaces; + + Info<< "Number of patches: " << patches.size() << nl; + + for (label facei=0; facei < meshIndexing.nFaces(); ++facei) + { + // The related i-j-k face index for the mesh face + const labelVector& faceIdx = meshIndexing.faceIndex[facei]; + + if (cmptMin(faceIdx) < 0) + { + continue; + } + + const label ix = faceIdx.x(); + const label iy = faceIdx.y(); + const label iz = faceIdx.z(); + const direction orient = meshIndexing.faceOrient[facei]; + + label patchId = -1; + scalar val(Zero); + + /* A bit messy to be changing sub_count here. but there is a problem of generation + of subgrid flame area Xp when the flame approaches a blocked wall. the fix is to make + the normal component of "n" zero in the cells adjacent to the blocked face. That component + of n is zero when that component of sub_count i.e. ns) equals count (i.e. N). */ + { + switch (orient) + { + case vector::X: + { + // face_block is the face blockage; + // face_patch is the patch number on the face (if any) + val = face_block(faceIdx).x(); + patchId = face_patch(faceIdx).x(); + + if + ( + val > limit_par + && iy < cellDims[vector::Y] + && iz < cellDims[vector::Z] + ) + { + // n_blocked_faces: + // count of x-faces blocked for this cell + + if (ix < cellDims[vector::X]) + { + ++n_blocked_faces(ix,iy,iz).x(); + sub_count(ix,iy,iz).x() = obs_count(ix,iy,iz); + } + + if (ix > 0) + { + // And the neighbouring cell + ++n_blocked_faces(ix-1,iy,iz).x(); + sub_count(ix-1,iy,iz).x() = obs_count(ix-1,iy,iz); + } + } + } + break; + + case vector::Y: + { + val = face_block(faceIdx).y(); + patchId = face_patch(faceIdx).y(); + + if + ( + val > limit_par + && iz < cellDims[vector::Z] + && ix < cellDims[vector::X] + ) + { + // n_blocked_faces: + // count of y-faces blocked for this cell + + if (iy < cellDims[vector::Y]) + { + ++n_blocked_faces(ix,iy,iz).y(); + sub_count(ix,iy,iz).y() = obs_count(ix,iy,iz); + } + + if (iy > 0) + { + // And the neighbouring cell + ++n_blocked_faces(ix,iy-1,iz).y(); + sub_count(ix,iy-1,iz).y() = obs_count(ix,iy-1,iz); + } + } + } + break; + + case vector::Z: + { + val = face_block(faceIdx).z(); + patchId = face_patch(faceIdx).z(); + + if + ( + val > limit_par + && ix < cellDims[vector::X] + && iy < cellDims[vector::Y] + ) + { + // n_blocked_faces: + // count of z-faces blocked for this cell + + if (iz < cellDims[vector::Z]) + { + ++n_blocked_faces(ix,iy,iz).z(); + sub_count(ix,iy,iz).z() = obs_count(ix,iy,iz); + } + + if (iz > 0) + { + // And the neighbouring cell + ++n_blocked_faces(ix,iy,iz-1).z(); + sub_count(ix,iy,iz-1).z() = obs_count(ix,iy,iz-1); + } + } + } + break; + } + + if (patchId > 0) + { + // If this face is on a defined patch add to list + usedFaces(patchId).set(facei); + } + else if (val > limit_par) + { + // Add to blocked faces list + usedFaces(PDRpatchDef::BLOCKED_FACE).set(facei); + } + } + } + + // Write in time or constant dir + const bool hasPolyMeshTimeDir = isDir(casepath/pars.timeName/"polyMesh"); + + const fileName setsDir = + ( + casepath + / (hasPolyMeshTimeDir ? pars.timeName : word("constant")) + / fileName("polyMesh/sets") + ); + + if (!isDir(setsDir)) + { + mkDir(setsDir); + } + + + // Create as blockedFaces Set file for each patch, including + // basic blocked faces + forAll(patches, patchi) + { + const word& patchName = patches[patchi].patchName; + + OFstream os(setsDir / (patchName + "Set")); + + make_header(os, "polyMesh/sets", "faceSet", patchName); + + // Check for blocked faces + const auto& fnd = usedFaces.cfind(patchi); + + if (fnd.good() && (*fnd).any()) + { + os << nl << (*fnd).toc() << nl; + } + else + { + os << nl << labelList() << nl; + } + + IOobject::writeEndDivider(os); + } + + // Create the PDRMeshDict, listing the blocked faces sets and their patch names + + { + DynamicList<word> panelNames; + + OFstream os(casepath / "system/PDRMeshDict"); + + make_header(os, "system", "dictionary", "PDRMeshDict"); + + os.writeEntry("blockedCells", "blockedCellsSet"); + os << nl << "blockedFaces" << nl << token::BEGIN_LIST << nl; + + for (const PDRpatchDef& p : patches) + { + const word& patchName = p.patchName; + const word setName = patchName + "Set"; + + if (p.patchType == 0) // Patch + { + os << " " << token::BEGIN_LIST + << setName << token::SPACE + << patchName << token::END_LIST + << nl; + } + else if (p.patchType > 0) // Panel + { + panelNames.append(setName); + } + } + + os << token::END_LIST << token::END_STATEMENT << nl << nl; + os.beginBlock("coupledFaces"); + + for (const PDRpatchDef& p : patches) + { + const word& patchName = p.patchName; + const word setName = patchName + "Set"; + + if (p.patchType > 0) // Panel + { + os.beginBlock(setName); + os.writeEntry("wallPatchName", word(patchName + "Wall")); + os.writeEntry("cyclicMasterPatchName", patchName); + os.endBlock(); + } + } + os.endBlock() << nl; + + os.writeEntry("defaultPatch", "blockedFaces"); + + IOobject::writeEndDivider(os); + + // Write panelList + OFstream(casepath / "panelList")() + << panelNames << token::END_STATEMENT << nl; + } +} + + +void write_blockedCellsSet +( + const IjkField<scalar>& fld, + const PDRmeshArrays& meshIndexing, + double limit_par, + const IjkField<Vector<direction>>& n_blocked_faces, + const fileName& casepath, + const word& listName +) +{ + if (listName.empty()) + { + return; + } + + // Write in time or constant dir + const bool hasPolyMeshTimeDir = isDir(casepath/pars.timeName/"polyMesh"); + + const fileName path = + ( + casepath + / (hasPolyMeshTimeDir ? pars.timeName : word("constant")) + / fileName("polyMesh/sets") + / listName + ); + + if (!isDir(path.path())) + { + mkDir(path.path()); + } + + bitSet blockedCell; + + for (label celli=0; celli < meshIndexing.nCells(); ++celli) + { + const labelVector& cellIdx = meshIndexing.cellIndex[celli]; + + if (cmptMin(cellIdx) < 0) + { + continue; + } + + if (fld(cellIdx) < limit_par) + { + blockedCell.set(celli); + continue; + } + + const Vector<direction>& blocked = n_blocked_faces(cellIdx); + + const label n_bfaces = cmptSum(blocked); + + label n_bpairs = 0; + + if (n_bfaces > 1) + { + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + if (blocked[cmpt] > 1) ++n_bpairs; + } + + #if 0 + // Extra debugging + Info<<"block " << celli << " from " + << blocked << " -> (" + << n_bfaces << ' ' << n_bpairs + << ')' << nl; + #endif + } + + if + ( + n_bfaces >= pars.nFacesToBlockC + || n_bpairs >= pars.nPairsToBlockC + ) + { + blockedCell.set(celli); + } + } + + + OFstream os(path); + make_header(os, "constant/polyMesh/sets", "cellSet", listName); + + if (blockedCell.any()) + { + os << blockedCell.toc(); + } + else + { + os << labelList(); + } + + os << token::END_STATEMENT << nl; + + IOobject::writeEndDivider(os); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRlegacy.H b/applications/utilities/preProcessing/PDRsetFields/PDRlegacy.H new file mode 100644 index 0000000000000000000000000000000000000000..bbb660f04abf9e8b298e04f3e382ac5b7fe8d9b1 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRlegacy.H @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Namespace + Foam::PDRlegacy + +Description + Legacy and transitional routines + +SourceFiles + PDRlegacyMeshSpec.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRlegacy_H +#define PDRlegacy_H + +#include "PDRblock.H" +#include "fileName.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class ISstream; +class PDRblock; + +/*---------------------------------------------------------------------------*\ + Namespace PDRlegacy +\*---------------------------------------------------------------------------*/ + +namespace PDRlegacy +{ + void print_info(const PDRblock& block); + + void read_mesh_spec(const fileName& casepath, PDRblock& pdrBlock); + + void read_mesh_spec(ISstream& is, PDRblock& pdrBlock); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRlegacyMeshSpec.C b/applications/utilities/preProcessing/PDRsetFields/PDRlegacyMeshSpec.C new file mode 100644 index 0000000000000000000000000000000000000000..720ec86359f07e5e247f43779c450405ba327d3b --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRlegacyMeshSpec.C @@ -0,0 +1,340 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// Read spec that resemble this: +// +// xmesh +// ( +// ( -8.18 14 0.83 ) +// ( -0.69 11 1.00 ) +// ( 0.69 14 1.20 ) +// ( 8.18 0 ) +// ) +// +// ymesh +// ( +// ... +// ) + +#include "PDRlegacy.H" + +// OpenFOAM includes +#include "error.H" +#include "IFstream.H" +#include "stringOps.H" +#include "OSspecific.H" + +#define XMESH_TAG "xmesh" +#define YMESH_TAG "ymesh" +#define ZMESH_TAG "zmesh" + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace PDRlegacy +{ +namespace Detail +{ + +//- Simple structure for processing a mesh spec entry +// Handles an entry with (float), (float int), or (float int float) +// +// This is for handling a sub-spec that resembles this: +// +// ( +// ( -8.18 14 0.83 ) +// ( -0.69 11 1.00 ) +// ( 0.69 14 1.20 ) +// ( 8.18 0 ) +// ) +struct pdrMeshSpecLine +{ + scalar knot; + label ndiv; + scalar factor; + + pdrMeshSpecLine() : knot(0), ndiv(0), factor(0) {} + + //- Cheap means to avoid uniform list output + bool operator!=(const pdrMeshSpecLine&) const + { + return false; + } +}; + + +// Read mesh-spec entry +Istream& operator>>(Istream& is, pdrMeshSpecLine& spec) +{ + spec.knot = 0; + spec.ndiv = 0; + spec.factor = 0; + + is.readBegin("pdrMeshSpecLine"); + + // Must have a point + is >> spec.knot; + + token tok(is); + if (tok.isLabel()) + { + spec.ndiv = tok.labelToken(); + + if (spec.ndiv) + { + is >> spec.factor; + } + } + else + { + is.putBack(tok); + } + + is.readEnd("pdrMeshSpecLine"); + + is.check(FUNCTION_NAME); + return is; +} + +#ifdef FULLDEBUG +// Write mesh-spec entry +Ostream& operator<<(Ostream& os, const pdrMeshSpecLine& spec) +{ + os << token::BEGIN_LIST << spec.knot; + + if (spec.ndiv) + { + os << token::SPACE << spec.ndiv + << token::SPACE << spec.factor; + } + + os << token::END_LIST; + + return os; +} +#endif + + +void read_spec(ISstream& is, const direction cmpt, List<scalar>& gridPoint) +{ + if (!gridPoint.empty()) + { + FatalErrorInFunction + << "Duplicate specification of " + << vector::componentNames[cmpt] + << " grid" + << exit(FatalError); + } + + List<pdrMeshSpecLine> specs(is); + + if (specs.size() < 2) + { + FatalErrorInFunction + << "Grid specification for " << vector::componentNames[cmpt] + << " is too small. Need at least two points!" << nl + << exit(FatalError); + } + + specs.last().ndiv = 0; // safety + + + DynamicList<scalar> knots; + DynamicList<label> divisions; + DynamicList<scalar> factors; + + for (const auto& spec : specs) + { + knots.append(spec.knot); + + if (spec.ndiv < 1) + { + break; + } + divisions.append(spec.ndiv); + factors.append(spec.factor); + } + + label nPoints = 1; + for (const label nDiv : divisions) + { + nPoints += nDiv; + } + + if (nPoints < 2) + { + FatalErrorInFunction + << "No cells defined for direction " + << vector::componentNames[cmpt] << nl + << exit(FatalError); + } + + + // Define the grid points + gridPoint.resize(nPoints); + + const label nSegments = divisions.size(); + + label start = 0; + + for (label segmenti=0; segmenti < nSegments; ++segmenti) + { + const label nDiv = divisions[segmenti]; + const scalar factor = factors[segmenti]; + + SubList<scalar> subPoint(gridPoint, nDiv+1, start); + start += nDiv; + + subPoint[0] = knots[segmenti]; + subPoint[nDiv] = knots[segmenti+1]; + + const scalar dist = (subPoint.last() - subPoint.first()); + + if (equal(factor, scalar(1))) + { + for (label i=1; i < nDiv; ++i) + { + subPoint[i] = (subPoint[0] + (dist * i)/nDiv); + } + } + else + { + scalar delta = dist * (1.0 - factor) / (1.0 - ::pow(factor, nDiv)); + + scalar xyz = subPoint[0]; + + for (label i=0; i < nDiv; ++i) + { + subPoint[i] = xyz; + xyz += delta; + delta *= factor; + } + } + } +} + + +} // End namespace Detail +} // End namespace PDRlegacy +} // End namespace Foam + + +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // + +void Foam::PDRlegacy::print_info(const PDRblock& block) +{ + Info<< "PDRblock" << nl + << " nCells: " << block.sizes() << nl + << " Box: " << block.bounds() << nl + << "x " << flatOutput(block.grid().x()) << nl + << "y " << flatOutput(block.grid().y()) << nl + << "z " << flatOutput(block.grid().z()) << nl + << endl; +} + + +void Foam::PDRlegacy::read_mesh_spec(const fileName& casepath, PDRblock& block) +{ + Info<< "Reading pdrMeshSpec (legacy format)" << nl; + + bool processed = false; + + for (const fileName dirName : { "system", "constant/polyMesh" }) + { + fileName path + ( + casepath / dirName / "pdrMeshSpec" + ); + + if (Foam::isFile(path)) + { + IFstream is(path); + + read_mesh_spec(is, block); + processed = true; + break; + } + } + + if (!processed) + { + FatalErrorInFunction + << "Did not process pdrMeshSpec" << nl + << exit(FatalError); + } +} + + +void Foam::PDRlegacy::read_mesh_spec(ISstream& is, PDRblock& block) +{ + Vector<scalarList> grid; + + string line; + + while (is.good()) + { + is.getLine(line); + stringOps::inplaceTrim(line); + + if (line == XMESH_TAG) + { + Detail::read_spec(is, vector::X, grid.x()); + } + else if (line == YMESH_TAG) + { + Detail::read_spec(is, vector::Y, grid.y()); + } + else if (line == ZMESH_TAG) + { + Detail::read_spec(is, vector::Z, grid.z()); + } + } + + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + if (grid[cmpt].empty()) + { + FatalErrorInFunction + << "No specification for " + << vector::componentNames[cmpt] + << " grid" << nl + << exit(FatalError); + } + } + + block.reset(grid.x(), grid.y(), grid.z()); + + #ifdef FULLDEBUG + print_info(block); + #endif +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRmeshArrays.C b/applications/utilities/preProcessing/PDRsetFields/PDRmeshArrays.C new file mode 100644 index 0000000000000000000000000000000000000000..8e6a6c1fd95496c471d8ec8c4f2087f443e1e9b1 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRmeshArrays.C @@ -0,0 +1,262 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRmeshArrays.H" +#include "PDRblock.H" +#include "polyMesh.H" +#include "Time.H" +#include "IjkField.H" + +// Notes +// +// Determines the face and cell numbers of all faces and cells in the +// central rectangular region where CAD_PDR operates. First, +// "points" is read and the coordinates (by which I mean here the +// indices in the x, y and z coordinate arrays) are determined. Then +// "faces" is read and for each the coordinates of the lower- x,y,z +// corner are determioned, also the orientation (X, Y or Z). +// (Orientation in the sense of e.g. + or -x is not noted.) The files +// "owner" and "neighbour" specify the six faces around each cell, so +// from these the coordinates of the cells are determined. +// +// Full checks are made that the mesh in the central region is consistent +// with CAD_PDR's mesh specified by the PDRmeshSpec file. +// +// Eventually, when writing out results, we shall work through the +// full list of cells, writing default values for any cells that are +// not in the central regtion. + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +Foam::scalar Foam::PDRmeshArrays::gridPointRelTol = 0.02; + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::PDRmeshArrays::classify +( + const polyMesh& mesh, + const PDRblock& pdrBlock +) +{ + // Additional copy of i-j-k addressing + cellDims = pdrBlock.sizes(); + faceDims = (cellDims + labelVector::one); + + const label maxPointId = cmptMax(pdrBlock.sizes())+1; + + Info<< "Mesh" << nl + << " nPoints:" << mesh.nPoints() + << " nCells:" << mesh.nCells() + << " nFaces:" << mesh.nFaces() << nl; + + Info<< "PDRblock" << nl + << " minEdgeLen:" << pdrBlock.minEdgeLen() << nl; + + + // Bin points into i-j-k locations + List<labelVector> pointIndex(mesh.nPoints()); + + for (label pointi=0; pointi < mesh.nPoints(); ++pointi) + { + const point& pt = mesh.points()[pointi]; + pointIndex[pointi] = pdrBlock.gridIndex(pt, gridPointRelTol); + } + + // Min x,y,z index + const labelMinMax invertedLimits(maxPointId, -maxPointId); + Vector<labelMinMax> faceLimits; + + const Vector<direction> faceBits + ( + boundBox::XDIR, + boundBox::YDIR, + boundBox::ZDIR + ); + + faceIndex.resize(mesh.nFaces()); + faceOrient.resize(mesh.nFaces()); + + for (label facei=0; facei < mesh.nFaces(); ++facei) + { + faceLimits.x() = faceLimits.y() = faceLimits.z() = invertedLimits; + + for (const label pointi : mesh.faces()[facei]) + { + for (direction cmpt=0; cmpt < labelVector::nComponents; ++cmpt) + { + faceLimits[cmpt].add(pointIndex[pointi][cmpt]); + } + } + + direction inPlane(0u); + + for (direction cmpt=0; cmpt < labelVector::nComponents; ++cmpt) + { + const auto& limits = faceLimits[cmpt]; + + if (!limits.valid()) + { + // This should be impossible + FatalErrorInFunction + << "Unexpected search failure for " << facei << " in " + << vector::componentNames[cmpt] << "-direction" << nl + << exit(FatalError); + } + + if (limits.min() < 0) + { + FatalErrorInFunction + << "Face " << facei << " contains non-grid point in " + << vector::componentNames[cmpt] << "-direction" << nl + << exit(FatalError); + } + else if (limits.min() == limits.max()) + { + // In plane + inPlane |= faceBits[cmpt]; + } + else if (limits.min() + 1 != limits.max()) + { + FatalErrorInFunction + << "Face " << facei + << " not in " << vector::componentNames[cmpt] << "-plane" << nl + << exit(FatalError); + } + } + + switch (inPlane) + { + case boundBox::XDIR: + faceOrient[facei] = vector::X; + break; + + case boundBox::YDIR: + faceOrient[facei] = vector::Y; + break; + + case boundBox::ZDIR: + faceOrient[facei] = vector::Z; + break; + + default: + FatalErrorInFunction + << "Face " << facei << " not in an x/y/z plane?" << nl + << exit(FatalError); + break; + } + + faceIndex[facei] = + labelVector + ( + faceLimits.x().min(), + faceLimits.y().min(), + faceLimits.z().min() + ); + } + + + // Bin cells into i-j-k locations + cellIndex = std::move(pointIndex); + cellIndex = labelVector::uniform(maxPointId); + cellIndex.resize(mesh.nCells(), labelVector::uniform(maxPointId)); + + // Option 1: use PDRblock.findCell() method + if (true) + { + const pointField& cc = mesh.cellCentres(); + + for (label celli=0; celli < mesh.nCells(); ++celli) + { + cellIndex[celli] = pdrBlock.findCell(cc[celli]); + } + } + + // Option 2: walk cell faces and use faceIndex information + if (false) + { + for (label celli=0; celli < mesh.nCells(); ++celli) + { + labelVector& cellIdx = cellIndex[celli]; + + for (const label facei : mesh.cells()[celli]) + { + cellIdx.x() = min(cellIdx.x(), faceIndex[facei].x()); + cellIdx.y() = min(cellIdx.y(), faceIndex[facei].y()); + cellIdx.z() = min(cellIdx.z(), faceIndex[facei].z()); + } + + if (cmptMin(cellIdx) < 0) + { + cellIdx = labelVector(-1,-1,-1); + } + } + } + + + // Verify that all i-j-k cells were found + { + // This could be more efficient - but we want to be picky + IjkField<bool> cellFound(pdrBlock.sizes(), false); + + for (label celli=0; celli < cellIndex.size(); ++celli) + { + const labelVector& cellIdx = cellIndex[celli]; + + if (cmptMin(cellIdx) >= 0) + { + cellFound(cellIdx) = true; + } + } + + label firstMissing = cellFound.find(false); + + if (firstMissing >= 0) + { + FatalErrorInFunction + << "No cell found for " << pdrBlock.index(firstMissing) + << " indexing" + << exit(FatalError); + } + } +} + + +void Foam::PDRmeshArrays::read +( + const Time& runTime, + const PDRblock& pdrBlock +) +{ + #include "createPolyMesh.H" + classify(mesh, pdrBlock); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRmeshArrays.H b/applications/utilities/preProcessing/PDRsetFields/PDRmeshArrays.H new file mode 100644 index 0000000000000000000000000000000000000000..26142e54fb85b7784363d469bd0049f2937b6d64 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRmeshArrays.H @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::PDRmeshArrays + +Description + OpenFOAM/PDRblock addressing information + + Provides mapping for a rectilinear OpenFOAM mesh in terms of + i-j-k indices for faces and cells. + + The mesh points are first binned according to their i-j-k locations. + Next the faces are classified according to their lowest x/y/z + coordinates and the face orientation as x/y/z. + Orientation in the sense +x or -x is not noted. + The cell faces are then examined to determine the appropriate i-j-k + location. + +SourceFiles + PDRmeshmeshArraysIO.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRmeshArrays_H +#define PDRmeshArrays_H + +#include "labelVector.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class PDRblock; +class polyMesh; +class Time; + +/*---------------------------------------------------------------------------*\ + Class PDRmeshArrays Declaration +\*---------------------------------------------------------------------------*/ + +class PDRmeshArrays +{ +public: + + //- Relative tolerance when matching grid points. Default = 0.02 + static scalar gridPointRelTol; + + //- The cell i-j-k addressing range + labelVector cellDims; + + //- The face i-j-k addressing range + labelVector faceDims; + + //- For each cell, the corresponding i-j-k address. + List<labelVector> cellIndex; + + //- For each face, the corresponding i-j-k address. + List<labelVector> faceIndex; + + //- For each face, the x/y/z orientation + List<direction> faceOrient; + + + // Constructors + + //- Construct null + PDRmeshArrays() = default; + + + //- Destructor + ~PDRmeshArrays() = default; + + + // Member Functions + + //- The number of cells + label nCells() const + { + return cellIndex.size(); + } + + //- The number of faces + label nFaces() const + { + return faceIndex.size(); + } + + + //- Determine i-j-k indices for faces/cells + void classify(const polyMesh& mesh, const PDRblock& pdrBlock); + + //- Read OpenFOAM mesh and determine i-j-k indices for faces/cells + void read(const Time& runTime, const PDRblock& pdrBlock); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRparams.C b/applications/utilities/preProcessing/PDRsetFields/PDRparams.C new file mode 100644 index 0000000000000000000000000000000000000000..9554f8618fba36e48a1f9ab15a0dd8c003394714 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRparams.C @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRparams.H" +#include "stringOps.H" + +// * * * * * * * * * * * * * * * * Global Data * * * * * * * * * * * * * * * // + +// Global parameter settings +Foam::PDRparams Foam::pars; + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::PDRparams::readDefaults(const dictionary& dict) +{ + dict.readIfPresent("legacyMeshSpec", legacyMeshSpec); + dict.readIfPresent("legacyObsSpec", legacyObsSpec); + + dict.readIfPresent("two_d", two_d); + dict.readIfPresent("yCyclic", yCyclic); + dict.readIfPresent("ySymmetry", ySymmetry); + dict.readIfPresent("deluge", deluge); + + dict.readIfPresent("newFields", new_fields); + dict.readIfPresent("noIntersectN", noIntersectN); + + dict.readIfPresent("blockedFacesWallFn", blockedFacesWallFn); + dict.readIfPresent("ignoreGratings", ignoreGratings); + + outer_orthog = dict.found("outer_orthog"); + + dict.readIfPresent("debugLevel", debugLevel); + dict.readIfPresent("nFacesToBlockC", nFacesToBlockC); + dict.readIfPresent("nPairsToBlockC", nPairsToBlockC); + dict.readIfPresent("overlaps", overlaps); + + dict.readIfPresent("gridPointTol", gridPointTol); + + dict.readIfPresent("Cb_r", cb_r); + dict.readIfPresent("Cb_s", cb_s); + + dict.readIfPresent("Cd_r", cd_r); + dict.readIfPresent("Cd_s", cd_s); + + dict.readIfPresent("congRegionMaxBetav", cong_max_betav); + + dict.readIfPresent("min_overlap_vol", min_overlap_vol); + dict.readIfPresent("min_overlap_area", min_overlap_area); + dict.readIfPresent("min_width", min_width); + dict.readIfPresent("empty_lobs_fac", empty_lobs_fac); + dict.readIfPresent("outerCombFac", outerCombFac); + dict.readIfPresent("obs_expand", obs_expand); + + dict.readIfPresent("def_grating_slat_w", def_grating_slat_w); + dict.readIfPresent("blockedCellPoros", blockedCellPoros); + dict.readIfPresent("blockedFacePar", blockedFacePar); + dict.readIfPresent("maxCR", maxCR); + + dict.readIfPresent("blockageNoCT", blockageNoCT); + dict.readIfPresent("scale", scale); + + UPatchBc = "fixedValue;value uniform (0 0 0)"; + if (dict.readIfPresent("UPatchBc", UPatchBc)) + { + stringOps::inplaceTrim(UPatchBc); + } +} + + +void Foam::PDRparams::read(const dictionary& dict) +{ + readDefaults(dict); + + dict.readEntry("obsFileDir", obsfile_dir); + dict.readEntry("obsFileNames", obsfile_names); + + stringOps::inplaceExpand(obsfile_dir); + + for (auto& f : obsfile_names) + { + stringOps::inplaceExpand(f); + } +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRparams.H b/applications/utilities/preProcessing/PDRsetFields/PDRparams.H new file mode 100644 index 0000000000000000000000000000000000000000..0d383021f69ccf0ac56a82bd9eb78731670826f7 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRparams.H @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2018-2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::PDRparams + +Description + Parameters for PDRsetFields + +SourceFiles + PDRparams.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRparams_H +#define PDRparams_H + +#include "labelList.H" +#include "scalarList.H" +#include "wordList.H" +#include "fileNameList.H" +#include "dictionary.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class PDRparams Declaration +\*---------------------------------------------------------------------------*/ + +class PDRparams +{ +public: + + // Data Members + + fileName obsfile_dir; + wordList obsfile_names; + word timeName; + string UPatchBc; //!< "fixedValue;value uniform (0 0 0)" + + bool legacyMeshSpec{false}; + bool legacyObsSpec{false}; + + bool two_d{false}; + bool yCyclic{false}; + bool ySymmetry{false}; + bool deluge{false}; + bool new_fields{true}; + bool noIntersectN{true}; + bool blockedFacesWallFn{false}; + bool ignoreGratings{false}; + bool outer_orthog{false}; + + int debugLevel{0}; + + //- Min number of blocked cell faces + //- for a cell to be marked as blocked + int nFacesToBlockC{6}; + + //- Min number of blocked cell face pairs (on opposite faces of a cell) + //- for a cell to be marked as blocked + int nPairsToBlockC{3}; + + //- Flag to control which overlap calculations are performed + int overlaps{0x7}; + + scalar gridPointTol{0.02}; + + scalar cb_r{0.035}; + scalar cb_s{0.08}; + + scalar cd_r{1.2}; + scalar cd_s{2.0}; + + scalar cong_max_betav{1.0}; + + scalar min_overlap_vol{0}; + scalar min_overlap_area{0}; + + //- Ignore obstacles with second dimension (or diameter) less than this + scalar min_width{0.001}; + + //- Lobs in empty cell is this * cube root of cell volume + scalar empty_lobs_fac{1.0}; + + //- Value for outer region + scalar outerCombFac{1.0}; + + scalar obs_expand{0}; + + //- Default slat thickness grating + scalar def_grating_slat_w{0.005}; + + //- Cells with porosity less than this are blocked + scalar blockedCellPoros{0.05}; + + //- Faces with area blockage greater than this are blocked + scalar blockedFacePar{0.95}; + + //- Upper limit on CR (CT also gets limited) + scalar maxCR{1e30}; + + //- If a single obstacle blocks a cell by more than this, + //- then no CT in that direction + scalar blockageNoCT{0.95}; + + //- Overall scale factor + scalar scale{1.0}; + + + // Constructors + + //- Construct null + PDRparams() = default; + + + // Member Functions + + //- Set or read defaults from dictionary. + // Can also be used with an empty dictionary + void readDefaults(const dictionary& dict); + + //- Read program parameters from dictionary + void read(const dictionary& dict); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +extern Foam::PDRparams pars; //!< Globals for program parameters (ugly hack) + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRpatchDef.C b/applications/utilities/preProcessing/PDRsetFields/PDRpatchDef.C new file mode 100644 index 0000000000000000000000000000000000000000..2fcf12d1ac1c3118e4ed9785f00065de03bcd354 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRpatchDef.C @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRpatchDef.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::Enum +< + Foam::PDRpatchDef::predefined +> +Foam::PDRpatchDef::names +({ + { predefined::BLOCKED_FACE, "blockedFaces" }, + { predefined::MERGING_PATCH, "mergingFaces" }, + { predefined::WALL_PATCH, "wallFaces" }, +}); + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void Foam::PDRpatchDef::operator=(const std::string& newName) +{ + patchName = word::validate(newName); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRpatchDef.H b/applications/utilities/preProcessing/PDRsetFields/PDRpatchDef.H new file mode 100644 index 0000000000000000000000000000000000000000..076786cd1863873b466ee6521b11aaebf5c07b8b --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRpatchDef.H @@ -0,0 +1,123 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::PDRpatchDef + +Description + Bookkeeping for patch definitions + +SourceFiles + PDRpatchDef.H + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRpatchDef_H +#define PDRpatchDef_H + +#include "string.H" +#include "scalar.H" +#include "Enum.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class PDRpatchDef Declaration +\*---------------------------------------------------------------------------*/ + +class PDRpatchDef +{ +public: + + //- Patch predefines + enum predefined + { + BLOCKED_FACE = 0, + MERGING_PATCH = 1, + WALL_PATCH = 2, + LAST_PREDEFINED = 2, // First user patch number will be 1 more + NUM_PREDEFINED = 3 + }; + + //- Names for predefined types + static const Enum<predefined> names; + + + // Data Members + + word patchName; + + label patchType; + + scalar blowoffPress; + + scalar blowoffTime; + + + // Constructors + + //- Construct null + PDRpatchDef() + : + patchName(), + patchType(0), + blowoffPress(0), + blowoffTime(0) + {} + + //- Construct with given patch name + explicit PDRpatchDef(const word& name) + : + patchName(name), + patchType(0), + blowoffPress(0), + blowoffTime(0) + {} + + + //- Construct with given patch name + PDRpatchDef& operator=(const PDRpatchDef&) = default; + PDRpatchDef& operator=(PDRpatchDef&&) = default; + + //- Assign new patch name + void operator=(const std::string& newName); +}; + + +typedef PDRpatchDef PATCH; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRsetFields.C b/applications/utilities/preProcessing/PDRsetFields/PDRsetFields.C new file mode 100644 index 0000000000000000000000000000000000000000..ca1c724aad30350cda6d76fb6e6ec42b4994536b --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRsetFields.C @@ -0,0 +1,351 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Applications + PDRsetFields + +Description + Preparation of fields for PDRFoam + +SourceFiles + PDRsetFields.C + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "IOdictionary.H" + +#include "PDRsetFields.H" +#include "PDRlegacy.H" +#include "PDRutils.H" +#include "IOmanip.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char* argv[]) +{ + argList::addNote + ( + "Processes a set of geometrical obstructions to determine the" + " equivalent blockage effects when setting cases for PDRFoam" + ); + argList::noParallel(); + argList::noFunctionObjects(); + + argList::addOption + ( + "time", + "time", + "Specify a time" + ); + + argList::addOption("dict", "file", "Use alternative PDRsetFieldsDict"); + + argList::addBoolOption + ( + "legacy", + "Force use of legacy obstacles table" + ); + + argList::addBoolOption + ( + "dry-run", + "Read obstacles and write VTK only" + ); + + #include "setRootCase.H" + #include "createTime.H" + + const word dictName("PDRsetFieldsDict"); + #include "setSystemRunTimeDictionaryIO.H" + + Info<< "Reading " << dictName << "\n" << endl; + + IOdictionary setFieldsDict(dictIO); + + const bool dryrun = args.found("dry-run"); + + const fileName& casepath = runTime.globalPath(); + + pars.timeName = "0"; + args.readIfPresent("time", pars.timeName); + + // Program parameters (globals) + pars.read(setFieldsDict); + + if (args.found("legacy")) + { + pars.legacyObsSpec = true; + } + + // Always have the following: + // 0 = blockedFaces patch (no wall functions) + // 1 = mergingFaces patch + // 2 = wallFaces patch + + DynamicList<PDRpatchDef> patches; + patches.resize(PDRpatchDef::NUM_PREDEFINED); + + for + ( + PDRpatchDef::predefined predef : + { + PDRpatchDef::BLOCKED_FACE, + PDRpatchDef::MERGING_PATCH, + PDRpatchDef::WALL_PATCH, + } + ) + { + patches[predef] = PDRpatchDef::names[predef]; + } + + + // Dimensions and grid points for i-j-k domain + PDRblock pdrBlock; + + if (pars.legacyMeshSpec) + { + PDRlegacy::read_mesh_spec(casepath, pdrBlock); + } + else + { + IOdictionary iodict + ( + IOobject + ( + "PDRblockMeshDict", + runTime.system(), + runTime, + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE + ) + ); + + pdrBlock.read(iodict); + + #ifdef FULLDEBUG + PDRlegacy::print_info(pdrBlock); + #endif + } + + // Storage for obstacles and cylinder-like obstacles + DynamicList<PDRobstacle> obstacles, cylinders; + + // Read in obstacles + const scalar volObstacles = + ( + pars.legacyObsSpec + ? PDRobstacle::legacyReadFiles + ( + pars.obsfile_dir, pars.obsfile_names, + pdrBlock.bounds(), + obstacles, + cylinders + ) + : PDRobstacle::readFiles + ( + pars.obsfile_dir, pars.obsfile_names, + pdrBlock.bounds(), + obstacles, + cylinders + ) + ); + + + PDRobstacle::generateVtk(casepath/"VTK", obstacles, cylinders); + + if (dryrun) + { + Info<< nl + << "dry-run: stopping after reading/writing obstacles" << nl + << "\nEnd\n" << nl; + return 0; + } + + + // Bookkeeping of the ranges within the obstacle list + + // Original blockage at the start + const labelRange origBlocks(0, obstacles.size()); + + // Intersection blockage + labelRange interBlocks(origBlocks.after(), 0); + + scalar volSubtract = 0; + + // Do binary intersections between blocks and cylinders (or diag-beam) + // by creating -ve blocks at the overlap + + labelRange int1Blocks(origBlocks.after(), 0); + + if (pars.overlaps % 2 > 0) + { + Info<< " block/cylinder intersections" << endl; + + label nblocked = obstacles.size(); + + volSubtract += block_cylinder_overlap(obstacles, origBlocks, cylinders); + + nblocked = (obstacles.size() - nblocked); + + interBlocks += nblocked; + int1Blocks += nblocked; + } + + // Do binary intersections between blocks + // by creating -ve blocks at the overlap + + labelRange int2Blocks(int1Blocks.after(), 0); + if (pars.overlaps % 4 > 1) + { + Info<< " block/block intersections" << endl; + + label nblocked = obstacles.size(); + + volSubtract += block_overlap(obstacles, origBlocks, 1.0); + + nblocked = (obstacles.size() - nblocked); + + interBlocks += nblocked; + int2Blocks += nblocked; + } + + // Correct for triple intersections + // by looking for overlaps between the -ve blocks just created + + labelRange int3Blocks(int2Blocks.after(), 0); + if (pars.overlaps % 8 > 3) + { + Info<< " triple intersections" << endl; + + label nblocked = obstacles.size(); + + volSubtract += block_overlap(obstacles, interBlocks, 1.0/3.0); + + nblocked = (obstacles.size() - nblocked); + + interBlocks += nblocked; + int3Blocks += nblocked; + } + + + // The field arrays, in one structure pass around easily + PDRarrays arr(pdrBlock); + + Info<< "Apply blockage" << endl; + + // Create blockage and count arrays by working through + // real and extra blocks and cylinders + + // User-defined negative blocks. Use "sign" to distinguish + if (origBlocks.size()) + { + Info<< " negative blocks: " << origBlocks.size() << nl; + + for (const PDRobstacle& obs : obstacles[origBlocks]) + { + arr.addBlockage(obs, patches, -1); + } + } + + // Do the intersection blocks positive and negative + // These are done first so that negative area blockage cancels positive + + if (interBlocks.size()) + { + Info<< " blocks " << interBlocks.size() << nl; + + for (const PDRobstacle& obs : obstacles[interBlocks]) + { + arr.addBlockage(obs, patches, 0); + } + } + + // The positive real bocks + if (origBlocks.size()) + { + Info<< " positive blocks: " << origBlocks.size() << nl; + + for (const PDRobstacle& obs : obstacles[origBlocks]) + { + arr.addBlockage(obs, patches, 1); + } + } + + // The cylinders + if (cylinders.size()) + { + Info<< " cylinders: " << cylinders.size() << nl; + + for (const PDRobstacle& obs : cylinders) + { + arr.addCylinder(obs); + } + } + + // Calculation of the fields of drag, turbulence + // generation and combustion enhancement + + arr.blockageSummary(); + + // Mapping of OpenFOAM cells/faces to i-j-k indices + PDRmeshArrays meshIdx; + meshIdx.gridPointRelTol = pars.gridPointTol; + + meshIdx.read(runTime, pdrBlock); + + PDRarrays::calculateAndWrite(arr, meshIdx, casepath, patches); + + Info<< nl + << setw(6) << origBlocks.size() << " blocks and " + << cylinders.size() << " cylinders/diagonal blocks" << nl; + + Info<< setw(6) << int2Blocks.size() + << " intersections amongst blocks" << nl; + + Info<< setw(6) << int1Blocks.size() + << " intersections between blocks and cyl/beams" << nl; + + Info<< setw(6) << int1Blocks.size() + << "/3 triple intersections" << nl; + + Info<< "Volume of obstacles read in: " << volObstacles + << ", volume of intersections: " << volSubtract << nl; + + Info<< nl << "After corrections:" << nl; + arr.blockageSummary(); + + Info<< nl << "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRsetFields.H b/applications/utilities/preProcessing/PDRsetFields/PDRsetFields.H new file mode 100644 index 0000000000000000000000000000000000000000..85bcda7aed8f9b322d1d005c3a8e1a3f109be58a --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRsetFields.H @@ -0,0 +1,142 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Preparation of fields for PDRFoam + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRsetFields_H +#define PDRsetFields_H + +#include "PDRarrays.H" +#include "PDRblock.H" +#include "PDRmeshArrays.H" +#include "PDRobstacle.H" +#include "PDRpatchDef.H" +#include "PDRparams.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +using namespace Foam; + + +//YCYCLIC is set to 1 for running the test cases with a cyclic boundry condition in the y direction +//TWO_D is set to 1 for running the 2D test cases (no z direction) - usually same case as YCYCLIC +//Now specified in CAD_PDRDict and read in as globals. + +// The program also labels intersection obstacles as types 96 and 86, but not then use these values +// Obstacles in group definitions have a multiple of 100 added to the type number + +#define floatSMALL 1.e-10 + +// Default initial values of field variables, used outside congested area, +//and everywhere for uniform fields. They atre strings because same routines +//are used to create b.c.s for scalars and tensors. +#define DEFAULT_K 0.00015 +#define DEFAULT_EPS 1e-5 +#define DEFAULT_T 300 +#define DEFAULT_P 100000 +#define DEFAULT_SU 0.5 +#define DEFAULT_LOBS 0.1 // Does not matter what it is outside congestion + // but zero would cause problems with Ep +#define DEFAULT_EP 0.01 // Gives length scale 0.1, calc. as (Xp-0.999)/Ep with Xp=1 + +// Boundary conditions on walls for all variables where it is not "zero_gradient" +#define K_WALL_FN "kqRWallFunction" +#define EPS_WALL_FN "epsilonWallFunction" +#define ALPHAT_WALL "nutkWallFunction" +#define MUT_WALL_FN "mutkWallFunction" +#define NUT_WALL_FN "nutkWallFunction" + +#define K_WALL_FN_LEGACY "compressible::kqRWallFunction" +#define EPS_WALL_FN_LEGACY "compressible::epsilonWallFunction" +#define ALPHAT_WALL_FN_LEGACY "alphatWallFunction;\n\t\tPrt\t0.85" + + +// The following parameters are used to decide when there arMAX_Ne sufficient (parts of) +// obstacles ina cell for them to define the length scale of the generated turbulence. +#define MIN_AB_FOR_SIZE 0.002 +#define MAX_VB_FOR_SIZE 0.9 +#define COUNT_FOR_SIZE 0.1 +#define MIN_COUNT_FOR_SIZE 0.05 + +// These define how blocked a face or cell has to be for removal from the mesh +//#define BLOCKED_CELL_PAR 0.05 //<- Now pars.blockedCellPoros +//#define BLOCKED_FACE_PAR 0.95 //<- Now pars.blockedFacePar + + +//- Calculate block/block overlaps +// +// Binary self-intersections are to be checked for blocks. +// Resulting negative blocks are appended to blocks. +// These new blocks have the opposite sign from input blocks, and +// blockage multiplied by multiplier. +// +// If the number of newly generated blocks is required, check the size +// of blocks on output vs input to see how many have been added. +// +// \param[in,out] blocks +// \param[in] range - the range within blocks to be examined +// +// \return overlap volume +scalar block_overlap +( + DynamicList<PDRobstacle>& blocks, + const labelRange& range, + const scalar multiplier = 1.0 +); + + +//- Calculate block/cylinder overlaps +// +// Binary intersections are to be checked for blocks and cylinders. +// Resulting negative blocks are appended to blocks. +// These new blocks have the opposite sign from input blocks, and +// blockage multiplied by multiplier. +// +// If the number of newly generated blocks is required, check the size +// of blocks on output vs input to see how many have been added. +// +// \param[in,out] arrp +// \param[in,out] blocks +// \param[in] range - the range within blocks to be examined +// \param[in] cylinders - the cylinders to be examined +// +// \return overlap volume +scalar block_cylinder_overlap +( + DynamicList<PDRobstacle>& blocks, + const labelRange& range, + const UList<PDRobstacle>& cylinders +); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRutils.H b/applications/utilities/preProcessing/PDRsetFields/PDRutils.H new file mode 100644 index 0000000000000000000000000000000000000000..9d28f5b2c6d78a0cc31b15bd9ed61ca65a3d7668 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRutils.H @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Namespace + Foam::PDRutils + +Description + Utilities for PDR (eg, for setFields) + +SourceFiles + PDRUtils.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRutils_H +#define PDRutils_H + +#include "PDRarrays.H" +#include "PDRblock.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class PDRobstacle; + +namespace PDRutils +{ + + +} // End namespace PDRutils +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRutilsInternal.H b/applications/utilities/preProcessing/PDRsetFields/PDRutilsInternal.H new file mode 100644 index 0000000000000000000000000000000000000000..f6e11a97899ff9ce383f069903c3412ac51e4ce9 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRutilsInternal.H @@ -0,0 +1,221 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Namespace + Foam::PDRutils + +Description + Utilities for PDR (eg, for setFields). Internal usage only. + + The C lineage of the original code is still evident in the use of + pointers instead of references. + This will be addressed in later versions of the code (2019-12). + +SourceFiles + PDRUtils.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRutilsInternal_H +#define PDRutilsInternal_H + +#include "PDRutils.H" +#include "PDRarrays.H" +#include "PDRblock.H" +#include "symmTensor2D.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace PDRutils +{ + +//- Determine 1-D overlap locations for a geometric entity +// +// \param[in] xmin - min position of the geometric entity +// \param[in] xmax - max position of the geometric entity +// \param[in] grid - grid point information +// \param[out] olap - Fraction of cell-width with overlap +// 0 for no overlap, 1 for full overlap. +// \param[out] cmin - first cell index (inclusive) with overlap, +// values in the range \c [0,nCells] +// \param[out] cmax - last cell index (inclusive) with overlap, +// values in the range \c [0,nCells] +// \param[out] cfmin - first cell index (inclusive) with staggered face, +// values in the range \c [0,nCells] +// \param[out] cfmax - last cell index (inclusive) with staggered face, +// values in the range \c [0,nCells] +void one_d_overlap +( + scalar xmin, + scalar xmax, + const PDRblock::location& grid, + List<scalar>& olap, + int *cmin, int *cmax, + int *cfmin, int *cfmax +); + + +//- Combine two 1D overlaps. +// Multiplying the two 1-d overlaps yields the proportion of each (2D) cell +// that is covered. +// +// \note We go one over the relevant min/max limits since these +// values might be used. +// The 1D arrays will have bee initially zeroed throughout. +void two_d_overlap +( + const UList<scalar>& a_olap, label amin, label amax, + const UList<scalar>& b_olap, label bmin, label bmax, + SquareMatrix<scalar>& ab_olap +); + + +//- Calculate the proportion of each (two-dimensional) grid cell +//- overlapped by the circle or angled rectangle. +// +// Coordinates are labelled a and b. +// +// \param[in] ac, bc coordinates of centre of circle or rectangle +// \param[in] dia diameter of circle (zero for rectangle) +// \param[in] theta, wa, wb parameters for rectangle +// \param[in] amin, amax first and last cells in a-grid overlapped by object +// \param[in] agrid locations of grid lines of a-grid +// \param[in] amin, amax first and last cells in b-grid overlapped by object +// \param[in] bgrid locations of grid lines of b-grid +// +// \param[out] abolap +// 2-D array of (proportionate) area blockage by grid cell +// \param[out] a_lblock +// 2-D array of (proportionate) blockage to a-direction flow +// (This will be area blockage when extruded in the third +// coordinate). +// +// \param[out] a_count +// 2-D array The contribution of this object to the count of +// obstacles blocking a-direction flow. This is only non-zero if the +// object is inside the lateral boundaries of the cell. It is large +// negative if the cell is totally blocked in this direction. +// +// +// \param[out] c_drag +// +// 2-D array of tensor that will give tensor drag in each cell (when +// multiplied Cd, cylinder length, and 0.5 rho*U^2) Dimension: L. +// +// \note this routine does not zero array elements outside the amin +// to amax, bmin to bmax area. +void circle_overlap +( + scalar ac, scalar bc, scalar dia, + scalar theta, scalar wa, scalar wb, + const PDRblock::location& agrid, label amin, label amax, + const PDRblock::location& bgrid, label bmin, label bmax, + SquareMatrix<scalar>& ab_olap, + SquareMatrix<scalar>& ab_perim, + SquareMatrix<scalar>& a_lblock, + SquareMatrix<scalar>& ac_lblock, + SquareMatrix<scalar>& c_count, + SquareMatrix<symmTensor2D>& c_drag, + SquareMatrix<scalar>& b_lblock, + SquareMatrix<scalar>& bc_lblock +); + + +//- Area of intersection between circle and rectangle. +// +// Calculates the area of intersection between the circle, centre (xc, yc), radius rad, +// and the rectangle with sides at x = x1 & x2, and y = y1 and y2. +// +// The return value is the fraction of the rectangle's area covered by the circle. +double inters_cy +( + double xc, //!< circle centre (x) + double yc, //!< circle centre (y) + double rad, //!< circle radius + double x1, double x2, + double y1, double y2, + scalar* perim_p, + scalar* x_proj_edge_p, + scalar* y_proj_edge_p, + scalar* x_overlap_p, + scalar* y_overlap_p +); + + +//- The area overlap in the plane of a diagonal block and a cell. +// +// Calculates the overlap, in the plane of a diagonal block and a cell, +// plus blockage and drag parameters. +// Note that x and y herein may be any two of the three coordinates - would have been better not to label them x and y. +// +// On entry: +// xc, yc Coordinates of axis of d.b. +// theta, wa, wb Angle and widths +// +// The returned parameters will be multipled by the length of the obstacle's intersection with +// the third dimension of the 3-D cell to give this obstacle's contribution to the count, drag +// and area blockages. +// The return value is the area of intersection, which will multiply to volume blockage. +// +double inters_db +( + double xc, double yc, double theta, + double wa, double wb, + double x1, double x2, + double y1, double y2, + scalar* count_p, + symmTensor2D& vdrag, scalar* perim_p, + scalar* x_lblk, scalar* y_lblk, + scalar* x_centre_p, scalar* y_centre_p +); + + +/* Calculates the blockage to x-direction flow presented by the specified circle on + the specified rectangle. + Becomes the area blockage when extruded to in the third dimension. + In other words, it is the projection on the y axis of the intersection between the + circle and the rectangle. + Returns fraction blocked + Note that x and y in this routine may in fact be any two of the three dimensions. + */ +double l_blockage +( + double xc, double yc, double rad, + double x1, double x2, + double y1, double y2, + scalar* count_p, scalar* drag_p, scalar* centre_p +); + + +} // End namespace PDRutils +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRutilsIntersect.C b/applications/utilities/preProcessing/PDRsetFields/PDRutilsIntersect.C new file mode 100644 index 0000000000000000000000000000000000000000..6cadff43e5e8992ced883d008cad3f4ff210c127 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRutilsIntersect.C @@ -0,0 +1,712 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRsetFields.H" +#include "PDRutilsInternal.H" +#include "mathematicalConstants.H" + +#ifndef FULLDEBUG +#define NDEBUG +#endif +#include <cassert> + +using namespace Foam::constant; + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Calculate the area of the sector of a circle whose ends are at +// (dxa, dya) and (dxb, dyb) relative to the centre. radsqu is radius +// squared. +// +// (We trust that this is consistent with the other parameters..) +inline static scalar sector +( + scalar dxa, scalar dya, + scalar dxb, scalar dyb +) +{ + scalar angle = (::atan2(dyb, dxb) - ::atan2(dya, dxa)); + + if (angle < -1.0E-10) + { + angle += mathematical::twoPi; + } + + return angle; +} + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +double Foam::PDRutils::inters_cy +( + double xc, double yc, double rad, + double x1, double x2, + double y1, double y2, + scalar* perim_p, + scalar* x_proj_edge_p, scalar* y_proj_edge_p, + scalar* x_overlap_p, scalar* y_overlap_p +) +{ + double angle, area, del; + double x_int[6][2], y_int[6][2]; // Coordinates of intersections between the circle and sides of the rectangle. + double x_arc[6][2], y_arc[6][2]; // Coordinates of end orc (within cell) for each quadrant + double dx[6], dy[6]; + + double x_olap_min = GREAT; + double x_olap_max = -GREAT; + double y_olap_min = GREAT; + double y_olap_max = -GREAT; + int n_vert, n_oppv; + int no_intersection; + + const double dx1 = (x1 - xc); + const double dx2 = (x2 - xc); + const double dy1 = (y1 - yc); + const double dy2 = (y2 - yc); + + const double dx1squ = dx1 * dx1; + const double dx2squ = dx2 * dx2; + const double dy1squ = dy1 * dy1; + const double dy2squ = dy2 * dy2; + const double radsqu = rad * rad; + + + /* Going clockwise from (x1, y1), vertices are labelled 1,2,3,4, with 0 the same as 4 + and 5 the same as 1 (so that we can find the vertices on either side of any of 1 to 4).*/ + + dx[1] = dx1; dy[1] = dy1; + dx[2] = dx1; dy[2] = dy2; + dx[3] = dx2; dy[3] = dy2; + dx[4] = dx2; dy[4] = dy1; + dx[0] = dx2; dy[0] = dy1; + dx[5] = dx1; dy[5] = dy1; + + // The positions of the ends of the arcs, if these points are + // inside the cell, they will be changed, if necessary, below. + + x_arc[2][0] = x_arc[1][1] = -rad; y_arc[2][0] = y_arc[1][1] = 0.0; + x_arc[3][0] = x_arc[2][1] = 0.0; y_arc[3][0] = y_arc[2][1] = rad; + x_arc[4][0] = x_arc[3][1] = rad; y_arc[4][0] = y_arc[3][1] = 0.0; + x_arc[1][0] = x_arc[4][1] = 0.0; y_arc[1][0] = y_arc[4][1] = -rad; + + // We catch arcs that are entirely inside the rectangle + // Note: this is wrong for a circle completely outside, but that + // will be dealt with separately + + int arc_in[6] = { /* zero-initialied */ }; + arc_in[1] = (dx1 < -rad && dy1 < -rad) ? 1 : 0; + arc_in[2] = (dx1 < -rad && dy2 > rad) ? 1 : 0; + arc_in[3] = (dx2 > rad && dy2 > rad) ? 1 : 0; + arc_in[4] = (dx2 > rad && dy1 < -rad) ? 1 : 0; + + // Work out which vertices are in the circle + + int vert_in[6]; + vert_in[1] = (dx1squ + dy1squ <= radsqu); + vert_in[2] = (dx1squ + dy2squ <= radsqu); + vert_in[3] = (dx2squ + dy2squ <= radsqu); + vert_in[4] = (dx2squ + dy1squ <= radsqu); + vert_in[0] = vert_in[4]; + vert_in[5] = vert_in[1]; + + int n_in = 0; + if (vert_in[1]) ++n_in; + if (vert_in[2]) ++n_in; + if (vert_in[3]) ++n_in; + if (vert_in[4]) ++n_in; + + + /* We now calculate the points of intersection of the circle with, successively, + x=x1, y=y2, x=x2. y=y1. + + Where there are two intersections with one side, need to be careful about + the order of the two points (i.e. clockwise round the rectangle) so that + later on we get the right sector (short or long way round the circumference) */ + + int n_int[6] = { /* zero-initialied */ }; + n_int[1] = 0; + if ( dx1squ <= radsqu) + { + del = std::sqrt( radsqu - dx1squ); + if ( ( ( -del ) <= dy2 ) && ( del >= dy1 ) ) + { + x_int[1][0] = x_int[1][1] = dx1; + if ( (-del ) > dy1 ) + { + y_int[1][0] = -del; + n_int[1]++; + // This intersection will be an end of the 3rd- or 4th-quadrant arc + if ( dx1 > 0.0 ) { x_arc[4][1] = dx1; y_arc[4][1] = -del; arc_in[4] = 1; } + else { x_arc[1][1] = dx1; y_arc[1][1] = -del; arc_in[1] = 1; } + } + if ( ( del ) < dy2 ) + { + y_int[1][n_int[1]] = del; + n_int[1]++; + if ( dx1 > 0.0 ) { x_arc[3][0] = dx1; y_arc[3][0] = del; arc_in[3] = 1; } + else { x_arc[2][0] = dx1; y_arc[2][0] = del; arc_in[2] = 1; } + } + } + } + + n_int[2] = 0; + if ( dy2squ <= radsqu) + { + del = std::sqrt( radsqu - dy2squ); + if ( ( ( -del ) <= dx2 ) && ( del >= dx1 ) ) + { + y_int[2][0] = y_int[2][1] = dy2; + if ( (-del ) > dx1 ) + { + x_int[2][0] = -del; + n_int[2]++; + if ( dy2 > 0.0 ) { x_arc[2][1] = -del; y_arc[2][1] = dy2; arc_in[2] = 1; } + else { x_arc[1][1] = -del; y_arc[1][1] = dy2; arc_in[1] = 1; } + } + if ( ( del ) < dx2 ) + { + x_int[2][n_int[2]] = del; + n_int[2]++; + if ( dy2 > 0.0 ) { x_arc[3][0] = del; y_arc[3][0] = dy2; arc_in[3] = 1; } + else { x_arc[4][0] = del; y_arc[4][0] = dy2; arc_in[4] = 1; } + } + } + } + + n_int[3] = 0; + if ( dx2squ <= radsqu) + { + del = std::sqrt( radsqu - dx2squ); + if ( ( ( -del ) <= dy2 ) && ( del >= dy1 ) ) + { + x_int[3][0] = x_int[3][1] = dx2; + if ( ( del ) < dy2 ) + { + y_int[3][0] = del; + n_int[3]++; + if ( dx2 > 0.0 ) { x_arc[3][1] = dx2; y_arc[3][1] = del; arc_in[3] = 1; } + else { x_arc[2][1] = dx2; y_arc[2][1] = del; arc_in[2] = 1; } + } + if ( (-del ) > dy1 ) + { + y_int[3][n_int[3]] = -del; + n_int[3]++; + if ( dx2 > 0.0 ) { x_arc[4][0] = dx2; y_arc[4][0] = -del; arc_in[4] = 1; } + else { x_arc[1][0] = dx2; y_arc[1][0] = -del; arc_in[1] = 1; } + } + } + } + + n_int[4] = 0; + if ( dy1squ <= radsqu) + { + del = std::sqrt( radsqu - dy1squ); + if ( ( ( -del ) <= dx2 ) && ( del >= dx1 ) ) + { + y_int[4][0] = y_int[4][1] = dy1; + if ( ( del ) < dx2 ) + { + x_int[4][0] = del; + n_int[4]++; + if ( dy1 > 0.0 ) { x_arc[3][1] = del; y_arc[3][1] = dy1; arc_in[3] = 1; } + else { x_arc[4][1] = del; y_arc[4][1] = dy1; arc_in[4] = 1; } + } + if ( (-del ) > dx1 ) + { + x_int[4][n_int[4]] = -del; + n_int[4]++; + if ( dy1 > 0.0 ) { x_arc[2][0] = -del; y_arc[2][0] = dy1; arc_in[2] = 1; } + else { x_arc[1][0] = -del; y_arc[1][0] = dy1; arc_in[1] = 1; } + } + } + } + + n_int[0] = n_int[4]; + n_int[5] = n_int[1]; + + y_int[0][0] = y_int[0][1] = dy1; + x_int[0][0] = x_int[4][0]; + x_int[0][1] = x_int[4][1]; + x_int[5][0] = x_int[5][1] = dx1; + y_int[5][0] = y_int[1][0]; + y_int[5][1] = y_int[1][1]; + + /* There are five separate cases, depending of the number of vertices inside the circle */ + switch ( n_in ) + { + case 0: + { + /* We start with the whole area of the circle, and then subtract any bits that stick out. */ + area = radsqu * mathematical::pi; + *perim_p = mathematical::twoPi * rad; + no_intersection = true; + for (n_vert = 1; n_vert < 5; n_vert++) + { + assert(n_int[n_vert] != 1); + if (n_int[n_vert] == 2) + { + /* The area of the bit to be subtracted is a sector minus a triangle. */ + no_intersection = false; + angle = sector( x_int[n_vert][1], y_int[n_vert][1], x_int[n_vert][0], y_int[n_vert][0]); + area -= angle * radsqu * 0.5; + *perim_p -= angle * rad; + /* Two trinagles specified here, but one has zero area. */ + area += ( - ( y_int[n_vert][1] - y_int[n_vert][0] ) * x_int[n_vert][0] + + ( x_int[n_vert][1] - x_int[n_vert][0] ) * y_int[n_vert][0] ) / 2.0; + } + } + /* Need to allow for when the circle is completely out side the rectanglle + by checking if the centre is outside the rectangle */ + if ( no_intersection ) + { + if ( (dx1>0) ||(dx2<0) || (dy1>0) || (dy2<0) ) + { + *perim_p = *x_proj_edge_p = *y_proj_edge_p = 0.0; + area = *x_overlap_p = *y_overlap_p = 0.0; + return area; + } + } + + break; + } + + case 1: + { + /* Find which vertex is inside */ + n_vert = 1; + while ( !vert_in[n_vert] ) { n_vert++; assert( n_vert < 5 ); } + assert( n_int[n_vert-1] == 1 ); + if ( n_int[n_vert] != 1 ) + { + assert( n_int[n_vert] == 1 ); + } + angle = sector( x_int[n_vert-1][0], y_int[n_vert-1][0], x_int[n_vert][0], y_int[n_vert][0]); + area = angle * radsqu * 0.5; + *perim_p = angle * rad; + /* We subtract (or add) two triangles; the other two evaluate to zero */ + area -= ( - ( x_int[n_vert][0] - dx[n_vert] ) * dy[n_vert] + + ( x_int[n_vert-1][0] - dx[n_vert] ) * dy[n_vert] + + ( y_int[n_vert][0] - dy[n_vert] ) * dx[n_vert] + - ( y_int[n_vert-1][0] - dy[n_vert] ) * dx[n_vert] ) / 2.0; + + break; + } + + case 2: + { + /* This time n_vert is the number of the side which is completely inside the circle */ + n_vert = 1; + while ( !(vert_in[n_vert] && vert_in[n_vert+1]) ) { n_vert++; assert( n_vert < 5 ); } + assert( n_int[n_vert-1] == 1 ); + assert( n_int[n_vert+1] == 1 ); + angle = sector( x_int[n_vert-1][0], y_int[n_vert-1][0], x_int[n_vert+1][0], y_int[n_vert+1][0]); + area = angle * radsqu * 0.5; + *perim_p = angle * rad; + /* We subtract (or add) three triangles; the other three evaluate to zero */ + area += ( ( x_int[n_vert+1][0] - dx[n_vert+1] ) * dy[n_vert+1] + - ( x_int[n_vert-1][0] - dx[n_vert] ) * dy[n_vert] + - ( y_int[n_vert+1][0] - dy[n_vert+1] ) * dx[n_vert+1] + + ( y_int[n_vert-1][0] - dy[n_vert] ) * dx[n_vert] + + ( dx[n_vert+1] -dx[n_vert] ) * dy[n_vert] + - ( dy[n_vert+1] -dy[n_vert] ) * dx[n_vert] ) / 2.0; + + switch ( n_vert ) + { + case 1: x_olap_min = dx1; break; + case 2: y_olap_max = dy2; break; + case 3: x_olap_max = dx2; break; + case 4: y_olap_min = dy1; break; + } + + break; + } + + case 3: + { + /* Find which vertex is NOT inside */ + n_vert = 1; + while ( vert_in[n_vert] ) { n_vert++; assert( n_vert < 5 ); } + assert( n_int[n_vert-1] == 1 ); + assert( n_int[n_vert] == 1 ); + n_oppv = (n_vert + 2) % 4; + angle = sector( x_int[n_vert][0], y_int[n_vert][0], x_int[n_vert-1][0], y_int[n_vert-1][0]); + area = angle * radsqu * 0.5; + *perim_p = angle * rad; + /* We subtract (or add) four triangles; the other four evaluate to zero */ + area += ( - ( x_int[n_vert][0] - dx[n_vert+1] ) * dy[n_vert+1] + + ( x_int[n_vert-1][0] - dx[n_vert-1] ) * dy[n_vert-1] + + ( y_int[n_vert][0] - dy[n_vert+1] ) * dx[n_vert+1] + - ( y_int[n_vert-1][0] - dy[n_vert-1] ) * dx[n_vert-1] + + ( dx[n_oppv] -dx[n_vert+1] ) * dy[n_oppv] + - ( dx[n_oppv] -dx[n_vert-1] ) * dy[n_oppv] + - ( dy[n_oppv] -dy[n_vert+1] ) * dx[n_oppv] + + ( dy[n_oppv] -dy[n_vert-1] ) * dx[n_oppv] ) / 2.0; + + x_olap_min = dx1; + y_olap_max = dy2; + x_olap_max = dx2; + y_olap_min = dy1; + + break; + } + + case 4: + { + /* Easy! We have the whole rectangle. */ + area = *x_overlap_p = *y_overlap_p = 1.0; // Normalised + *perim_p = *x_proj_edge_p = *y_proj_edge_p = 0.0; + return area; + + break; + } + } + + // The area may be very small negative by rounding errors + assert(area >=-1.0E-4); + if (area < 0.0) area = 0.0; + /* Return the overlap as a fraction of the rectangle's area. */ + area /= ( (x2 - x1 ) * ( y2 - y1 ) ); + + // Sum the parts of the circumference that are inside the circle, projected onto axes + *x_proj_edge_p = + ( + (y_arc[1][1] - y_arc[1][0]) * arc_in[1] + + (y_arc[2][1] - y_arc[2][0]) * arc_in[2] + + (y_arc[3][0] - y_arc[3][1]) * arc_in[3] + + (y_arc[4][0] - y_arc[4][1]) * arc_in[4] + ); + + *y_proj_edge_p = + ( + (x_arc[1][0] - x_arc[1][1]) * arc_in[1] + + (x_arc[2][1] - x_arc[2][0]) * arc_in[2] + + (x_arc[3][1] - x_arc[3][0]) * arc_in[3] + + (x_arc[4][0] - x_arc[4][1]) * arc_in[4] + ); + + if (arc_in[1]) + { + x_olap_min = min(x_olap_min, x_arc[1][1]); + x_olap_max = max(x_olap_max, x_arc[1][0]); + y_olap_min = min(y_olap_min, y_arc[1][0]); + y_olap_max = max(y_olap_max, y_arc[1][1]); + } + if (arc_in[2]) + { + x_olap_min = min(x_olap_min, x_arc[2][0]); + x_olap_max = max(x_olap_max, x_arc[2][1]); + y_olap_min = min(y_olap_min, y_arc[2][0]); + y_olap_max = max(y_olap_max, y_arc[2][1]); + } + if (arc_in[3]) + { + x_olap_min = min(x_olap_min, x_arc[3][0]); + x_olap_max = max(x_olap_max, x_arc[3][1]); + y_olap_min = min(y_olap_min, y_arc[3][1]); + y_olap_max = max(y_olap_max, y_arc[3][0]); + } + if (arc_in[4]) + { + x_olap_min = min(x_olap_min, x_arc[4][1]); + x_olap_max = max(x_olap_max, x_arc[4][0]); + y_olap_min = min(y_olap_min, y_arc[4][1]); + y_olap_max = max(y_olap_max, y_arc[4][0]); + } + + *x_overlap_p = ( x_olap_max - x_olap_min ) / ( x2 - x1 ); + *y_overlap_p = ( y_olap_max - y_olap_min ) / ( y2 - y1 ); + assert ( *x_overlap_p >= -floatSMALL ); + assert ( *y_overlap_p >= -floatSMALL ); + + return area; +} // End intersect + + +// ************************************************************************* // + +double Foam::PDRutils::l_blockage +( + double xc, double yc, double rad, + double x1, double x2, + double y1, double y2, + scalar* count_p, scalar* drag_p, scalar* centre_p +) +{ + double xi = 0.0, lb, lb1, lb2, del; + bool within = true; // Indicates that the the intersection does not overlap the ends of the line + + /* xi is the side we need to calc. intersections with */ + if ( xc < x1 ) { xi = x1; } + else if ( xc > x2 ) { xi = x2; } + + if ( xi == 0.0 ) + { + del = rad; // The relevant lowest ( or highest) point is at end of vertical radius + } + else // The relevant lowest ( or highest) point at intersection with x = xi + { + del = rad*rad - ( xi - xc ) * ( xi - xc ); + if ( del < 0.0 ) { del = 0.0; } // No intersection + else { del = std::sqrt(del); } + } + + if ( ( yc + del ) > y2 ) { lb2 = y2; within = false; } else { lb2 = yc + del; } + if ( ( yc - del ) < y1 ) { lb1 = y1; within = false; } else { lb1 = yc - del; } + + lb = (lb2 - lb1) / (y2 - y1); + *centre_p = (lb2 + lb1) * 0.5; + + if ( lb < 0.0 ) lb = 0.0; + + /* *count_p is 0 if the circle overlaps either y-side of the rectangle, + 1 if the circle is entirely inside the rectangle + reduced if it overlaps x-sides. + A negative value indicates total blockage*/ + if ( within && (lb > 0.0) ) + { + *count_p = 1.0; + if ( ( xc - rad ) < x1 ) *count_p -= 0.5; + if ( ( xc + rad ) > x2 ) *count_p -= 0.5; + } + else + { + *count_p = 0.0; + } + *drag_p = lb * 1.2; //*drag_p = lb * CD_ROUND; + if ( lb > 0.99 ) { *count_p = -1000.0; *drag_p = 1000.0; } + assert(lb >-100.0); + return lb; +}// End l_blockage + + +// ************************************************************************* // + +double Foam::PDRutils::inters_db +( + double xc, double yc, double theta, + double wa, double wb, + double x1, double x2, + double y1, double y2, + scalar* count_p, + symmTensor2D& vdrag, scalar* perim_p, + scalar* x_lblk_p, scalar* y_lblk_p, + scalar* x_centre_p, scalar* y_centre_p +) +{ + double x_int[6][2], y_int[6][2]; // Coordinates of intersections between the circle and sides of the rectangle. + double area, lpa, lpb, len; + + double m = ::tan( theta ); + double cth = ::cos( theta ); + double sth = ::sin( theta ); + + double was = wa * sth * 0.5; + double wac = wa * cth * 0.5; + double wbs = wb * sth * 0.5; + double wbc = wb * cth * 0.5; + double waos = wa / sth * 0.5; + double waoc = wa / cth * 0.5; + double wbos = wb / sth * 0.5; + double wboc = wb / cth * 0.5; + + double xb[6], yb[6], xp1, xp2, yp1, yp2; + + double dx1 = (x1 - xc); + double dx2 = (x2 - xc); + double dy1 = (y1 - yc); + double dy2 = (y2 - yc); + + *count_p = 0; + +// The vertices of the rectangle (all coordinates relative to centre of rectangle) + xb[1] = -wac - wbs; + yb[1] = -was + wbc; + xb[3] = wac + wbs; + yb[3] = was - wbc; + xb[2] = wac - wbs; + yb[2] = was + wbc; + xb[4] = -wac + wbs; + yb[4] = -was - wbc; + + // First parameter of x_int or y_int determines which side of the cell we intersecting with + // Second parameter 0 is first intersection, 1 is second, going clockwise + + if ( xb[1] < dx1 ) // i.e. if left corner of block is to the left of x1 + { + // Where one of lower sides of block intersects with x=x1 + // Innermost max determines which intersection is the genuine one + // (not if whole block is to left of x1) + y_int[1][0] = min(max(max(dx1 * m - wboc, -dx1 / m - waos), dy1), dy2); + // Upper intersection + y_int[1][1] = min(max(min(dx1 * m + wboc, -dx1 / m + waos), dy1), dy2); + } + else + { + y_int[1][1] = dy1; + y_int[1][0] = dy2; + // We add a quarter to count for each vertex inside the cell + if ( (yb[1] > dy1) && (yb[1] < dy2) ) // ?? Seems inefficient ?? + { *count_p += 0.25; } + } + if ( xb[3] > dx2 ) + { + y_int[3][1] = min(max(max(dx2 * m - wboc, -dx2 / m - waos), dy1), dy2); + y_int[3][0] = min(max(min(dx2 * m + wboc, -dx2 / m + waos), dy1), dy2); + } + else + { + y_int[3][0] = dy1; + y_int[3][1] = dy2; + if (yb[3] > dy1 && yb[3] < dy2) + { + *count_p += 0.25; + } + } + if (yb[2] > dy2) + { + x_int[2][0] = min(max(max(dy2 / m - wbos, -dy2 * m - waoc), dx1), dx2); + x_int[2][1] = min(max(min(dy2 / m + wbos, -dy2 * m + waoc), dx1), dx2); + } + else + { + x_int[2][0] = dx2; + x_int[2][1] = dx1; + if ( (xb[2] > dx1) && (xb[2] < dx2) ) + { *count_p += 0.25; } + } + if ( yb[4] < dy1 ) + { + x_int[4][1] = min(max(max(dy1 / m - wbos, -dy1 * m - waoc ), dx1), dx2); + x_int[4][0] = min(max(min(dy1 / m + wbos, -dy1 * m + waoc ), dx1), dx2); + } + else + { + x_int[4][1] = dx2; + x_int[4][0] = dx1; + if ( (xb[4] > dx1) && (xb[4] < dx2) ) + { *count_p += 0.25; } + } + + y_int[0][0] = y_int[0][1] = dy1; + x_int[0][0] = x_int[4][0]; + x_int[0][1] = x_int[4][1]; + x_int[5][0] = x_int[5][1] = dx1; + y_int[5][0] = y_int[1][0]; + y_int[5][1] = y_int[1][1]; + + +// We can now define a smaller enclosing rectangle + + xp1 = min(x_int[2][0], x_int[4][1]); // Leftmost of the intersections with top and bottom of cell + if ( yb[1] > dy1 && yb[1] < dy2 ) xp1 = min(xp1, xb[1] ); // left corner of block + xp1 = max(xp1, dx1); // Make sure it is not to the left of x1 + + yp2 = max(y_int[1][1], y_int[3][0] ); + if ( xb[2] > dx1 && xb[2] < dx2 ) yp2 = max(yp2, yb[2] ); + yp2 = min(yp2, dy2); + + xp2 = max(x_int[2][1], x_int[4][0] ); + if ( yb[3] > dy1 && yb[3] < dy2 ) xp2 = max(xp2, xb[3] ); + xp2 = min(xp2, dx2); + + yp1 = min(y_int[1][0], y_int[3][1]); + if ( xb[4] > dx1 && xb[4] < dx2 ) yp1 = min(yp1, yb[4] ); + yp1 = max(yp1, dy1 ); + + // Conveniently, the dimensions of the enclosing rectangle give us the line blockages + *x_lblk_p = (xp2 - xp1 ) / (x2 - x1 ); + if ( *x_lblk_p < 0.0 ) { *x_lblk_p = 0.0; *count_p = 0.0; }; // ?? Better to trap no intersection earlier?? + *y_lblk_p = (yp2 - yp1 ) / (y2 - y1 ); + if ( *y_lblk_p < 0.0 ) { *y_lblk_p = 0.0; *count_p = 0.0; }; + + *x_centre_p = xc + (xp2 + xp1 ) * 0.5; + *y_centre_p = yc + (yp2 + yp1 ) * 0.5; + + *perim_p = lpa = lpb = 0.0;; + area = (xp2 - xp1 ) * ( yp2 - yp1 ); + { + double dxx, dyy; + // Lower left + dyy = max(0.0, min(yb[1], y_int[1][0]) - yp1); + dxx = min(xb[4], x_int[0][1] ) - xp1; + + if ( ( dxx * dyy) > 0.0 ) + { + area -= dxx * dyy * 0.5; + len = std::hypot(dxx, dyy); + lpa += len * 0.5; + *perim_p += len; + } + // Upper left + dxx = max(0.0, min(xb[2], x_int[2][0]) - xp1); + dyy = yp2 - max(yb[1], y_int[1][1] ); + if ( ( dxx * dyy) > 0.0 ) + { + area -= dxx * dyy * 0.5; + len = std::hypot(dxx, dyy); + lpb += len * 0.5; + *perim_p += len; + } + // Upper right + dyy = max(0.0, yp2 - max(yb[3], y_int[3][0])); + dxx = xp2 - max(xb[2], x_int[2][1] ); + if ( ( dxx * dyy) > 0.0 ) + { + area -= dxx * dyy * 0.5; + len = std::hypot(dxx, dyy); + lpa += len * 0.5; + *perim_p += len; + } + // Lower right + dxx = max(0.0, xp2 - max(xb[4], x_int[4][0])); + dyy = min(yb[3], y_int[3][1] ) - yp1; + if ( ( dxx * dyy) > 0.0 ) + { + area -= dxx * dyy * 0.5; + len = std::hypot(dxx, dyy); + lpb += len * 0.5; + *perim_p += len; + } + + } + + vdrag.xx() = lpa * cth * cth + lpb * sth * sth; + vdrag.xy() = lpa * cth * sth - lpb * sth * cth; + vdrag.yy() = lpa * sth * sth + lpb * cth * cth; + + return area / ( (x2 - x1 ) * ( y2 - y1 ) ); +} // End inters_db + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/PDRutilsOverlap.C b/applications/utilities/preProcessing/PDRsetFields/PDRutilsOverlap.C new file mode 100644 index 0000000000000000000000000000000000000000..85f5fa9efa3edb823a81f30cbc3f0978ef2a31cc --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/PDRutilsOverlap.C @@ -0,0 +1,767 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRsetFields.H" +#include "PDRutilsInternal.H" +#include "mathematicalConstants.H" + +#ifndef FULLDEBUG +#define NDEBUG +#endif +#include <cassert> + +using namespace Foam::constant; + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + // A sign-corrected multiply + // This is used for porosity of obstacle intersections + inline static scalar COMBLK(const scalar a, const scalar b) + { + if (a < 0) + { + return -a * b; + } + + return a * b; + } + + + // Obstacle satisfies some minimum size checks. + // A volume check misses thin plates, so use area. + // Thin sheet overlaps can be produced by touching objects + // if the obs_extend parameter is > 0. + inline static bool obsHasMinSize(const vector& span, const PDRparams& tol) + { + return + ( + (cmptProduct(span) > tol.min_overlap_vol) + && + ( + (span.x() * span.y() > tol.min_overlap_area) + || (span.y() * span.z() > tol.min_overlap_area) + || (span.z() * span.x() > tol.min_overlap_area) + ) + ); + } + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +void Foam::PDRutils::one_d_overlap +( + scalar xmin, + scalar xmax, + const PDRblock::location& grid, + List<scalar>& olap, + int *cmin, int *cmax, + int *cfmin, int *cfmax +) +{ + // Looking at one coordinate direction, called x here, for something + // that extends from xmin to xmax, calculate how much it overlaps + // each cell in this direction. Result returned in 'olap' List is + // the proportion of the grid step overlapped, i.e dimensionless. + // First and last steps overlapped given by *cmin, *cmax + // Ditto for shifted grid given by *cfmin, *cfmax. + + // Initially zero everwhere + olap = Zero; + + if (olap.size() < grid.nPoints()) + { + FatalErrorInFunction + << "The overlap scratch array is too small, has " + << olap.size() << " but needs " << grid.nPoints() << nl + << exit(FatalError); + } + + + // No intersection with the box + if (xmax <= grid.first() || grid.last() <= xmin) + { + // Mark as bad range, cannot iterate + *cmin = 0; + *cmax = -1; + + // Another bad range (cannot iterate) but for extra safety ensure + // that (cfmin -> cmin) and (cmax -> cfmax) cannot iterate either + *cfmin = 1; + *cfmax = -2; + return; + } + + // Ensure search is within the (point) bounds + xmin = grid.clip(xmin); + xmax = grid.clip(xmax); + + // The begin/end of the obstacle + *cmin = grid.findCell(xmin); + *cmax = grid.findCell(xmax); + + for (label ix = *cmin; ix <= *cmax; ++ix) + { + olap[ix] = 1.0; + } + + // Fixup ends + if (*cmax == *cmin) + { + olap[*cmax] = (xmax - xmin) / grid.width(*cmax); + } + else + { + if (grid[*cmin] < xmin) + { + olap[*cmin] = (grid[*cmin+1] - xmin) / grid.width(*cmin); + } + + if (xmax < grid[*cmax+1]) + { + olap[*cmax] = (xmax - grid[*cmax]) / grid.width(*cmax); + } + } + assert(olap[*cmax] >= 0.0); + + + // Is xmin below/above the cell-centre (for virtual staggered-grid) ? + *cfmin = + ( + xmin < grid.C(*cmin) + ? *cmin + : Foam::min(*cmin+1, grid.nCells()-1) + ); + + // Is xmax below/above the cell-centre (for virtual staggered-grid) ? + *cfmax = + ( + xmax < grid.C(*cmax) + ? *cmax + : Foam::min(*cmax+1, grid.nCells()-1) + ); +} + + +/**************************************************************************************************/ + +void Foam::PDRutils::two_d_overlap +( + const UList<scalar>& a_olap, label amin, label amax, + const UList<scalar>& b_olap, label bmin, label bmax, + SquareMatrix<scalar>& ab_olap +) +{ + // We go one over the relevant min/max limits since these values might be + // used. If not, they would have been zeroed in one_d_overlap + + amin = Foam::max(0, amin-1); + bmin = Foam::max(0, bmin-1); + amax = Foam::min(a_olap.size()-1, amax+1); + bmax = Foam::min(b_olap.size()-1, bmax+1); + + for (label ia = amin; ia <= amax; ++ia) + { + for (label ib = bmin; ib <= bmax; ++ib) + { + ab_olap(ia,ib) = a_olap[ia] * b_olap[ib]; + } + } +} + + +/**************************************************************************************************/ + +void Foam::PDRutils::circle_overlap +( + scalar ac, scalar bc, scalar dia, + scalar theta, scalar wa, scalar wb, + const PDRblock::location& agrid, label amin, label amax, + const PDRblock::location& bgrid, label bmin, label bmax, + SquareMatrix<scalar>& ab_olap, + SquareMatrix<scalar>& ab_perim, + SquareMatrix<scalar>& a_lblock, + SquareMatrix<scalar>& ac_lblock, + SquareMatrix<scalar>& c_count, + SquareMatrix<symmTensor2D>& c_drag, + SquareMatrix<scalar>& b_lblock, + SquareMatrix<scalar>& bc_lblock +) +{ + /* This routine calculates the proportion of each (two-dimensional) grid cell + overlapped by the circle or angled rectangle. Coordinates are labelled a and b. + On entry: + ac, bc coordinates of centre of circle or rectangle + dia diameter of circle (zero for rectangle) + theta, wa, wb parameters for rectangle + agrid[] locations of grid lines of a-grid + amin, amax first and last cells in a-grid overlapped by object + (similarly for b) + On exit: + abolap 2-D array of (proportionate) area blockage by grid cell + a_lblock 2-D array of (proportionate) blockage to a-direction flow + (This will be area blockage when extruded in the third coordinate). + a_count (2-D array)The contribution of this object to the count of obstacles blocking + a-direction flow. This is only non-zero if the object is inside the + lateral boundaries of the cell. It is large negative if the cell is + totally blocked in this direction. + (similarly for b) + c_drag 2-D array of tensor that will give tensor drag in each cell (when multiplied + Cd, cylinder length, and 0.5 rho*U^2) Dimension: L. + + Note that this routine does not zero array elements outside the amin to amax, bmin to bmax area. + */ + + scalar count, a_lblk, b_lblk, perim, dummy; + + symmTensor2D vdrag(Zero); + + // Prevent stepping outside of the array when the obstacle is on the + // upper boundary + + // Upper limit of inclusive range is nCells-1 + amin = Foam::max(0, amin); + bmin = Foam::max(0, bmin); + amax = Foam::min(amax, agrid.nCells()-1); + bmax = Foam::min(bmax, bgrid.nCells()-1); + + for (label ia = amin; ia <= amax; ++ia) + { + // Cell-centred grid + const scalar a1 = agrid[ia]; + const scalar a2 = agrid[ia+1]; + + // Left-shifted staggered face grid (-1 addressing is OK) + const scalar af1 = agrid.C(ia-1); + const scalar af2 = agrid.C(ia); + + for (label ib = bmin; ib <= bmax; ++ib) + { + // Cell-centred grid + const scalar b1 = bgrid[ib]; + const scalar b2 = bgrid[ib+1]; + + // Left-shifted staggered face grid (-1 addressing is OK) + const scalar bf1 = bgrid.C(ib-1); + const scalar bf2 = bgrid.C(ib); + + // Do the centred cell + if ( dia > 0.0 ) + { + ab_olap(ia,ib) = inters_cy + ( + ac, bc, 0.5*dia, a1, a2, b1, b2, &perim, + &dummy, &dummy, &b_lblk, &a_lblk + ); +/* The last two arguments of the above call appear to be reversed, but the inters_cy routine returns + the amount of overlap in the a and b direcvtions, which are the blockage to the b and a directions. */ + +/* abolap * cell area is area of cylinder in this cell. Divide by PI%D^2/4 to get proportion of cylinder in cell + For whole cylinger c_drag should be = D, so multiply by D. */ + + c_drag(ia,ib).xx() = c_drag(ia,ib).yy() = 4.0 * ab_olap(ia,ib) * (a2 - a1) * (b2 - b1) / dia / mathematical::pi; + c_drag(ia,ib).xy() = Zero; + c_count(ia,ib) = perim / (mathematical::pi * dia); + +//******????? + scalar area = (a2 - a1) * (b2 - b1); + scalar rat = dia * dia / area - 1.5; + if (rat > 0.0) + { + scalar da = ac - 0.5 * (a1 + a2); + scalar db = bc - 0.5 * (b1 + b2); + scalar dc = std::hypot(da, db); + scalar rat1 = min(max((dc / sqrt(area) - 0.3) * 1.4, 0), 1); + scalar drg0 = c_drag(ia,ib).xx(); + scalar drg1 = c_drag(ia,ib).yy(); + scalar drg = std::hypot(drg0, drg1); + c_drag(ia,ib).xx() = drg * ( 1.0 - rat1 ) + drg * da*da/dc/dc * rat1; + c_drag(ia,ib).yy() = drg * ( 1.0 - rat1 ) + drg * db*db/dc/dc * rat1; + c_drag(ia,ib).xy() = drg * da*db/dc/dc *rat1; + } + } + else + { + ab_olap(ia,ib) = inters_db( ac, bc, theta, wa, wb, a1, a2, b1, b2, &count, c_drag(ia,ib), &perim, &a_lblk, &b_lblk, &dummy, &dummy ); + c_count(ia,ib) = perim / ( wa + wb ) * 0.5; + } + ac_lblock(ia,ib) = a_lblk; + bc_lblock(ia,ib) = b_lblk; + ab_perim(ia,ib) = perim; + + // Do the a-shifted cell + if ( dia > 0.0 ) // I.e. a cylinder, not a d.b. + { + if (ac >= af1 && ac < af2) + { + // Only want to block one layer of faces + a_lblock(ia,ib) = l_blockage + ( + ac, bc, 0.5*dia, + af1, af2, b1, b2, &count, &dummy, &dummy + ); + } + inters_cy + ( + ac, bc, 0.5*dia, + af1, af2, b1, b2, + &perim, &count, &dummy, &dummy, &dummy + ); + } + else + { + inters_db + ( + ac, bc, theta, wa, wb, af1, af2, b1, b2, + &count, vdrag, &dummy, &a_lblk, &b_lblk, &dummy, &dummy + ); + a_lblock(ia,ib) = a_lblk; + } + + // Do the b-shifted cell + if ( dia > 0.0 ) + { + if (bc >= bf1 && bc < bf2) + { + // Only want to block one layer of faces + b_lblock(ia,ib) = l_blockage + ( + bc, ac, 0.5*dia, bf1, bf2, a1, a2, + &count, &(vdrag.yy()), &dummy + ); + } + + inters_cy + ( + ac, bc, 0.5*dia, + a1, a2, bf1, bf2, + &perim, &dummy, &count, &dummy, &dummy + ); + } + else + { + inters_db + ( + ac, bc, theta, wa, wb, + a1, a2, bf1, bf2, + &count, vdrag, &dummy, &a_lblk, &b_lblk, &dummy, &dummy + ); + b_lblock(ia,ib) = b_lblk; + } + } + } + +} // End circle_overlap + + +/**************************************************************************************************/ + +scalar block_overlap +( + DynamicList<PDRobstacle>& blocks, + const labelRange& range, + const scalar multiplier +) +{ + // Size information + const label nBlock = range.size(); + + // The return value + scalar totVolume = 0; + + if (nBlock < 2) return 0; + + + // Sort blocks by their x-position (with sortBias) + labelList blkOrder; + sortedOrder(blocks[range], blkOrder); + + DynamicList<PDRobstacle> newBlocks; + + // Work through the sorted blocks + for (label i1 = 0; i1 < nBlock-1; ++i1) + { + const PDRobstacle& blk1 = blocks[range[blkOrder[i1]]]; + + // Upper coordinates + const vector max1 = blk1.pt + blk1.span; + + // For second block start with the next one on the list, and + // stop when we find the first one whose biased x-position + // is beyond the end of the block1 + + for (label i2 = i1 + 1; i2 < nBlock; ++i2) + { + const PDRobstacle& blk2 = blocks[range[blkOrder[i2]]]; + + // Upper coordinates + const vector max2 = blk2.pt + blk2.span; + + if (max1.x() <= blk2.x()) + { + break; + } + + if + ( + max1.y() <= blk2.y() + || max1.z() <= blk2.z() + || max2.y() <= blk1.y() + || max2.z() <= blk1.z() + || (blk1.vbkge * blk2.vbkge <= 0) + ) + { + continue; + } + + + { + PDRobstacle over; + + over.pt = max(blk1.pt, blk2.pt); + over.span = min(max1, max2) - over.pt; + + assert(cmptProduct(over.span) > 0.0); + + // This routine should only have been called for all +ve o r all -ve obstacles + assert(blk1.vbkge * blk2.vbkge > 0); + /* At the first level of intersection, we create an obstacle of blockage -1 (if both objects solid) + to cancel out the double counting. (multiplier is 1). + ?? COMBLK does a (sign corrected) multiply; is this corrrect for porous obstacles? + Depends on how blockages were summed in the first place. In fact this -ve obstacle + concept only works if the blockages are summed??*/ + over.vbkge = - COMBLK( blk1.vbkge, blk2.vbkge ) * multiplier; + over.xbkge = - COMBLK( blk1.xbkge, blk2.xbkge ) * multiplier; + over.ybkge = - COMBLK( blk1.ybkge, blk2.ybkge ) * multiplier; + over.zbkge = - COMBLK( blk1.zbkge, blk2.zbkge ) * multiplier; + over.typeId = 81 + int(15 * multiplier); // Not subsequently used + + if (obsHasMinSize(over.span, pars)) + { + // Obstacle satisfies some minimum size checks + totVolume -= over.volume(); + + newBlocks.append(over); + } + } + } + } + + blocks.append(std::move(newBlocks)); + + return totVolume; +} + + +/**************************************************************************************************/ + +using namespace Foam::PDRutils; + +scalar block_cylinder_overlap +( + DynamicList<PDRobstacle>& blocks, + const labelRange& range, + const UList<PDRobstacle>& cylinders +) +{ + // Size information + const label nBlock = range.size(); + const label nCyl = cylinders.size(); + + // The return value + scalar totVolume = 0; + + if (!nBlock || !nCyl) return 0; + + scalar area, a_lblk, b_lblk, dummy, a_centre, b_centre; + symmTensor2D dum2; + + + // Sort blocks and cylinders by their x-position (with sortBias) + labelList blkOrder; + sortedOrder(blocks[range], blkOrder); + + labelList cylOrder; + sortedOrder(cylinders, cylOrder); + + DynamicList<PDRobstacle> newBlocks; + + // Work through the sorted blocks + for (label i1 = 0; i1 < nBlock; i1++) + { + const PDRobstacle& blk1 = blocks[range[blkOrder[i1]]]; + + // Upper coordinates + const vector max1 = blk1.pt + blk1.span; + + // Cyls whose end is before start of this block no longer + // need to be considered + + label i2 = 0; + while (i2 < nCyl-1 && cylinders[cylOrder[i2]] < blk1) + { + ++i2; + } + + for (/*nil*/; i2 < nCyl; ++i2) + { + const PDRobstacle& cyl2 = cylinders[cylOrder[i2]]; + + // Calculate overlap in axis direction; if zero continue. + // Calculate 2-d overlap and c 0f g; if area zero continue. + + PDRobstacle over; + + + switch (cyl2.orient) + { + case vector::Z: + { + const scalar zm2 = cyl2.z() + cyl2.len(); + if (blk1.z() > zm2 || cyl2.z() > max1.z()) continue; + + if ( cyl2.dia() == 0.0 ) + { + area = inters_db + ( + cyl2.x(), cyl2.y(), cyl2.theta(), cyl2.wa, cyl2.wb, + blk1.x(), max1.x(), + blk1.y(), max1.y(), + &dummy, dum2, &dummy, &a_lblk, &b_lblk, + &a_centre, &b_centre + ); + } + else + { + area = inters_cy + ( + cyl2.x(), cyl2.y(), 0.5*cyl2.dia(), + blk1.x(), max1.x(), + blk1.y(), max1.y(), + &dummy, &dummy, &dummy, &dummy, &dummy + ); + b_lblk = l_blockage + ( + cyl2.x(), cyl2.y(), 0.5*cyl2.dia(), + blk1.x(), max1.x(), + blk1.y(), max1.y(), + &dummy, &dummy, &b_centre + ); + a_lblk = l_blockage + ( + cyl2.y(), cyl2.x(), 0.5*cyl2.dia(), + blk1.y(), max1.y(), + blk1.x(), max1.x(), + &dummy, &dummy, &a_centre + ); + } + if (equal(area, 0)) continue; + assert(a_lblk >0.0); + assert(b_lblk >0.0); + + // The intersection between a circle and a rectangle can be an odd shape. + // We have its area. a_lblk and b_lblk are dimensions of enclosing rectangle + // and a_centre and b_centre its centre. We scale this rectangle down to + // the corect areacorrect area, as a rectangular approximation to the intersection. + const scalar ratio = std::sqrt( area / a_lblk / b_lblk ); + + a_lblk *= blk1.span.x() * ratio; + b_lblk *= blk1.span.y() * ratio; + assert(b_lblk >0.0); + assert(a_lblk >0.0); + + over.x() = a_centre - 0.5 * a_lblk; + over.y() = b_centre - 0.5 * b_lblk; + over.z() = max(blk1.z(), cyl2.z()); + + over.span.x() = a_lblk; + over.span.y() = b_lblk; + over.span.z() = min(max1.z(), cyl2.z() + cyl2.len()) - over.z(); + assert(over.x() > -200.0); + assert(over.x() < 2000.0); + } + break; + + case vector::Y: + { + const scalar ym2 = cyl2.y() + cyl2.len(); + if (blk1.y() > ym2 || cyl2.y() > max1.y()) continue; + + if ( cyl2.dia() == 0.0 ) + { + area = inters_db + ( + cyl2.z(), cyl2.x(), cyl2.theta(), cyl2.wa, cyl2.wb, + blk1.z(), max1.z(), + blk1.x(), max1.x(), + &dummy, dum2, &dummy, &a_lblk, &b_lblk, + &a_centre, &b_centre + ); + } + else + { + area = inters_cy + ( + cyl2.z(), cyl2.x(), 0.5*cyl2.dia(), + blk1.z(), max1.z(), + blk1.x(), max1.x(), + &dummy, &dummy, &dummy, &dummy, &dummy + ); + + b_lblk = l_blockage + ( + cyl2.z(), cyl2.x(), 0.5*cyl2.dia(), + blk1.z(), max1.z(), + blk1.x(), max1.x(), + &dummy, &dummy, &b_centre + ); + + a_lblk = l_blockage + ( + cyl2.x(), cyl2.z(), 0.5*cyl2.dia(), + blk1.x(), max1.x(), + blk1.z(), max1.z(), + &dummy, &dummy, &a_centre + ); + } + + if (equal(area, 0)) continue; + assert(a_lblk >0.0); + assert(b_lblk >0.0); + + // a_lblk and b_lblk are dimensions of enclosing rectangle. + // Need to scale to correct area + const scalar ratio = std::sqrt( area / a_lblk / b_lblk ); + a_lblk *= blk1.span.z() * ratio; + b_lblk *= blk1.span.x() * ratio; + + over.z() = a_centre - a_lblk * 0.5; + over.x() = b_centre - b_lblk * 0.5; + over.y() = max(blk1.y(), cyl2.y()); + + over.span.z() = a_lblk; + over.span.x() = b_lblk; + over.span.y() = min(max1.y(), cyl2.y() + cyl2.len()) - over.y(); + } + break; + + case vector::X: + { + const scalar xm2 = cyl2.x() + cyl2.len(); + if (blk1.x() > xm2 || cyl2.x() > max1.x()) continue; + + if ( cyl2.dia() == 0.0 ) + { + area = inters_db + ( + cyl2.y(), cyl2.z(), cyl2.theta(), cyl2.wa, cyl2.wb, + blk1.y(), max1.y(), + blk1.z(), max1.z(), + &dummy, dum2, &dummy, &a_lblk, &b_lblk, + &a_centre, &b_centre + ); + } + else + { + area = inters_cy + ( + cyl2.y(), cyl2.z(), 0.5*cyl2.dia(), + blk1.y(), max1.y(), + blk1.z(), max1.z(), + &dummy, &dummy, &dummy, &dummy, &dummy + ); + + b_lblk = l_blockage + ( + cyl2.y(), cyl2.z(), 0.5*cyl2.dia(), + blk1.y(), max1.y(), + blk1.z(), max1.z(), + &dummy, &dummy, &b_centre + ); + + a_lblk = l_blockage + ( + cyl2.z(), cyl2.y(), 0.5*cyl2.dia(), + blk1.z(), max1.z(), + blk1.y(), max1.y(), + &dummy, &dummy, &a_centre + ); + + } + + if (equal(area, 0)) continue; + assert(a_lblk >0.0); + assert(b_lblk >0.0); + + // a_lblk and b_lblk are dimensions of enclosing rectangle. + // Need to scale to correct area + const scalar ratio = std::sqrt( area / a_lblk / b_lblk ); + assert(ratio >-10000.0); + assert(ratio <10000.0); + a_lblk *= blk1.span.y() * ratio; + b_lblk *= blk1.span.z() * ratio; + + over.y() = a_centre - a_lblk * 0.5; + over.z() = b_centre - b_lblk * 0.5; + over.x() = max(blk1.x(), cyl2.x()); + + over.span.y() = a_lblk; + over.span.z() = b_lblk; + over.span.x() = min(max1.x(), cyl2.x() + cyl2.len()) - over.x(); + } + break; + } + over.vbkge = over.xbkge = over.ybkge = over.zbkge = -1.0; + over.typeId = PDRobstacle::IGNORE; + + assert(cmptProduct(over.span) > 0.0); + assert(b_lblk >0.0); + assert(a_lblk >0.0); + assert(over.x() > -10000.0); + + if (obsHasMinSize(over.span, pars)) + { + // Obstacle satisfies some minimum size checks + totVolume -= over.volume(); + + newBlocks.append(over); + } + } + } + + blocks.append(std::move(newBlocks)); + + return totVolume; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/ObstaclesDict b/applications/utilities/preProcessing/PDRsetFields/obstacles/ObstaclesDict new file mode 100644 index 0000000000000000000000000000000000000000..84b5a97cf9a42047ce9f05349ef99396965c3930 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/ObstaclesDict @@ -0,0 +1,179 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1812 | +| \\ / A nd | Web: www.OpenFOAM.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +group1 +{ + positions + ( + (0 0 0) + ); + + obstacles + ( + box { point (0 0 0); span (0.05 0.05 2); porosity 0; } + box { point (1 0 0); span (0.05 0.05 2); porosity 0; } + box { point (1 0 0); span (0.05 0.05 2); porosity 0; } + box { point (2 0 0); span (0.05 0.05 2); porosity 0; } + box { point (3 0 0); span (0.05 0.05 2); porosity 0; } + box { point (0 1 0); span (0.05 0.05 2); porosity 0; } + box { point (1 1 0); span (0.05 0.05 2); porosity 0; } + box { point (2 1 0); span (0.05 0.05 2); porosity 0; } + box { point (3 1 0); span (0.05 0.05 2); porosity 0; } + box { point (0 2 0); span (0.05 0.05 2); porosity 0; } + box { point (1 2 0); span (0.05 0.05 2); porosity 0; } + box { point (2 2 0); span (0.05 0.05 2); porosity 0; } + box { point (3 2 0); span (0.05 0.05 2); porosity 0; } + box { point (0 3 0); span (0.05 0.05 2); porosity 0; } + box { point (1 3 0); span (0.05 0.05 2); porosity 0; } + box { point (2 3 0); span (0.05 0.05 2); porosity 0; } + box { point (3 3 0); span (0.05 0.05 2); porosity 0; } + box { point (0 0 0); span (0.05 3.05 0.05); } + box { point (1 0 0); span (0.05 3.05 0.05); } + box { point (2 0 0); span (0.05 3.05 0.05); } + box { point (3 0 0); span (0.05 3.05 0.05); } + box { point (0 0 1); span (0.05 3.05 0.05); } + box { point (1 0 1); span (0.05 3.05 0.05); } + box { point (2 0 1); span (0.05 3.05 0.05); } + box { point (3 0 1); span (0.05 3.05 0.05); } + box { point (0 0 2); span (0.05 3.05 0.05); } + box { point (1 0 2); span (0.05 3.05 0.05); } + box { point (2 0 2); span (0.05 3.05 0.05); } + box { point (3 0 2); span (0.05 3.05 0.05); } + box { point (0 0 0); span (3.05 0.05 0.05); } + box { point (0 1 0); span (3.05 0.05 0.05); } + box { point (0 2 0); span (3.05 0.05 0.05); } + box { point (0 3 0); span (3.05 0.05 0.05); } + box { point (0 0 1); span (3.05 0.05 0.05); } + box { point (0 1 1); span (3.05 0.05 0.05); } + box { point (0 2 1); span (3.05 0.05 0.05); } + box { point (0 3 1); span (3.05 0.05 0.05); } + box { point (0 0 2); span (3.05 0.05 0.05); } + box { point (0 1 2); span (3.05 0.05 0.05); } + box { point (0 2 2); span (3.05 0.05 0.05); } + box { point (0 3 2); span (3.05 0.05 0.05); } + + patch { point (1 1 1); span (2 2 2); inlet x; outlet y; name xpatch; } + ); +} + +group11 +{ + positions + ( + (0 0 0) + ); + +} + +group14 +{ + positions + ( + (0 0 0.15) + (0 0 0.45) + ); + + obstacles + ( + box { point (0.05 0 1.05); span(0.006 3.05 0.05); } + box { point (0.997 0 1.05); span(0.006 3.05 0.05); } + box { point (1.05 0 1.05); span(0.006 3.05 0.05); } + box { point (1.997 0 1.05); span(0.006 3.05 0.05); } + box { point (2.05 0 1.05); span(0.006 3.05 0.05); } + box { point (2.997 0 1.05); span(0.006 3.05 0.05); } + + cyl { point (0.05 0.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 0.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 0.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 0.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 1.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 1.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 1.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 1.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 2.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 2.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 2.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 2.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (0.05 3.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 0.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 0.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 0.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 0.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 1.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 1.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 1.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 1.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 2.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 2.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 2.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 2.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (1.05 3.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 0.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 0.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 0.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 0.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 1.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 1.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 1.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 1.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 2.025 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 2.275 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 2.525 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 2.775 1.075); length 0.947; diameter 0.026; direction x; } + cyl { point (2.05 3.025 1.075); length 0.947; diameter 0.026; direction x; } + ); +} + + +group17 +{ + positions + ( + (0 0 0) + (0 0 0.30) + ); + +} + +group21 +{ + positions + ( + (0 0 0) + ); + +} + +group31 +{ + positions + ( + (0 0 0) + ); + +} + +group41 +{ + positions + ( + (0 0 0) + ); + +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacle.C b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacle.C new file mode 100644 index 0000000000000000000000000000000000000000..91ccc58d14f2073aff90ead01e3be2b70ed09d2f --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacle.C @@ -0,0 +1,737 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRobstacle.H" +#include "boundBox.H" +#include "meshedSurf.H" +#include "axisAngleRotation.H" +#include "coordinateSystem.H" +#include "foamVtkSurfaceWriter.H" +#include "unitConversion.H" +#include "addToMemberFunctionSelectionTable.H" + +using namespace Foam::constant; + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineMemberFunctionSelectionTable(PDRobstacle, read, dictRead); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::PDRobstacle::PDRobstacle() +: + groupId(0), + typeId(0), + orient(vector::X), + sortBias(0), + pt(Zero), + span(Zero), + wa(0), + wb(0), + vbkge(0), + xbkge(0), + ybkge(0), + zbkge(0), + blowoff_type(0), + identifier() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::PDRobstacle::clear() +{ + groupId = 0; + typeId = 0; + orient = vector::X; + sortBias = 0; + pt = Zero; + span = Zero; + wa = 0; + wb = 0; + vbkge = 0; + xbkge = 0; + ybkge = 0; + zbkge = 0; + blowoff_type = 0; + identifier.clear(); +} + + +void Foam::PDRobstacle::readProperties(const dictionary& dict) +{ + PDRobstacle::clear(); + + // Read as word, which handles quoted or unquoted entries + word obsName; + + if (dict.readIfPresent("name", obsName)) + { + identifier = std::move(obsName); + } +} + + +void Foam::PDRobstacle::scale(const scalar factor) +{ + if (factor <= 0) + { + return; + } + + sortBias *= factor; + + switch (typeId) + { + case PDRobstacle::CYLINDER: + { + pt *= factor; + + dia() *= factor; + len() *= factor; + break; + } + + case PDRobstacle::DIAG_BEAM: + { + pt *= factor; + + len() *= factor; + wa *= factor; + wb *= factor; + break; + } + + case PDRobstacle::CUBOID_1: + case PDRobstacle::LOUVRE_BLOWOFF: + case PDRobstacle::CUBOID: + case PDRobstacle::WALL_BEAM: + case PDRobstacle::GRATING: + case PDRobstacle::RECT_PATCH: + { + pt *= factor; + span *= factor; + + if (typeId == PDRobstacle::GRATING) + { + slat_width *= factor; + } + break; + } + } +} + + +Foam::scalar Foam::PDRobstacle::volume() const +{ + scalar vol = 0; + + switch (typeId) + { + case PDRobstacle::CYLINDER: + vol = 0.25 * mathematical::pi * sqr(dia()) * len(); + break; + + case PDRobstacle::DIAG_BEAM: + vol = wa * wb * len(); + break; + + case PDRobstacle::CUBOID_1: + case PDRobstacle::LOUVRE_BLOWOFF: + case PDRobstacle::CUBOID: + case PDRobstacle::WALL_BEAM: + case PDRobstacle::GRATING: + vol = cmptProduct(span) * vbkge; + break; + } + + return vol; +} + + +bool Foam::PDRobstacle::tooSmall(const scalar minWidth) const +{ + if (minWidth <= 0) + { + return false; + } + + switch (typeId) + { + case PDRobstacle::CYLINDER: + { + // The effective half-width + if ((0.25 * dia() * sqrt(mathematical::pi)) <= minWidth) + { + return true; + } + break; + } + + case PDRobstacle::DIAG_BEAM: + { + if + ( + (len() <= minWidth && wa <= minWidth) + || (len() <= minWidth && wb <= minWidth) + || (wa <= minWidth && wb <= minWidth) + ) + { + return true; + } + break; + } + + case PDRobstacle::CUBOID_1: + case PDRobstacle::LOUVRE_BLOWOFF: + case PDRobstacle::CUBOID: + case PDRobstacle::WALL_BEAM: + case PDRobstacle::GRATING: + case PDRobstacle::RECT_PATCH: + { + if + ( + (span.x() <= minWidth && span.y() <= minWidth) + || (span.y() <= minWidth && span.z() <= minWidth) + || (span.z() <= minWidth && span.x() <= minWidth) + ) + { + return true; + } + + break; + } + } + + return false; +} + + +Foam::volumeType Foam::PDRobstacle::trim(const boundBox& bb) +{ + volumeType::type vt = volumeType::UNKNOWN; + + if (!bb.valid() || !typeId) + { + return vt; + } + + switch (typeId) + { + case PDRobstacle::CYLINDER: + { + const scalar rad = 0.5*dia(); + + direction e1 = vector::X; + direction e2 = vector::Y; + direction e3 = vector::Z; + + if (orient == vector::X) + { + e1 = vector::Y; + e2 = vector::Z; + e3 = vector::X; + } + else if (orient == vector::Y) + { + e1 = vector::Z; + e2 = vector::X; + e3 = vector::Y; + } + else + { + orient = vector::Z; // extra safety? + } + + if + ( + (pt[e1] + rad <= bb.min()[e1]) + || (pt[e2] + rad <= bb.min()[e2]) + || (pt[e3] + len() <= bb.min()[e3]) + || (pt[e1] - rad >= bb.max()[e1]) + || (pt[e2] - rad >= bb.max()[e2]) + || (pt[e3] >= bb.max()[e3]) + ) + { + // No overlap + return volumeType::OUTSIDE; + } + + vt = volumeType::INSIDE; + + // Trim obstacle length as required + if (pt[e3] < bb.min()[e3]) + { + vt = volumeType::MIXED; + len() -= bb.min()[e3] - pt[e3]; + pt[e3] = bb.min()[e3]; + } + + if (pt[e3] + len() > bb.max()[e3]) + { + vt = volumeType::MIXED; + len() = bb.max()[e3] - pt[e3]; + } + + // Cannot trim diameter very well, so just mark as protruding + if + ( + (pt[e1] - rad < bb.min()[e1]) || (pt[e1] + rad > bb.max()[e1]) + || (pt[e2] - rad < bb.min()[e2]) || (pt[e2] + rad > bb.max()[e2]) + ) + { + vt = volumeType::MIXED; + } + + break; + } + + + case PDRobstacle::DIAG_BEAM: + { + // Not implemented + break; + } + + + case PDRobstacle::CUBOID_1: + case PDRobstacle::LOUVRE_BLOWOFF: + case PDRobstacle::CUBOID: + case PDRobstacle::WALL_BEAM: + case PDRobstacle::GRATING: + case PDRobstacle::RECT_PATCH: + { + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + if + ( + ((pt[cmpt] + span[cmpt]) < bb.min()[cmpt]) + || (pt[cmpt] > bb.max()[cmpt]) + ) + { + // No overlap + return volumeType::OUTSIDE; + } + } + + + vt = volumeType::INSIDE; + + // Trim obstacle as required + + for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt) + { + if (pt[cmpt] < bb.min()[cmpt]) + { + vt = volumeType::MIXED; + if (span[cmpt] > 0) + { + span[cmpt] -= bb.min()[cmpt] - pt[cmpt]; + } + pt[cmpt] = bb.min()[cmpt]; + } + + + if (pt[cmpt] + span[cmpt] > bb.max()[cmpt]) + { + vt = volumeType::MIXED; + span[cmpt] -= bb.max()[cmpt] - pt[cmpt]; + } + } + + break; + } + } + + return vt; +} + + +Foam::meshedSurface Foam::PDRobstacle::surface() const +{ + meshedSurface surf; + + const PDRobstacle& obs = *this; + + switch (obs.typeId) + { + case PDRobstacle::CUBOID_1 : + case PDRobstacle::CUBOID : + { + boundBox box(obs.pt, obs.pt + obs.span); + + pointField pts(box.points()); + faceList fcs(boundBox::faces); + + surf.transfer(pts, fcs); + + break; + } + + case PDRobstacle::DIAG_BEAM : + { + boundBox box(Zero); + + switch (orient) + { + case vector::X: + { + box.min() = vector(0, -0.5*obs.wa, -0.5*obs.wb); + box.max() = vector(obs.len(), 0.5*obs.wa, 0.5*obs.wb); + break; + } + + case vector::Y: + { + box.min() = vector(-0.5*obs.wb, 0, -0.5*obs.wa); + box.max() = vector(0.5*obs.wb, obs.len(), 0.5*obs.wa); + break; + } + + case vector::Z: + { + box.min() = vector(-0.5*obs.wa, -0.5*obs.wb, 0); + box.max() = vector(0.5*obs.wa, 0.5*obs.wb, obs.len()); + break; + } + } + + coordinateSystem cs + ( + obs.pt, + coordinateRotations::axisAngle + ( + vector::components(obs.orient), + obs.theta(), + false + ) + ); + + pointField pts0(box.points()); + faceList fcs(boundBox::faces); + + pointField pts(cs.globalPosition(pts0)); + + surf.transfer(pts, fcs); + + break; + } + + case PDRobstacle::CYLINDER : + { + // Tessellation 12 looks fairly reasonable + + constexpr int nDiv = 12; + + point org(obs.pt); + + direction e1 = vector::X; + direction e2 = vector::Y; + direction e3 = vector::Z; + + if (obs.orient == vector::X) + { + e1 = vector::Y; + e2 = vector::Z; + e3 = vector::X; + } + else if (obs.orient == vector::Y) + { + e1 = vector::Z; + e2 = vector::X; + e3 = vector::Y; + } + + pointField pts(2*nDiv, org); + faceList fcs(2 + nDiv); + + // Origin for back + org[e3] += obs.len(); + SubList<point>(pts, nDiv, nDiv) = org; + + const scalar radius = 0.5*obs.dia(); + + for (label i=0; i < nDiv; ++i) + { + const scalar angle = (i * mathematical::twoPi) / nDiv; + const scalar s = radius * sin(angle); + const scalar c = radius * cos(angle); + + pts[i][e1] += s; + pts[i][e2] += c; + + pts[nDiv+i][e1] += s; + pts[nDiv+i][e2] += c; + } + + // Side-faces + for (label facei=0; facei < nDiv; ++facei) + { + face& f = fcs[facei]; + f.resize(4); + + f[0] = facei; + f[3] = (facei + 1) % nDiv; + f[1] = f[0] + nDiv; + f[2] = f[3] + nDiv; + } + + { + // Front face + face& f1 = fcs[nDiv]; + f1.resize(nDiv); + + f1[0] = 0; + for (label pti=1; pti < nDiv; ++pti) + { + f1[pti] = nDiv-pti; + } + + // Back face + labelList& f2 = fcs[nDiv+1]; + f2 = identity(nDiv, nDiv); + } + + surf.transfer(pts, fcs); + + break; + } + + case PDRobstacle::RECT_PATCH : + { + pointField pts(4, obs.span); + pts[0] = Zero; + + switch (obs.inlet_dirn) + { + case -1: + case 1: + { + for (auto& p : pts) + { + p.x() = 0; + } + + pts[1].z() = 0; + pts[3].y() = 0; + break; + } + case -2: + case 2: + { + for (auto& p : pts) + { + p.y() = 0; + } + + pts[1].x() = 0; + pts[3].z() = 0; + break; + } + default: + { + for (auto& p : pts) + { + p.z() = 0; + } + + pts[1].y() = 0; + pts[3].x() = 0; + break; + } + } + + // pts += obs.pt; + + faceList fcs(one(), face(identity(4))); + + surf.transfer(pts, fcs); + + break; + } + + default: + break; + +// LOUVRE_BLOWOFF = 5, +// WALL_BEAM = 7, +// GRATING = 8, +// CIRC_PATCH = 12, +// MESH_PLANE = 46, + } + + return surf; +} + + +Foam::label Foam::PDRobstacle::addPieces +( + vtk::surfaceWriter& surfWriter, + const UList<PDRobstacle>& list, + label pieceId +) +{ + for (const PDRobstacle& obs : list) + { + meshedSurface surf(obs.surface()); + + if (!surf.empty()) + { + surfWriter.piece(surf.points(), surf.surfFaces()); + + surfWriter.writeGeometry(); + surfWriter.beginCellData(2); + surfWriter.writeUniform("group", label(obs.groupId)); + surfWriter.writeUniform("type", label(obs.typeId)); + surfWriter.writeUniform("obstacle", pieceId); + ++pieceId; + } + } + + return pieceId; +} + + +void Foam::PDRobstacle::generateVtk +( + const fileName& outputDir, + const UList<PDRobstacle>& obslist, + const UList<PDRobstacle>& cyllist +) +{ + label pieceId = 0; + + meshedSurf::emptySurface dummy; + + vtk::surfaceWriter surfWriter + ( + dummy.points(), + dummy.faces(), + // vtk::formatType::INLINE_ASCII, + (outputDir / "Obstacles"), + false // serial only + ); + + pieceId = addPieces(surfWriter, obslist, pieceId); + pieceId = addPieces(surfWriter, cyllist, pieceId); + + Info<< "Wrote " << pieceId << " obstacles (VTK) to " + << outputDir/"Obstacles" << nl; +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const InfoProxy<PDRobstacle>& iproxy +) +{ + const PDRobstacle& obs = iproxy.t_; + + switch (obs.typeId) + { + case PDRobstacle::CUBOID_1 : + case PDRobstacle::CUBOID : + os << "box { point " << obs.pt + << "; size " << obs.span + << "; }"; + break; + + case PDRobstacle::CYLINDER : + os << "cyl { point " << obs.pt + << "; length " << obs.len() << "; diameter " << obs.dia() + << "; direction " << vector::componentNames[obs.orient] + << "; }"; + break; + + case PDRobstacle::DIAG_BEAM : + os << "diag { point " << obs.pt + << "; length " << obs.len() + << "; width (" << obs.wa << ' ' << obs.wb << ')' + << "; angle " << radToDeg(obs.theta()) + << "; direction " << vector::componentNames[obs.orient] + << "; }"; + break; + + case PDRobstacle::WALL_BEAM : + os << "wallbeam { point " << obs.pt + << " size " << obs.span + << "; }"; + break; + + case PDRobstacle::GRATING : + os << "grate { point " << obs.pt + << "; size " << obs.span + << "; slats " << obs.slat_width + << "; }"; + break; + + case PDRobstacle::LOUVER_BLOWOFF : + os << "louver { point " << obs.pt + << "; size " << obs.span + << "; pressure " << paToBar(obs.blowoff_press) + << "; }"; + break; + + case PDRobstacle::RECT_PATCH : + os << "patch { " << obs.pt + << "; size " << obs.span + << "; name " << obs.identifier + << "; }"; + break; + + case PDRobstacle::OLD_INLET : + case PDRobstacle::OLD_BLOWOFF : + case PDRobstacle::IGNITION : + os << "/* ignored: " << obs.typeId << " */"; + break; + + default: + os << "/* unknown: " << obs.typeId << " */"; + break; + + } + + return os; +} + + +// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * // + +bool Foam::operator<(const PDRobstacle& a, const PDRobstacle& b) +{ + return (a.pt.x() + a.sortBias) < (b.pt.x() + b.sortBias); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacle.H b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacle.H new file mode 100644 index 0000000000000000000000000000000000000000..0580a8015f1f71f8183a2b734aa1d0040bc83979 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacle.H @@ -0,0 +1,477 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::PDRobstacle + +Description + Obstacle definitions for PDR + +SourceFiles + PDRobstacle.C + PDRobstacleIO.C + PDRobstacleRead.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRobstacle_H +#define PDRobstacle_H + +#include "InfoProxy.H" +#include "labelPair.H" +#include "MeshedSurface.H" +#include "MeshedSurfacesFwd.H" +#include "boundBox.H" +#include "DynamicList.H" +#include "pointField.H" +#include "volumeType.H" +#include "memberFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class boundBox; +class PDRobstacle; + +Istream& operator>>(Istream& is, PDRobstacle& obs); +Ostream& operator<<(Ostream& os, const InfoProxy<PDRobstacle>& info); + +namespace vtk +{ + class surfaceWriter; +} + + +/*---------------------------------------------------------------------------*\ + Class PDRobstacle Declaration +\*---------------------------------------------------------------------------*/ + +class PDRobstacle +{ +public: + + //- Obstacle types (legacy numbering) + enum legacyTypes + { + NONE = 0, //!< Placeholder + CUBOID_1 = 1, + CYLINDER = 2, + LOUVER_BLOWOFF = 5, + LOUVRE_BLOWOFF = 5, + CUBOID = 6, + WALL_BEAM = 7, + GRATING = 8, + OLD_INLET = 9, //!< ignored (old) + OLD_BLOWOFF = 10, //!< ignored (old) + CIRC_PATCH = 12, + RECT_PATCH = 16, + DIAG_BEAM = 22, + IGNITION = 41, //!< ignored (old) + MESH_PLANE = 46, + IGNORE = 200 + }; + + + // Static Data Members + + //- The max blowoff pressure [bar] + // Primarily to catch accidental input in Pa or mbar + static constexpr int maxBlowoffPressure = 10; + + + // Data Members + + //- The group-id + label groupId; + + //- The obstacle type-id + int typeId; + + //- The x/y/z orientation (0,1,2) + direction orient; + + //- Bias for position sorting + scalar sortBias; + + //- The obstacle location. + // Lower corner for boxes, end-centre for cylinders + point pt; + + //- The obstacle dimensions (for boxes) + vector span; + + // Accessors for cylinders and diagonal blocks + + inline scalar dia() const { return span[vector::X]; } + inline scalar theta() const { return span[vector::Y]; } + inline scalar len() const { return span[vector::Z]; } + + inline scalar& dia() { return span[vector::X]; } + inline scalar& theta() { return span[vector::Y]; } + inline scalar& len() { return span[vector::Z]; } + + union + { + scalar wa; + scalar slat_width; + scalar blowoff_press; + }; + union + { + scalar wb; + scalar blowoff_time; + }; + scalar vbkge; + scalar xbkge; + scalar ybkge; + scalar zbkge; + + union + { + int blowoff_type; + int inlet_dirn; + }; + + string identifier; + +public: + + // Constructors + + //- Construct zero-initialized + PDRobstacle(); + + //- Read construct as named dictionary + explicit PDRobstacle(Istream& is); + + + // Member Function Selectors + + declareMemberFunctionSelectionTable + ( + void, + PDRobstacle, + read, + dictRead, + ( + PDRobstacle& obs, + const dictionary& dict + ), + (obs, dict) + ); + + + // Static Member Functions + + //- Read obstacle files and add to the lists + // \return the total volume + static scalar legacyReadFiles + ( + const fileName& obsFileDir, + const wordList& obsFileNames, + const boundBox& meshBb, + // output + DynamicList<PDRobstacle>& blocks, + DynamicList<PDRobstacle>& cylinders + ); + + //- Read obstacle files and set the lists + // \return the total volume + static scalar readFiles + ( + const fileName& obsFileDir, + const wordList& obsFileNames, + const boundBox& meshBb, + // output + DynamicList<PDRobstacle>& blocks, + DynamicList<PDRobstacle>& cylinders + ); + + + // Member Functions + + //- Read name / dictionary + bool read(Istream& is); + + //- Read the 'name' identifier if present + void readProperties(const dictionary& dict); + + //- Obstacle position accessors + inline scalar x() const { return pt.x(); } + inline scalar y() const { return pt.y(); } + inline scalar z() const { return pt.z(); } + inline scalar& x() { return pt.x(); } + inline scalar& y() { return pt.y(); } + inline scalar& z() { return pt.z(); } + + + //- Is obstacle type id cylinder-like? + inline static bool isCylinder(const label id); + + //- Is obstacle cylinder-like? + inline bool isCylinder() const; + + //- Reset to a zero obstacle + void clear(); + + //- Scale obstacle dimensions by specified scaling factor + // Zero and negative factors are ignored + void scale(const scalar factor); + + //- Volume of the obstacle + scalar volume() const; + + //- True if the obstacle is considered to be too small + bool tooSmall(const scalar minWidth) const; + + //- Set values from single-line, multi-column format. + // The only input format, but termed 'legacy' since it may + // be replaced in the near future. + // \return false if the scanning failed or if the obstacle type + // is not supported (or no longer supported) + bool setFromLegacy + ( + const int groupTypeId, + const string& buffer, + const label lineNo = -1, + const word& inputFile = word::null + ); + + //- Trim obstacle to ensure it is within the specified bounding box + volumeType trim(const boundBox& bb); + + //- Surface (points, faces) representation + meshedSurface surface() const; + + //- Add pieces to vtp output + static label addPieces + ( + vtk::surfaceWriter& surfWriter, + const UList<PDRobstacle>& list, + label pieceId = 0 + ); + + //- Generate multi-piece VTK (vtp) file of obstacles + static void generateVtk + ( + const fileName& outputDir, + const UList<PDRobstacle>& obslist, + const UList<PDRobstacle>& cyllist + ); + + + // IOstream Operators + + //- Return info proxy. + InfoProxy<PDRobstacle> info() const + { + return *this; + } + + friend Istream& operator>>(Istream& is, PDRobstacle& obs); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Global Operators + +//- Compare according to x0 position +bool operator<(const PDRobstacle& a, const PDRobstacle& b); + +//- For list output, assert that no obstacles are identical +inline bool operator!=(const PDRobstacle& a, const PDRobstacle& b) +{ + return true; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace PDRlegacy +{ + +/*---------------------------------------------------------------------------*\ + Class obstacleGrouping Declaration +\*---------------------------------------------------------------------------*/ + +//- Locations for each instance of an obstacle group. +class obstacleGrouping +: + public DynamicList<point> +{ + //- Number of obstacles counted + label nObstacle_; + + //- Number of cylinder-like obstacles counted + label nCylinder_; + + +public: + + //- Construct null + obstacleGrouping() + : + nObstacle_(0), + nCylinder_(0) + {} + + //- Construct with one location (instance) + explicit obstacleGrouping(const vector& origin) + : + obstacleGrouping() + { + append(origin); + } + + //- Clear obstacle count and locations + void clear() + { + nObstacle_ = 0; + nCylinder_ = 0; + DynamicList<point>::clear(); + } + + //- Increment the number of obstacles + void addObstacle() + { + ++nObstacle_; + } + + //- Increment the number of cylinder-like obstacles + void addCylinder() + { + ++nCylinder_; + } + + //- The number of obstacles + label nObstacle() const + { + return nObstacle_; + } + + //- The number of cylinder-like obstacles + label nCylinder() const + { + return nCylinder_; + } + + //- The number of locations x number of obstacles + label nTotalObstacle() const + { + return size() * nObstacle_; + } + + //- The number of locations x number of cylinder-like obstacles + label nTotalCylinder() const + { + return size() * nCylinder_; + } + + //- The number of locations x number of obstacles + label nTotal() const + { + return size() * (nObstacle_ + nCylinder_); + } + + //- Add a location + using DynamicList<point>::append; + + //- Add a location + void append(const scalar x, const scalar y, const scalar z) + { + append(point(x, y, z)); + } +}; + + +// Service Functions + +//- Read obstacle files, do counting only. +// \return nObstacle, nCylinder read +labelPair readObstacleFiles +( + const fileName& obsFileDir, + const wordList& obsFileNames, + Map<obstacleGrouping>& groups +); + + +//- Read obstacle files and add to the lists +// \return the total volume +scalar readObstacleFiles +( + const fileName& obsFileDir, + const wordList& obsFileNames, + const Map<obstacleGrouping>& groups, + const boundBox& meshBb, + // output + DynamicList<PDRobstacle>& blocks, + DynamicList<PDRobstacle>& cylinders +); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace PDRlegacy + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Global Operators + +//- Locations for each instance of an obstacle group. +inline Ostream& operator<< +( + Ostream& os, + const PDRlegacy::obstacleGrouping& group +) +{ + os << token::BEGIN_LIST + << group.size() << token::SPACE + << group.nObstacle() << token::SPACE + << group.nCylinder() << token::END_LIST; + + return os; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "PDRobstacleI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleI.H b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleI.H new file mode 100644 index 0000000000000000000000000000000000000000..954591664cc7253ead57b8a0d0a4a5fb2ddd8aab --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleI.H @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline bool Foam::PDRobstacle::isCylinder(const label id) +{ + return + ( + id == PDRobstacle::CYLINDER + || id == PDRobstacle::DIAG_BEAM + ); +} + + +inline bool Foam::PDRobstacle::isCylinder() const +{ + return isCylinder(typeId); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleIO.C b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleIO.C new file mode 100644 index 0000000000000000000000000000000000000000..1d4c9182f86a7bf723aabef3b54a351a5f23dca5 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleIO.C @@ -0,0 +1,353 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRsetFields.H" +#include "PDRobstacle.H" +#include "volumeType.H" + +using namespace Foam; +using namespace Foam::constant; + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::PDRobstacle::read(Istream& is) +{ + this->clear(); + + const word obsType(is); + const dictionary dict(is); + + const auto mfIter = readdictReadMemberFunctionTablePtr_->cfind(obsType); + + if (!mfIter.good()) + { + FatalIOErrorInFunction(is) + << "Unknown obstacle type: " << obsType << nl + << "Valid types:" << nl + << readdictReadMemberFunctionTablePtr_->sortedToc() << nl + << exit(FatalIOError); + } + + mfIter()(*this, dict); + + return true; +} + + +Foam::scalar Foam::PDRobstacle::readFiles +( + const fileName& obsFileDir, + const wordList& obsFileNames, + const boundBox& meshBb, + + DynamicList<PDRobstacle>& blocks, + DynamicList<PDRobstacle>& cylinders +) +{ + blocks.clear(); + cylinders.clear(); + + scalar totVolume = 0; + label nOutside = 0; + label nProtruding = 0; + + scalar shift = pars.obs_expand; + + if (!obsFileNames.empty()) + { + Info<< "Reading obstacle files" << nl; + } + + label maxGroup = -1; + + for (const word& inputFile : obsFileNames) + { + Info<< " file: " << inputFile << nl; + + fileName path = (obsFileDir / inputFile); + + IFstream is(path); + dictionary inputDict(is); + + const scalar scaleFactor = inputDict.getOrDefault<scalar>("scale", 0); + + const label verbose = inputDict.getOrDefault<label>("verbose", 0); + + for (const entry& dEntry : inputDict) + { + if (!dEntry.isDict()) + { + // ignore non-dictionary entry + continue; + } + + const dictionary& dict = dEntry.dict(); + + if (!dict.getOrDefault("enabled", true)) + { + continue; + } + + label obsGroupId = 0; + if (dict.readIfPresent("groupId", obsGroupId)) + { + maxGroup = max(maxGroup, obsGroupId); + } + else + { + obsGroupId = ++maxGroup; + } + + + pointField pts; + dict.readIfPresent("locations", pts); + if (pts.empty()) + { + pts.resize(1, Zero); + } + + List<PDRobstacle> obsInput; + dict.readEntry("obstacles", obsInput); + + label nCyl = 0; // The number of cylinders vs blocks + + for (PDRobstacle& obs : obsInput) + { + obs.groupId = obsGroupId; + obs.scale(scaleFactor); + + if (obs.isCylinder()) + { + ++nCyl; + } + } + + const label nBlock = (obsInput.size() - nCyl); + + blocks.reserve(blocks.size() + nBlock*pts.size()); + cylinders.reserve(cylinders.size() + nCyl*pts.size()); + + if (verbose) + { + Info<< "Read " << obsInput.size() << " obstacles (" + << nCyl << " cylinders) with " + << pts.size() << " locations" << nl; + + if (verbose > 1) + { + Info<< "locations " << pts << nl + << "obstacles " << obsInput << nl; + } + } + + for (const PDRobstacle& scanObs : obsInput) + { + // Reject anything below minimum width + if (scanObs.tooSmall(pars.min_width)) + { + continue; + } + + for (const point& origin : pts) + { + // A different (very small) shift for each obstacle + // so that faces cannot be coincident + + shift += floatSMALL; + const scalar shift2 = shift * 2.0; + + + switch (scanObs.typeId) + { + case PDRobstacle::CYLINDER: + { + // Make a copy + PDRobstacle obs(scanObs); + + // Offset for the group position + obs.pt += origin; + + // Shift the end outwards so, if exactly on + // cell boundary, now overlap cell. + // So included in Aw. + obs.pt -= point::uniform(shift); + obs.len() += shift2; + obs.dia() -= floatSMALL; + + + // Trim against the mesh bounds + // - ignore if it doesn't overlap + const volumeType vt = obs.trim(meshBb); + + switch (vt) + { + case volumeType::OUTSIDE: + ++nOutside; + continue; // Can ignore the rest + break; + + case volumeType::MIXED: + ++nProtruding; + break; + + default: + break; + } + + // Later for position sorting + switch (obs.orient) + { + case vector::X: + obs.sortBias = obs.len(); + break; + case vector::Y: + obs.sortBias = 0.5*obs.dia(); + break; + case vector::Z: + obs.sortBias = 0.5*obs.dia(); + break; + } + + totVolume += obs.volume(); + cylinders.append(obs); + + break; + } + + case PDRobstacle::DIAG_BEAM: + { + // Make a copy + PDRobstacle obs(scanObs); + + // Offset for the group position + obs.pt += origin; + + // Shift the end outwards so, if exactly on + // cell boundary, now overlap cell. + // So included in Aw. + obs.pt -= point::uniform(shift); + obs.len() += shift2; + obs.wa += shift2; + obs.wb += shift2; + + totVolume += obs.volume(); + cylinders.append(obs); + + break; + } + + case PDRobstacle::CUBOID_1: + case PDRobstacle::LOUVRE_BLOWOFF: + case PDRobstacle::CUBOID: + case PDRobstacle::WALL_BEAM: + case PDRobstacle::GRATING: + case PDRobstacle::RECT_PATCH: + { + // Make a copy + PDRobstacle obs(scanObs); + + // Offset for the position of the group + obs.pt += origin; + + if (obs.typeId == PDRobstacle::GRATING) + { + if (obs.slat_width <= 0) + { + obs.slat_width = pars.def_grating_slat_w; + } + } + + // Shift the end outwards so, if exactly on + // cell boundary, now overlap cell. + // So included in Aw. + obs.pt -= point::uniform(shift); + obs.span += point::uniform(shift2); + + + // Trim against the mesh bounds + // - ignore if it doesn't overlap + const volumeType vt = obs.trim(meshBb); + + switch (vt) + { + case volumeType::OUTSIDE: + ++nOutside; + continue; // Can ignore the rest + break; + + case volumeType::MIXED: + ++nProtruding; + break; + + default: + break; + } + + totVolume += obs.volume(); + + blocks.append(obs); + + break; + } + } + } + } + + // Info<< "Cylinders: " << cylinders << nl; + } + + if (nOutside || nProtruding) + { + Info<< "Warning: " << nOutside << " obstacles outside domain, " + << nProtruding << " obstacles partly outside domain" << nl; + } + } + + // #ifdef FULLDEBUG + // Info<< blocks << nl << cylinders << nl; + // #endif + + + Info<< "Number of obstacles: " + << (blocks.size() + cylinders.size()) << " (" + << cylinders.size() << " cylinders)" << nl; + + return totVolume; +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, PDRobstacle& obs) +{ + obs.read(is); + + return is; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleLegacyIO.C b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleLegacyIO.C new file mode 100644 index 0000000000000000000000000000000000000000..c2d305c08cfc51eb0925d39a19a4d96fae69c4b7 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleLegacyIO.C @@ -0,0 +1,475 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRobstacle.H" +#include "vector.H" +#include "doubleVector.H" +#include "stringOps.H" +#include "unitConversion.H" +#include <cmath> + +#define ReportLineInfo(line, file) \ + if (line >= 0 && !file.empty()) \ + { \ + Info<< " Line " << line << " of file '" << file << '\''; \ + } \ + Info<< nl; + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::PDRobstacle::setFromLegacy +( + const int groupTypeId, + const string& buffer, + const label lineNo, + const word& inputFile +) +{ + // Handling the optional identifier string can be a pain. + // Generally can only say that it exists if there are 15 or + // more columns. + // + // Cylinder has 8 normal entries + // Cuboid, diagonal beam etc have 14 normal entries + // However, reject anything that looks like a slipped numeric + + double dummy1; + + string in_ident; + + const auto columns = stringOps::splitSpace(buffer); + + for (std::size_t coli = 14; coli < columns.size(); ++coli) + { + // See if it can parse into a numerical value + if (!readDouble(columns[coli].str(), dummy1)) + { + // Not a numeric value. This must be our identifier + in_ident = buffer.substr(columns[coli].first - buffer.begin()); + + #ifdef FULLDEBUG + Info<< "Identifier: " << in_ident << nl; + #endif + break; + } + } + + // Strip off group number + groupId = groupTypeId / 100; + typeId = groupTypeId % 100; + + // This is a safe value + orient = vector::X; + + switch (typeId) + { + case PDRobstacle::CYLINDER: + { + // 8 Tokens + // "%d %lf %lf %lf %lf %lf %d %lf" + // USP 13/8/14 Read vbkge in case a negative cyl to punch a circular hole + + int in_typeId; + double in_x, in_y, in_z; + double in_len, in_dia; + int in_orient; + double in_poro; + + int nread = + sscanf + ( + buffer.c_str(), + "%d %lf %lf %lf %lf %lf %d %lf", + &in_typeId, &in_x, &in_y, &in_z, + &in_len, &in_dia, &in_orient, + &in_poro + ); + + if (nread < 8) + { + Info<< "Expected 8 items, but read in " << nread; + ReportLineInfo(lineNo, inputFile); + } + + identifier = in_ident; + pt = point(in_x, in_y, in_z); + + len() = in_len; + dia() = in_dia; + + orient = vector::X; // Check again later + + // Read porosity. Convert to blockage. + vbkge = 1.0 - in_poro; + + // Orientation (1,2,3) on input -> (0,1,2) + // - sortBias for later position sorting + switch (in_orient) + { + case 1: + orient = vector::X; + sortBias = len(); + break; + case 2: + orient = vector::Y; + sortBias = 0.5*dia(); + break; + case 3: + orient = vector::Z; + sortBias = 0.5*dia(); + break; + default: + sortBias = len(); + Info<< "Unexpected orientation " << in_orient; + ReportLineInfo(lineNo, inputFile); + break; + } + } + break; + + case PDRobstacle::DIAG_BEAM: + { + // A diagonal block + + // 14 columns + identifier + // "%d %lf %lf %lf %lf %lf %d %lf %lf %lf %lf %lf %d %lf %s" + // vbkge (porosity at this stage) should be 0. Not used (yet) + + int in_typeId; + double in_x, in_y, in_z; + double in_len, in_theta; + int in_orient; + double in_wa, in_wb, in_poro; + double col_11, col_12, col_14; + int col_13; + + int nread = + sscanf + ( + buffer.c_str(), + "%d %lf %lf %lf %lf %lf %d %lf %lf %lf %lf %lf %d %lf", + &in_typeId, &in_x, &in_y, &in_z, + &in_len, &in_theta, &in_orient, + &in_wa, &in_wb, &in_poro, + &col_11, &col_12, &col_13, &col_14 + ); + + if (nread < 14) + { + Info<< "Expected min 10 items, but read in " << nread; + ReportLineInfo(lineNo, inputFile); + } + + identifier = in_ident; + pt = point(in_x, in_y, in_z); + + len() = in_len; + dia() = 0; + theta() = 0; // Fix later on + + orient = vector::X; // Check again later + + wa = in_wa; + wb = in_wb; + + // Degrees on input, limit to range [0, PI] + while (in_theta > 180) in_theta -= 180; + while (in_theta < 0) in_theta += 180; + + // Swap axes when theta > PI/2 + // For 89-90 degrees it becomes -ve, which is picked up + // in next section + if (in_theta > 89) + { + in_theta -= 90; + // Swap wa <-> wb + wa = in_wb; + wb = in_wa; + } + + theta() = degToRad(in_theta); + + // Orientation (1,2,3) on input -> (0,1,2) + // - sortBias for later position sorting + switch (in_orient) + { + case 1: + orient = vector::X; + sortBias = len(); + break; + + case 2: + orient = vector::Y; + sortBias = 0.5*(wa * sin(theta()) + wb * cos(theta())); + break; + + case 3: + orient = vector::Z; + sortBias = 0.5*(wa * cos(theta()) + wb * sin(theta())); + break; + + default: + sortBias = len(); + Info<< "Unexpected orientation " << in_orient; + ReportLineInfo(lineNo, inputFile); + break; + } + + + // If very nearly aligned with axis, turn it into normal block, + // to avoid 1/tan(theta) blowing up + if (in_theta < 1) + { + switch (orient) + { + case vector::X: + span = vector(len(), wa, wb); + // Was end center, now lower corner + pt.y() = pt.y() - 0.5 * span.y(); + pt.z() = pt.z() - 0.5 * span.z(); + break; + + case vector::Y: + span = vector(wb, len(), wa); + // Was end center, now lower corner + pt.z() = pt.z() - 0.5 * span.z(); + pt.x() = pt.x() - 0.5 * span.x(); + break; + + case vector::Z: + span = vector(wa, wb, len()); + // Was end center, now lower corner + pt.x() = pt.x() - 0.5 * span.x(); + pt.y() = pt.y() - 0.5 * span.y(); + break; + } + + typeId = PDRobstacle::CUBOID; + sortBias = 0; + xbkge = ybkge = zbkge = vbkge = 1.0; + blowoff_type = 0; + + Info<< "... changed to type cuboid" << nl; + break; + } + } + break; + + case PDRobstacle::CUBOID_1: // Cuboid "Type 1" + case PDRobstacle::LOUVRE_BLOWOFF: // Louvred wall or blow-off panel + case PDRobstacle::CUBOID: // Cuboid + case PDRobstacle::WALL_BEAM: // Beam against wall (treated here as normal cuboid) + case PDRobstacle::GRATING: // Grating + case PDRobstacle::RECT_PATCH: // Inlet, outlet, other b.c. (rectangular) + { + // 14 columns + identifier + // "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %d %lf" + + int in_typeId; + double in_x, in_y, in_z; + double in_delx, in_dely, in_delz; + double in_poro, in_porox, in_poroy, in_poroz; + double col_12; + int col_13; + double in_blowoff_time = 0; + + int nread = + sscanf + ( + buffer.c_str(), + "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %d %lf", + &in_typeId, &in_x, &in_y, &in_z, + &in_delx, &in_dely, &in_delz, + &in_poro, &in_porox, &in_poroy, &in_poroz, + &col_12, &col_13, &in_blowoff_time + ); + + blowoff_time = scalar(in_blowoff_time); + + if (nread < 14) + { + Info<< "Expected 14 items, but read in " << nread; + ReportLineInfo(lineNo, inputFile); + } + + identifier = in_ident; + pt = point(in_x, in_y, in_z); + + span = vector(in_delx, in_dely, in_delz); + + // Read porosity. Convert to blockage. + vbkge = 1.0 - in_poro; + xbkge = 1.0 - in_porox; + ybkge = 1.0 - in_poroy; + zbkge = 1.0 - in_poroz; + + if + ( + typeId == PDRobstacle::CUBOID_1 + || typeId == PDRobstacle::WALL_BEAM + || typeId == PDRobstacle::RECT_PATCH + ) + { + // Check for invalid input + + if (vbkge != 1.0 || xbkge != 1.0 || ybkge != 1.0 || zbkge != 1.0) + { + Info<< "Type " << typeId << " is porous (setting to blockage)."; + ReportLineInfo(lineNo, inputFile); + + vbkge = 1; + xbkge = 1; + ybkge = 1; + zbkge = 1; + } + if (typeId == PDRobstacle::RECT_PATCH) + { + // Correct interpretation of column 13 + inlet_dirn = col_13; + + if (identifier.empty()) + { + FatalErrorInFunction + << "RECT_PATCH without a patch name" + << exit(FatalError); + } + } + } + else if (typeId == PDRobstacle::CUBOID) + { + } + else + { + if (!equal(cmptProduct(span), 0)) + { + Info<< "Type " << typeId << " has non-zero thickness."; + ReportLineInfo(lineNo, inputFile); + } + } + + if (typeId == PDRobstacle::LOUVRE_BLOWOFF) + { + // Blowoff panel + blowoff_press = barToPa(col_12); + blowoff_type = col_13; + + if (blowoff_type == 1) + { + Info<< "Type " << typeId + << ": blowoff-type 1 not yet implemented."; + ReportLineInfo(lineNo, inputFile); + + if (blowoff_time != 0) + { + Info<< "Type " << typeId << " has blowoff time set," + << " not set to blow off cell-by-cell"; + ReportLineInfo(lineNo, inputFile); + } + } + else + { + if + ( + (blowoff_type == 1 || blowoff_type == 2) + && (col_12 > 0) + ) + { + if (col_12 > maxBlowoffPressure) + { + Info<< "Blowoff pressure (" << col_12 + << ") too high for blowoff type " + << blowoff_type; + ReportLineInfo(lineNo, inputFile); + } + } + else + { + Info<< "Problem with blowoff parameters"; + ReportLineInfo(lineNo, inputFile); + Info<< "Col12 " << col_12 + << " Blowoff type " << blowoff_type + << ", blowoff pressure " << blowoff_press << nl; + } + } + } + else if (typeId == PDRobstacle::WALL_BEAM) + { + // WALL_BEAM against walls only contribute half to drag + // if ((col_12 == 1) || (col_12 == -1)) { against_wall_fac = 0.5; } + } + else if (typeId == PDRobstacle::GRATING) + { + if (col_12 > 0) + { + slat_width = col_12; + } + else + { + slat_width = 0; + } + + // Set orientation + if (equal(span.x(), 0)) + { + orient = vector::X; + } + else if (equal(span.y(), 0)) + { + orient = vector::Y; + } + else + { + orient = vector::Z; + } + } + } + break; + + case 0: // Group location + case PDRobstacle::OLD_INLET: // Ventilation source only + return false; + break; + + case PDRobstacle::IGNITION: // Ignition (now ignored. 2019-04) + Info<< "Ignition cell type ignored"; + ReportLineInfo(lineNo, inputFile); + return false; + break; + + default: + Info<< "Unexpected type " << typeId; + ReportLineInfo(lineNo, inputFile); + return false; + break; + } + + return true; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleLegacyRead.C b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleLegacyRead.C new file mode 100644 index 0000000000000000000000000000000000000000..27b1dd4fe64cbc621f98b6faa0cf045b053d3bd6 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleLegacyRead.C @@ -0,0 +1,567 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016 Shell Research Ltd. + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRsetFields.H" +#include "PDRobstacle.H" +#include "volumeType.H" + +using namespace Foam; +using namespace Foam::constant; + +#undef USE_ZERO_INSTANCE_GROUPS +// #define USE_ZERO_INSTANCE_GROUPS + + +// Counting +Foam::labelPair Foam::PDRlegacy::readObstacleFiles +( + const fileName& obsFileDir, + const wordList& obsFileNames, + Map<obstacleGrouping>& groups +) +{ + // Default group with single instance and position (0,0,0) + groups(0).clear(); + groups(0).append(point::zero); + + string buffer; + + if (!obsFileNames.empty()) + { + Info<< "Counting groups in obstacle files" << nl; + } + for (const word& inputFile : obsFileNames) + { + Info<< " file: " << inputFile << nl; + + fileName path = (obsFileDir / inputFile); + + IFstream is(path); + + while (is.good()) + { + // Process each line of obstacle files + is.getLine(buffer); + + const auto firstCh = buffer.find_first_not_of(" \t\n\v\f\r"); + + if + ( + firstCh == std::string::npos + || buffer[firstCh] == '#' + ) + { + // Empty line or comment line + continue; + } + + int typeId; + double x, y, z; // Double (not scalar) to match sscanf spec + + if + ( + sscanf(buffer.c_str(), "%d %lf %lf %lf", &typeId, &x, &y, &z)<4 + || typeId == 0 + || typeId == PDRobstacle::MESH_PLANE + ) + { + continue; + } + + x *= pars.scale; + y *= pars.scale; + z *= pars.scale; + + const label groupId = typeId / 100; + typeId %= 100; + + if (typeId == PDRobstacle::OLD_INLET) + { + Info<< "Ignored old-inlet type" << nl; + continue; + } + else if (typeId == PDRobstacle::GRATING && pars.ignoreGratings) + { + Info<< "Ignored grating" << nl; + continue; + } + + if (typeId == 0) + { + // Defining a group location + groups(groupId).append(x, y, z); + } + else if (PDRobstacle::isCylinder(typeId)) + { + // Increment cylinder count for the group + groups(groupId).addCylinder(); + } + else + { + // Increment obstacle count for the group + groups(groupId).addObstacle(); + } + } + } + + + label nTotalObs = 0; + label nTotalCyl = 0; + + label nMissedObs = 0; + label nMissedCyl = 0; + + forAllConstIters(groups, iter) + { + const auto& group = iter.val(); + + nTotalObs += group.nTotalObstacle(); + nTotalCyl += group.nTotalCylinder(); + + if (group.empty()) + { + nMissedObs += group.nObstacle(); + nMissedCyl += group.nCylinder(); + } + } + + for (const label groupId : groups.sortedToc()) + { + const auto& group = groups[groupId]; + + if (groupId) + { + if (group.size()) + { + Info<< "Found " << group.size() + << " instances of group " << groupId << " (" + << group.nObstacle() << " obstacles " + << group.nCylinder() << " cylinders)" + << nl; + } + } + else + { + // The group 0 is for ungrouped obstacles + Info<< "Found " + << group.nObstacle() << " obstacles " + << group.nCylinder() << " cylinders not in groups" << nl; + } + } + + Info<< "Number of obstacles: " + << (nTotalObs + nTotalCyl) << " (" + << nTotalCyl << " cylinders)" << nl; + + if (nMissedObs + nMissedCyl) + { + #ifdef USE_ZERO_INSTANCE_GROUPS + + nTotalObs += nMissedObs; + nTotalCyl += nMissedCyl; + Info<< "Adding " << (nMissedObs + nMissedCyl) + << " obstacles in groups without instances to default group" << nl; + + #else + + Warning + << nl << "Found " << (nMissedObs + nMissedCyl) + << " obstacles in groups without instances" << nl << nl; + + if (pars.debugLevel > 1) + { + for (const label groupId : groups.sortedToc()) + { + const auto& group = groups[groupId]; + + if + ( + groupId && group.empty() + && (group.nObstacle() || group.nCylinder()) + ) + { + Info<< " Group " << groupId << " (" + << group.nObstacle() << " obstacles " + << group.nCylinder() << " cylinders)" + << nl; + } + } + } + #endif + } + + return labelPair(nTotalObs, nTotalCyl); +} + + +Foam::scalar Foam::PDRlegacy::readObstacleFiles +( + const fileName& obsFileDir, + const wordList& obsFileNames, + const Map<obstacleGrouping>& groups, + const boundBox& meshBb, + + DynamicList<PDRobstacle>& blocks, + DynamicList<PDRobstacle>& cylinders +) +{ + // Catch programming errors + if (!groups.found(0)) + { + FatalErrorInFunction + << "No default group 0 defined!" << nl + << exit(FatalError); + } + + scalar totVolume = 0; + label nOutside = 0; + label nProtruding = 0; + + scalar shift = pars.obs_expand; + + string buffer; + + if (!obsFileNames.empty()) + { + Info<< "Reading obstacle files" << nl; + } + + for (const word& inputFile : obsFileNames) + { + Info<< " file: " << inputFile << nl; + + fileName path = (obsFileDir / inputFile); + + IFstream is(path); + + label lineNo = 0; + while (is.good()) + { + // Process each line of obstacle files + ++lineNo; + is.getLine(buffer); + + const auto firstCh = buffer.find_first_not_of(" \t\n\v\f\r"); + + if + ( + firstCh == std::string::npos + || buffer[firstCh] == '#' + ) + { + // Empty line or comment line + continue; + } + + // Quick reject + + int typeId; // Int (not label) to match sscanf spec + double x, y, z; // Double (not scalar) to match sscanf spec + + if + ( + sscanf(buffer.c_str(), "%d %lf %lf %lf", &typeId, &x, &y, &z) < 4 + || typeId == 0 + || typeId == PDRobstacle::MESH_PLANE + ) + { + continue; + } + + int groupId = typeId / 100; + typeId %= 100; + + if + ( + typeId == PDRobstacle::OLD_INLET + || (typeId == PDRobstacle::GRATING && pars.ignoreGratings) + ) + { + // Silent - already warned during counting + continue; + } + + if (typeId == 0) + { + // Group location - not an obstacle + continue; + } + + if (!groups.found(groupId)) + { + // Catch programming errors. + // - group should be there after the previous read + Warning + << "Encountered undefined group: " << groupId << nl; + continue; + } + + #ifdef USE_ZERO_INSTANCE_GROUPS + const obstacleGrouping& group = + ( + groups[groups[groupId].size() ? groupId : 0] + ); + #else + const obstacleGrouping& group = groups[groupId]; + #endif + + // Add the obstacle to the list with different position + // offsets according to its group. Non-group obstacles + // are treated as group 0, which has a single instance + // with position (0,0,0) and are added only once. + + PDRobstacle scanObs; + + if + ( + !scanObs.setFromLegacy + ( + (groupId * 100) + typeId, + buffer, + lineNo, + inputFile + ) + ) + { + continue; + } + + scanObs.scale(pars.scale); + + // Ignore anything below minimum width + if (scanObs.tooSmall(pars.min_width)) + { + continue; + } + + + for (const point& origin : group) + { + // A different (very small) shift for each obstacle + // so that faces cannot be coincident + shift += floatSMALL; + const scalar shift2 = shift * 2.0; + + switch (typeId) + { + case PDRobstacle::CYLINDER: + { + // Make a copy + PDRobstacle obs(scanObs); + + // Offset for the position of the group + obs.pt += origin; + + // Shift the end outwards so, if exactly on + // cell boundary, now overlap cell. + // So included in Aw. + obs.pt -= point::uniform(shift); + obs.len() += shift2; + obs.dia() -= floatSMALL; + + + // Trim against the mesh bounds + // - ignore if it doesn't overlap + const volumeType vt = obs.trim(meshBb); + + switch (vt) + { + case volumeType::OUTSIDE: + ++nOutside; + continue; // Can ignore the rest + break; + + case volumeType::MIXED: + ++nProtruding; + break; + + default: + break; + } + + // Later for position sorting + switch (obs.orient) + { + case vector::X: + obs.sortBias = obs.len(); + break; + case vector::Y: + obs.sortBias = 0.5*obs.dia(); + break; + case vector::Z: + obs.sortBias = 0.5*obs.dia(); + break; + } + + totVolume += obs.volume(); + cylinders.append(obs); + + break; + } + + case PDRobstacle::DIAG_BEAM: + { + // Make a copy + PDRobstacle obs(scanObs); + + // Offset for the position of the group + obs.pt += origin; + + // Shift the end outwards so, if exactly on + // cell boundary, now overlap cell. + // So included in Aw. + obs.pt -= point::uniform(shift); + obs.len() += shift2; + obs.wa += shift2; + obs.wb += shift2; + + totVolume += obs.volume(); + cylinders.append(obs); + + break; + } + + case PDRobstacle::CUBOID_1: // Cuboid "Type 1" + case PDRobstacle::LOUVRE_BLOWOFF: // Louvred wall or blow-off panel + case PDRobstacle::CUBOID: // Cuboid + case PDRobstacle::WALL_BEAM: // Beam against wall (treated here as normal cuboid) + case PDRobstacle::GRATING: // Grating + case PDRobstacle::RECT_PATCH: // Inlet, outlet or ather b.c. (rectangular) + { + // Make a copy + PDRobstacle obs(scanObs); + + // Offset for the position of the group + obs.pt += origin; + + if (typeId == PDRobstacle::GRATING) + { + if (obs.slat_width <= 0) + { + obs.slat_width = pars.def_grating_slat_w; + } + } + + // Shift the end outwards so, if exactly on + // cell boundary, now overlap cell. + // So included in Aw. + obs.pt -= point::uniform(shift); + obs.span += point::uniform(shift2); + + + // Trim against the mesh bounds + // - ignore if it doesn't overlap + const volumeType vt = obs.trim(meshBb); + + switch (vt) + { + case volumeType::OUTSIDE: + ++nOutside; + continue; // Can ignore the rest + break; + + case volumeType::MIXED: + ++nProtruding; + break; + + default: + break; + } + + totVolume += obs.volume(); + + blocks.append(obs); + + break; + } + } + } + } + + if (nOutside || nProtruding) + { + Info<< "Warning: " << nOutside << " obstacles outside domain, " + << nProtruding << " obstacles partly outside domain" << nl; + } + } + + + // #ifdef FULLDEBUG + // Info<< blocks << nl << cylinders << nl; + // #endif + + return totVolume; +} + + +Foam::scalar Foam::PDRobstacle::legacyReadFiles +( + const fileName& obsFileDir, + const wordList& obsFileNames, + const boundBox& meshBb, + DynamicList<PDRobstacle>& blocks, + DynamicList<PDRobstacle>& cylinders +) +{ + // Still just with legacy reading + + // Count the obstacles and get the group locations + Map<PDRlegacy::obstacleGrouping> groups; + + const labelPair obsCounts = + PDRlegacy::readObstacleFiles(obsFileDir, obsFileNames, groups); + + const label nObstacle = obsCounts.first(); + const label nCylinder = obsCounts.second(); + + // Info<< "grouping: " << groups << endl; + + if (!nObstacle && !nCylinder) + { + FatalErrorInFunction + << "No obstacles in domain" << nl + << exit(FatalError); + } + + blocks.clear(); + blocks.reserve(4 * max(4, nObstacle)); + + cylinders.clear(); + cylinders.reserve(4 * max(4, nCylinder)); + + return PDRlegacy::readObstacleFiles + ( + obsFileDir, obsFileNames, groups, + meshBb, + blocks, + cylinders + ); +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleTypes.C b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleTypes.C new file mode 100644 index 0000000000000000000000000000000000000000..3fc8275f46f689ea847f6bdd2e06080bae24364b --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleTypes.C @@ -0,0 +1,512 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "PDRobstacleTypes.H" +#include "PDRobstacleTypes.H" +#include "Enum.H" +#include "unitConversion.H" +#include "addToMemberFunctionSelectionTable.H" + +using namespace Foam::constant; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#define addObstacleReader(obsType, obsName) \ + namespace Foam \ + { \ + namespace PDRobstacles \ + { \ + addNamedToMemberFunctionSelectionTable \ + ( \ + PDRobstacle, \ + obsType, \ + read, \ + dictRead, \ + obsName \ + ); \ + } \ + } + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Read porosity, change to blockage. Clamp values [0-1] silently +static const scalarMinMax limits01(scalarMinMax::zero_one()); + +// Volume porosity -> blockage +inline scalar getPorosity(const dictionary& dict) +{ + return 1 - limits01.clip(dict.getOrDefault<scalar>("porosity", 0)); +} + +// Direction porosities -> blockage +inline vector getPorosities(const dictionary& dict) +{ + vector blockage(vector::one); + + if (dict.readIfPresent("porosities", blockage)) + { + for (scalar& val : blockage) + { + val = 1 - limits01.clip(val); + } + } + + return blockage; +} + + +// Check for "porosity", or "porosities" +// inline static bool hasPorosity(const dictionary& dict) +// { +// return dict.found("porosity") || dict.found("porosities"); +// } + + +static const Foam::Enum<Foam::vector::components> +vectorComponentsNames +({ + { vector::components::X, "x" }, + { vector::components::Y, "y" }, + { vector::components::Z, "z" }, +}); + + +enum inletDirnType +{ + _X = -1, // -ve x + _Y = -2, // -ve y + _Z = -3, // -ve z + X = 1, // +ve x + Y = 2, // +ve y + Z = 3, // +ve z +}; + +static const Foam::Enum<inletDirnType> +inletDirnNames +({ + { inletDirnType::_X, "-x" }, + { inletDirnType::_Y, "-y" }, + { inletDirnType::_Z, "-z" }, + { inletDirnType::_X, "_x" }, + { inletDirnType::_Y, "_y" }, + { inletDirnType::_Z, "_z" }, + { inletDirnType::X, "+x" }, + { inletDirnType::Y, "+y" }, + { inletDirnType::Z, "+z" }, + { inletDirnType::X, "x" }, + { inletDirnType::Y, "y" }, + { inletDirnType::Z, "z" }, +}); + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(cylinder, cyl); +addObstacleReader(cylinder, cylinder); + +void Foam::PDRobstacles::cylinder::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + obs.PDRobstacle::readProperties(dict); + obs.typeId = enumTypeId; + + // Enforce complete blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + // if (hasPorosity(dict)) ... warn? + + + dict.readEntry("point", obs.pt); + dict.readEntry("length", obs.len()); + dict.readEntry("diameter", obs.dia()); + + obs.orient = vectorComponentsNames.get("direction", dict); + + // The sortBias for later position sorting + switch (obs.orient) + { + case vector::X: + obs.sortBias = obs.len(); + break; + + default: + obs.sortBias = 0.5*obs.dia(); + break; + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(diagbeam, diag); +addObstacleReader(diagbeam, diagbeam); + +void Foam::PDRobstacles::diagbeam::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + obs.PDRobstacle::readProperties(dict); + obs.typeId = enumTypeId; + + // Enforce complete blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + // if (hasPorosity(dict)) ... warn? + + + dict.readEntry("point", obs.pt); + dict.readEntry("length", obs.len()); + obs.dia() = Zero; + obs.theta() = Zero; // Fix later on + + obs.orient = vectorComponentsNames.get("direction", dict); + + // Angle (degrees) on input, limit to range [0, PI] + scalar angle = dict.get<scalar>("angle"); + + while (angle > 180) angle -= 180; + while (angle < 0) angle += 180; + + labelPair dims; + dict.readEntry("width", dims); + + // Swap axes when theta > PI/2 + // For 89-90 degrees it becomes -ve, which is picked up in following section + if (angle > 89) + { + angle -= 90; + dims.flip(); // Swap dimensions + } + + obs.theta() = degToRad(angle); + + obs.wa = dims.first(); + obs.wb = dims.second(); + + const scalar ctheta = cos(obs.theta()); + const scalar stheta = sin(obs.theta()); + + // The sortBias for later position sorting + switch (obs.orient) + { + case vector::X: + obs.sortBias = obs.len(); + break; + + case vector::Y: + obs.sortBias = 0.5*(obs.wa * stheta + obs.wb * ctheta); + break; + + case vector::Z: + obs.sortBias = 0.5*(obs.wa * ctheta + obs.wb * stheta); + break; + } + + // If very nearly aligned with axis, turn it into normal block, + // to avoid 1/tan(theta) blowing up + if (angle < 1) + { + Info<< "... changed diag-beam to box" << nl; + + switch (obs.orient) + { + case vector::X: + obs.span = vector(obs.len(), obs.wa, obs.wb); + break; + + case vector::Y: + obs.span = vector(obs.wb, obs.len(), obs.wa); + break; + + case vector::Z: + obs.span = vector(obs.wa, obs.wb, obs.len()); + break; + } + + // The pt was end centre (cylinder), now lower corner + vector adjustPt = -0.5*obs.span; + adjustPt[obs.orient] = 0; + + obs.pt -= adjustPt; + + obs.typeId = PDRobstacles::cuboid::enumTypeId; + obs.sortBias = 0; + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1.0; + obs.blowoff_type = 0; + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(cuboid, box); + +void Foam::PDRobstacles::cuboid::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + obs.PDRobstacle::readProperties(dict); + obs.typeId = enumTypeId; + + // Default - full blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + + + dict.readEntry("point", obs.pt); + dict.readEntry("size", obs.span); + + // Optional + obs.vbkge = getPorosity(dict); + + // Optional + const vector blockages = getPorosities(dict); + obs.xbkge = blockages.x(); + obs.ybkge = blockages.y(); + obs.zbkge = blockages.z(); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(wallbeam, wallbeam); + +void Foam::PDRobstacles::wallbeam::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + PDRobstacles::cuboid::read(obs, dict); + obs.typeId = enumTypeId; + + // Enforce complete blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + + // if (hasPorosity(dict)) ... warn? + + // Additional adjustment for drag etc. +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(grating, grating); +addObstacleReader(grating, grate); + +void Foam::PDRobstacles::grating::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + obs.PDRobstacle::readProperties(dict); + obs.typeId = enumTypeId; + + // Initialize to full blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + + dict.readEntry("point", obs.pt); + dict.readEntry("size", obs.span); + + // TODO: better error handling + // if (!equal(cmptProduct(obs.span), 0)) + // { + // Info<< "Type " << typeId << " has non-zero thickness."; + // ReportLineInfo(lineNo, inputFile); + // } + + obs.vbkge = getPorosity(dict); + + const vector blockages = getPorosities(dict); + obs.xbkge = blockages.x(); + obs.ybkge = blockages.y(); + obs.zbkge = blockages.z(); + + // TODO: Warning if porosity was not specified? + + + // TBD: Default slat width from PDR.params + obs.slat_width = dict.getOrDefault<scalar>("slats", Zero); + + // Determine the orientation + if (equal(obs.span.x(), 0)) + { + obs.orient = vector::X; + } + else if (equal(obs.span.y(), 0)) + { + obs.orient = vector::Y; + } + else + { + obs.orient = vector::Z; + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(louver, louver); +addObstacleReader(louver, louvre); + +void Foam::PDRobstacles::louver::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + obs.PDRobstacle::readProperties(dict); + obs.typeId = enumTypeId; + + // Initialize to full blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + + dict.readEntry("point", obs.pt); + dict.readEntry("size", obs.span); + + // TODO: better error handling + // if (!equal(cmptProduct(obs.span), 0)) + // { + // Info<< "Type " << typeId << " has non-zero thickness."; + // ReportLineInfo(lineNo, inputFile); + // } + + obs.vbkge = getPorosity(dict); + + const vector blockages = getPorosities(dict); + obs.xbkge = blockages.x(); + obs.ybkge = blockages.y(); + obs.zbkge = blockages.z(); + + // TODO: Warning if porosity was not specified? + + + // Blowoff pressure [bar] + const scalar blowoffPress = dict.get<scalar>("pressure"); + + obs.blowoff_press = barToPa(blowoffPress); + obs.blowoff_time = dict.getOrDefault<scalar>("time", 0); + obs.blowoff_type = dict.getOrDefault<label>("type", 2); + + if (obs.blowoff_type == 1) + { + Info<< "Louver : blowoff-type 1 not yet implemented." << nl; + // ReportLineInfo(lineNo, inputFile); + + if (obs.blowoff_time != 0) + { + Info<< "Louver : has blowoff time set," + << " not set to blow off cell-by-cell" << nl; + // ReportLineInfo(lineNo, inputFile); + } + } + else + { + if + ( + (obs.blowoff_type == 1 || obs.blowoff_type == 2) + && (blowoffPress > 0) + ) + { + if (blowoffPress > maxBlowoffPressure) + { + Info<< "Blowoff pressure (" << blowoffPress + << ") too high for blowoff type " + << obs.blowoff_type << nl; + // ReportLineInfo(lineNo, inputFile); + } + } + else + { + Info<< "Problem with blowoff parameters" << nl; + // ReportLineInfo(lineNo, inputFile); + Info<< "Pressure[bar] " << blowoffPress + << " Blowoff type " << obs.blowoff_type + << ", blowoff pressure " << obs.blowoff_press << nl; + } + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +addObstacleReader(patch, patch); + +void Foam::PDRobstacles::patch::read +( + PDRobstacle& obs, + const dictionary& dict +) +{ + obs.PDRobstacle::readProperties(dict); + obs.typeId = enumTypeId; + + const auto nameLen = obs.identifier.length(); + + word patchName = word::validate(obs.identifier); + + if (patchName.empty()) + { + FatalErrorInFunction + << "RECT_PATCH without a patch name" + << exit(FatalError); + } + else if (patchName.length() != nameLen) + { + WarningInFunction + << "RECT_PATCH stripped invalid characters from patch name: " + << obs.identifier + << exit(FatalError); + + obs.identifier = std::move(patchName); + } + + // Enforce complete blockage + obs.xbkge = obs.ybkge = obs.zbkge = obs.vbkge = 1; + + dict.readEntry("point", obs.pt); + dict.readEntry("size", obs.span); + obs.inlet_dirn = inletDirnNames.get("direction", dict); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#undef addObstacleReader + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleTypes.H b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleTypes.H new file mode 100644 index 0000000000000000000000000000000000000000..9fa7d93a25d7e821de43df4fe725bd5a8b2b1f03 --- /dev/null +++ b/applications/utilities/preProcessing/PDRsetFields/obstacles/PDRobstacleTypes.H @@ -0,0 +1,300 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Namespace + Foam::PDRobstacles + +Description + Reader classes for concrete PDRsetFields obstacle types. + +SourceFiles + PDRobstacleTypes.C + +\*---------------------------------------------------------------------------*/ + +#ifndef PDRobstacleTypes_H +#define PDRobstacleTypes_H + +#include "PDRobstacle.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace PDRobstacles +{ + +/*---------------------------------------------------------------------------*\ + Class cylinder Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief A cylinder, selectable as \c cyl or \c cylinder + +Dictionary controls +\table + Property | Description | Required | Default + point | The end centre-point | yes | + length | The cylinder length | yes | + diameter | The cylinder diameter | yes | + direction | The x/y/z direction | yes | +\endtable + +Example, +\verbatim +cyl +{ + point (0 0 0); + length 0.95; + diameter 0.05; + direction x; +} +\endverbatim + +\note Does not have porosity. +*/ +struct cylinder : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::CYLINDER; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + + +/*---------------------------------------------------------------------------*\ + Class diagbeam Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief A diagonal beam, which is cylinder-like, + selectable as \c diag or \c diagbeam + + If the beam angle is close to zero, it will be changed to a box + (PDRobstacles::cuboid) + +Dictionary controls +\table + Property | Description | Required | Default + point | The end centre-point | yes | + length | The beam length | yes | + width | The beam cross-dimensions | yes | + angle | The beam angle (degrees) | yes | + direction | The x/y/z direction | yes | +\endtable + +Example, +\verbatim +diag +{ + point (0 0 0); + length 0.95; + width (0.05 0.01); + angle 25; + direction x; +} +\endverbatim + +\note Does not have porosity. +*/ +struct diagbeam : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::DIAG_BEAM; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + +/*---------------------------------------------------------------------------*\ + Class cuboid Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief A cuboid, selectable as \c box + +Dictionary controls +\table + Property | Description | Required | Default + point | The lower left corner | yes | + size | The (x y z) dimensions | yes | + porosity | The volumetric porosity | no | 0 + porosities | The directional porosities | no | (0 0 0) +\endtable + +Example, +\verbatim +box +{ + point (0 0 0); + size (0.05 0.05 2); +} +\endverbatim +*/ +struct cuboid : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::CUBOID; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + + +/*---------------------------------------------------------------------------*\ + Class wallbeam Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief A wallbeam, selectable as \c wallbeam which is currently identical + to a box (PDRobstacles::cuboid) + +Dictionary controls +\table + Property | Description | Required | Default + point | The lower left corner | yes | + size | The (x y z) dimensions | yes | +\endtable + +Example, +\verbatim +wallbeam +{ + point (0 0 0); + size (0.05 0.05 2); +} +\endverbatim + +\note Does not have porosity. +*/ +struct wallbeam : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::WALL_BEAM; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + +/*---------------------------------------------------------------------------*\ + Class grating Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief A grating, selectable as \c grate or \c grating + +The dimensions must include one component that is zero, +which establishes the orientation. + +Dictionary controls +\table + Property | Description | Required | Default + point | The lower left corner | yes | + size | The (x y z) dimensions | yes | + slats | The slat width | no | 0 +\endtable + +Example, +\verbatim +grating +{ + point (0 0 0); + size (0.1 0.1 0); + slats 0.005; +} +\endverbatim +*/ +struct grating : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::GRATING; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + +/*---------------------------------------------------------------------------*\ + Class louver Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief Louver blowoff, selectable as \c louver or \c louvre + +Dictionary controls +\table + Property | Description | Required | Default + point | The lower left corner | yes | + size | The (x y z) dimensions | yes | + pressure | The blowoff pressure (bar) | yes | + time | The blowoff time | no | 0 + type | The blowoff type (1, 2) | no | 1 +\endtable + +Example, +\verbatim +louver +{ + point (0 0 0); + size (0.1 0.1); + pressure 3; + type 1; +} +\endverbatim +*/ +struct louver : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::LOUVER_BLOWOFF; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + +/*---------------------------------------------------------------------------*\ + Class patch Declaration +\*---------------------------------------------------------------------------*/ + +/*! \brief Rectangular patch, selectable as \c patch + +Dictionary controls +\table + Property | Description | Required | Default + name | The patch name corner | yes | + point | The lower left corner | yes | + size | The (x y z) dimensions | yes | + direction | The direction (x/y/z, _x/_y/_z or "-x"/"-y"/"-z" | yes | +\endtable + +Example, +\verbatim +patch +{ + name inlet; + direction _x; + point (0 0 0); + size (0 0.05 1.0); +} +\endverbatim +*/ +struct patch : public PDRobstacle +{ + static constexpr int enumTypeId = legacyTypes::RECT_PATCH; + static void read(PDRobstacle& obs, const dictionary& dict); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace PDRobstacles +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/GRep b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/GRep new file mode 100644 index 0000000000000000000000000000000000000000..91573a0262e76574c33b87feeb659bc6a2a80445 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/GRep @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object GRep; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/GRxp b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/GRxp new file mode 100644 index 0000000000000000000000000000000000000000..39e5b0d4d5ca401c26d932f43bc4512330988ff2 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/GRxp @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object GRxp; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/RPers b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/RPers new file mode 100644 index 0000000000000000000000000000000000000000..b908ab1d38a9111ef49e7c28df9bc0507e3b1c39 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/RPers @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object RPers; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Su b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Su new file mode 100644 index 0000000000000000000000000000000000000000..83506af59e1b53d770481a06c2c9b939ae98ecc7 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Su @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Su; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform 0.5; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/T b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/T new file mode 100644 index 0000000000000000000000000000000000000000..ec6430d27b2774c4fcf5dbb0ede676aea7213b21 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/T @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Tu b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Tu new file mode 100644 index 0000000000000000000000000000000000000000..3dd7d9ef60d0ebcc5931a5d3e3d354c66cc94f93 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Tu @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Tu; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/U b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/U new file mode 100644 index 0000000000000000000000000000000000000000..fd04393804fb642088e0810361332c238ebb5219 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/U @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type fixedValue; + value uniform (0 0 0); + } + mergingFaces + { + type fixedValue; + value uniform (0 0 0); + } + wallFaces + { + type fixedValue; + value uniform (0 0 0); + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Xi b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Xi new file mode 100644 index 0000000000000000000000000000000000000000..8df42d17908e1af38cf503ef3c738431b73cc145 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Xi @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Xi; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Xp b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Xp new file mode 100644 index 0000000000000000000000000000000000000000..3561760892e973826d0cff631dfc38d0d18845ae --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/Xp @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Xp; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/b b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/b new file mode 100644 index 0000000000000000000000000000000000000000..de1bd852a700e9def854ef248cfb1258d6ab8842 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/b @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object b; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/epsilon b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/epsilon new file mode 100644 index 0000000000000000000000000000000000000000..83eea113dff87da9ff33822da8de3c2827a6a14b --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/epsilon @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +internalField uniform 1e-05; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type epsilonWallFunction; + value $internalField; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type epsilonWallFunction; + value $internalField; + } + wallFaces + { + type epsilonWallFunction; + value $internalField; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/ft b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/ft new file mode 100644 index 0000000000000000000000000000000000000000..3b93fe741f2f7c3e3b1b9a59af0f01035eff1750 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/ft @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object ft; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/k b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/k new file mode 100644 index 0000000000000000000000000000000000000000..a2bba748a9b78c1092a988e0fe23bdaf23fbb55a --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/k @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0.00015; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type kqRWallFunction; + value $internalField; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type kqRWallFunction; + value $internalField; + } + wallFaces + { + type kqRWallFunction; + value $internalField; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/nut b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/nut new file mode 100644 index 0000000000000000000000000000000000000000..224fc7a466fce1e7454e4c275d35707b2f9dde31 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/nut @@ -0,0 +1,60 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object nut; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + + seaGround + { + type nutkWallFunction; + value $internalField; + } + + blockedFaces + { + type zeroGradient; + } + + mergingFaces + { + type nutkWallFunction; + value $internalField; + } + + wallFaces + { + type nutkWallFunction; + value $internalField; + } + + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/0.orig/p b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/p new file mode 100644 index 0000000000000000000000000000000000000000..dc7c467281112a0bfdf625b9b449f721b2207768 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/0.orig/p @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 100000; + +boundaryField +{ + outer + { + type waveTransmissive; + gamma 1.3; + fieldInf 100000; + lInf 5; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/Allclean b/tutorials/combustion/PDRFoam/pipeLattice/Allclean new file mode 100755 index 0000000000000000000000000000000000000000..64ab01a64efa43371760ad8a6f8833179e2b339e --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/Allclean @@ -0,0 +1,13 @@ +#!/bin/sh +cd "${0%/*}" || exit # Run from this directory +. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions # Tutorial clean functions +#------------------------------------------------------------------------------ + +cleanCase0 + +# Remove some generated files +rm -f panelList +rm -f constant/ignitionPoint +rm -f system/PDRMeshDict + +#------------------------------------------------------------------------------ diff --git a/tutorials/combustion/PDRFoam/pipeLattice/Allrun b/tutorials/combustion/PDRFoam/pipeLattice/Allrun new file mode 100755 index 0000000000000000000000000000000000000000..96cbf639e0fecca1a377c2b63a4a2da885cdfd69 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/Allrun @@ -0,0 +1,34 @@ +#!/bin/sh +cd "${0%/*}" || exit # Run from this directory +. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions +#------------------------------------------------------------------------------ + +# For post-processing +runApplication -s dryrun PDRsetFields -dry-run + +restore0Dir + +runApplication PDRblockMesh + +runApplication PDRsetFields + +# Get location for ignition + +echo "Ignition point from constant/combustionProperties > system/ignitionPoint" +echo "// Ignition point extracted from constant/combustionProperties" >| \ + constant/ignitionPoint + +foamDictionary -entry ignitionSites \ + constant/combustionProperties | \ + sed -ne 's/^.*\(location *([^;]*\).*$/\1;/p' >> constant/ignitionPoint + +# Use constant/ignitionPoint for topoSet +runApplication topoSet + +runApplication refineHexMesh ignition + +runApplication setFields + +runApplication $(getApplication) + +#------------------------------------------------------------------------------ diff --git a/tutorials/combustion/PDRFoam/pipeLattice/constant/PDRProperties b/tutorials/combustion/PDRFoam/pipeLattice/constant/PDRProperties new file mode 100644 index 0000000000000000000000000000000000000000..0a01b14cd66a228cb9aa5ce4d90cda4da83db53e --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/constant/PDRProperties @@ -0,0 +1,286 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object PDRProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +StSmoothCoef 1000.0; + +//No smooth if >100 + +schelkin +{ + subGridSchelkin true; + uPrimeCoef 1.0; + lCoef 0.336; + maxSchFac 100.0; + nrCoef 0.1; + nrExp 0.0; + nrExp2 0.05; +} + +PDRDragModel basic; + +basicCoeffs +{ + drag on; + Csu 0.5; + Csk 0.05; +} + +basicSchCoeffs +{ + drag on; + $schelkin; + Csu 0.0; + Csk 0.0; +} + +XiModel transport; + +algebraicCoeffs +{ + XiShapeCoef 1; + XpShapeCoef 1; + CpfiDot 0.0; + CpfiCross 0.0; + GEtaExp 0.0; + LOverCw 0.01; +} + +transportTwoEqsCoeffs +{ + XiShapeCoef 1; + XpShapeCoef 1; + CpfiDot 0.0; + CpfiCross 0.0; + GEtaExp 0.0; + LOverCw 0.01; +} + +k3Coeffs +{ + k3Obs 10.0; + k3Open 1.0; +} + +transportThreeEqsCoeffs +{ + $transportTwoEqsCoeffs; + $k3Coeffs; +} + +transportFourEqsCoeffs +{ + $transportTwoEqsCoeffs; + $k3Coeffs; +} + +transportOneEqObsCoeffs +{ + XiShapeCoef 1; + Cpfi 0.0; + GEtaExp 0.0; +} + +transportXp +{ +} + +transportCoeffs +{ + XiShapeCoef 1; + GEtaExp 0.28; +} + +fixedCoeffs +{ +} + + +/*---------------------------------------------------------------------------*\ + XiEqModel : Model for XiEq +\*---------------------------------------------------------------------------*/ + +XiEqModel instability; + +BLMcoeffs +{ + XiEqCoef 1.0; + alphaCoefP 0.023; + alphaCoefN 0.085; + betaCoefP -0.0103; + betaCoefN -0.0075; + maLim 30.0; + maLim1 7.0; + quenchCoef 34.0; + quenchExp -1.8; + quenchM -4.0; + quenchRate1 0.6; + quenchRate2 0.14; +} + +instability2XiEqCoeffs +{ + defaultCIn 12.6; + XiEqInFade 1.0; + + XiEqModel BLMgMaXiEq; + + BLMgMaXiEqCoeffs + { + $schelkin; + gulderCoef 1.0; //this value is not usssed 1.0. + kaCoef 0.25; + lowK0 0.1; + lowKg 0.0; + gMaCoef 0.032; //not used + gMaCoef1 0.0; // not used + $BLMcoeffs; + } + + BLMXiEqCoeffs + { + $schelkin; + gulderCoef 0.31; + kaCoef 0.25; + lowK1 0.02; + lowK2 0.05; + $BLMcoeffs; + } +} + +instabilityCoeffs +{ + + XiEqIn 2.5; + XiEqModel Gulder; + GulderCoeffs + { + uPrimeCoef 1.0; + subGridSchelkin true; + XiEqCoef 0.62; + } + + SCOPEBlendCoeffs + { + XiEqModelL + { + XiEqModel Gulder; + + GulderCoeffs + { + $schelkin; + XiEqCoef 0.62; + } + } + + XiEqModelH + { + XiEqModel SCOPEXiEq; + + SCOPEXiEqCoeffs + { + $schelkin; + XiEqCoef 1.6; + XiEqExp 0.33333; + } + } + } +} + + +/*---------------------------------------------------------------------------*\ + XiGModel : Model for generation of Xi +\*---------------------------------------------------------------------------*/ + +XiGModel instabilityG; + +instability2GCoeffs +{ + lambdaIn 0.0001; + defaultCIn 10.0; + GInMult 5.0; + GInFade 4.0; + + XiGModel KTS; + + KTSCoeffs + { + GEtaCoef 0.28; + } +} + +instabilityGCoeffs +{ + lambdaIn 4.5e-3; + GIn 1.917; + + XiGModel KTS; + KTSCoeffs + { + GEtaCoef 0.28; + } +} + + +/*---------------------------------------------------------------------------*\ + XpEqGModel : Model for XpEq +\*---------------------------------------------------------------------------*/ + +XpEqModel normBasicSubGrid; + +normBasicSubGridCoeffs +{ + Cxpe1 800.0; + Cxpe2 40.0; + Cxpe3 400.0; + Cxpe4 1.0; +} + +basicSubGridCoeffs +{ +} + + +/*---------------------------------------------------------------------------*\ + XpGModel : Model for generation of Xp +\*---------------------------------------------------------------------------*/ + +XpGModel normBasicSubGridG; + +normBasicSubGridGCoeffs +{ + k1 0.0; + kb1 14.0; + kbe 1.5; + kbx 0.4; + k2 1.0; + LOverCw 0.01; + Cxpe1 800.0; + Cxpe2 40.0; + Cxpe3 400.0; + Cxpe4 1.0; +} + +basicSubGridGCoeffs +{ + XpGModel KTS; + KTSCoeffs + { + GEtaCoef 0.28; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/constant/combustionProperties b/tutorials/combustion/PDRFoam/pipeLattice/constant/combustionProperties new file mode 100644 index 0000000000000000000000000000000000000000..86df5fda40fa1c322a5df7c67d84ffe3da2e84c3 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/constant/combustionProperties @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object combustionProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +laminarFlameSpeedCorrelation SCOPE; + +fuel Methane; + +fuelFile "fuels/methane"; + +ignite yes; + +ignitionSites +( +{ + location (2.129836154 2.129836154 0.1773225); + diameter 0.0525394295667244; + start 2E-05; + duration 0.5; + strength 10.0; +} +); + +ignitionSphereFraction 1.0; + +ignitionThickness 0.05; + +ignitionCircleFraction 0.5; + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/constant/g b/tutorials/combustion/PDRFoam/pipeLattice/constant/g new file mode 100644 index 0000000000000000000000000000000000000000..d2f1c1c7d6c6af4fa2ad0042f93e89687bdf0bd6 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/constant/g @@ -0,0 +1,22 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; + +value ( 0 0 0 ); + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/constant/thermophysicalProperties b/tutorials/combustion/PDRFoam/pipeLattice/constant/thermophysicalProperties new file mode 100644 index 0000000000000000000000000000000000000000..e75e4d05653cafeda50186fc5f693cce26b17945 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/constant/thermophysicalProperties @@ -0,0 +1,145 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//thermoType hhuMixtureThermo<inhomogeneousMixture<sutherlandTransport<specieThermo<janafThermo<perfectGas>>>>>; + +thermoType +{ + type heheuPsiThermo; + mixture inhomogeneousMixture; + //mixture sprayHomogeneousMixtureDisp; + //mixture sprayInhomogeneousMixture; + //mixture inhomogeneousMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy absoluteEnthalpy; +} + +inertSpecie AIR; + +liquids +{ + //liquidComponents ( H2OPS ); + H2OPS + { + defaultCoeffs yes; + } + water + { + defaultCoeffs yes; + } +} + +solids +{ + //solidComponents ( ); +} + +stoichiometricAirFuelMassRatio 17.1667; + +fuel +{ + specie + { + nMoles 1; + molWeight 16.043; + } + thermodynamics + { + Tlow 20; + Thigh 5000; + Tcommon 1000; + highCpCoeffs (1.68348e+000 1.02372e-002 -3.87513e-006 6.78559e-010 -4.50342e-014 -10080.799805 9.623400); + lowCpCoeffs (7.78741e-001 1.74767e-002 -2.78341e-005 3.04971e-008 -1.22393e-011 -9825.230469 13.722200); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } +} + +oxidant +{ + specie + { + nMoles 1; + molWeight 28.8504; + } + thermodynamics + { + Tlow 20; + Thigh 5000; + Tcommon 1000; + highCpCoeffs (3.08854e+000 1.30434e-003 -4.75532e-007 8.34944e-011 -5.57380e-015 -988.135710 5.394344); + lowCpCoeffs (3.28067e+000 1.34928e-003 -3.25182e-006 4.73272e-009 -2.11558e-012 -1017.613519 4.388088); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } +} + +burntProducts +{ + specie + { + nMoles 1; + molWeight 27.633; + } + thermodynamics + { + Tlow 20; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 3.02337e+000 1.94303e-003 -6.93814e-007 1.17760e-010 -7.62884e-015 -10994.911525 5.489135); + lowCpCoeffs ( 3.21823e+000 2.61002e-003 -5.03021e-006 6.01014e-009 -2.42546e-012 -11067.319096 4.284645); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } +} + +steam +{ + specie + { + nMoles 1; + molWeight 18.02; + } + thermodynamics + { + Tlow 200.00; + Thigh 5000.00; + Tcommon 1000.00; + highCpCoeffs ( 2.67215e+00 3.05629e-03 -8.73026e-07 1.20100e-10 -6.39162e-15 -29899.199219 6.862820); + lowCpCoeffs ( 3.38684e+00 3.47498e-03 -6.35470e-06 6.96858e-09 -2.50659e-12 -30208.099609 2.590230); + } + transport + { + As 1.6721e-06; + Ts 1.7067e+02; + } +} + + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/constant/turbulenceProperties b/tutorials/combustion/PDRFoam/pipeLattice/constant/turbulenceProperties new file mode 100644 index 0000000000000000000000000000000000000000..bb3ff5e8194da994d0770ba501d36ab85292c76e --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/constant/turbulenceProperties @@ -0,0 +1,107 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object turbulenceProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType RAS; + +RAS +{ + RASModel PDRkEpsilon; + + PDRkEpsilonCoeffs + { + Cmu 0.09; + C1 1.44; + C2 1.92; + C3 -0.33;//0; (Original : -0.33) + C4 0.1; + alphah 1; + alphak 1; + alphaEps 0.76923; + } + + PDRkEpsilonFiltCoeffs + { + Cmu 0.09; + C1 1.44; + C2 1.92; + C3 -0.33; + C5 1.5; + C6 1.0; + alphah 1; + alphak 1; + alphaEps 0.76923; + noTurbUntil 0.0; + LOverLobs 0.2; + LOverMobs 0.0; + maxLOverCellW 2.0; + lCoef 0.35; + resCoef 0.0; + maxResFac 1.0; + filtRadMult 6.0; + bFilt 0.85; + flameFilteredG 1; + } + + PDRRNGkEpsilonCoeffs + { + Cmu 0.0845; + C1 1.42; + C2 1.68; + C3 -0.33; + sigmak 0.71942; + sigmaEps 0.71942; + eta0 4.38; + beta 0.012; + LOverLobs 0.5; + LOverMobs 0.5; + maxLOverCellW 2.0; + lCoef 0.35; + C5 1.5; + C6 1.0; + alphah 1; + alphak 1; + alphaEps 0.76923; + } + + + PDRrealkEpsilonCoeffs + { + Cmu 0.09; + A0 4.0; + C2 1.9; + C3 -0.33; + sigmak 1; + sigmaEps 0.71942; + eta0 4.38; + beta 0.012; + LOverLobs 0.5; + LOverMobs 0.5; + maxLOverCellW 2.0; + lCoef 0.35 ; + C5 1.5; + C6 1.0; + alphah 1; + alphak 1; + alphaEps 0.76923; + } + + turbulence on; + + printCoeffs on; +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/fuels/methane b/tutorials/combustion/PDRFoam/pipeLattice/fuels/methane new file mode 100644 index 0000000000000000000000000000000000000000..12168eed0f05965f414ae786456b68d8f8bb76c3 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/fuels/methane @@ -0,0 +1,152 @@ +// -*- C++ -*- + +name methane; + +SCOPECoeffs +{ + lowerFlammabilityLimit 0.502449441017432; + upperFlammabilityLimit 1.68468341988198; + + lowerSuPolynomial + { + lowerLimit 0.545; + upperLimit 1.16; + coefficients + ( + 0.35 + 0.907851467 + -6.629714256 + -8.646022633 + 16.38787781 + 37.29584992 + 0.0 + ); + } + + upperSuPolynomial + { + lowerLimit 1.1; + upperLimit 1.6; + coefficients + ( + 0.057804451 + 80.27932789 + -411.9361947 + 642.8456718 + -168.8792404 + -221.4502558 + 0.0 + ); + } + + lowerMaPolynomial + { + lowerLimit 0.5; + upperLimit 1.0581; + coefficients + ( + 3.73 + 1.6 + 4.0 + 1.0 + -12.0 + -11.0 + 0.0 + ); + } + + upperMaPolynomial + { + lowerLimit 1.0579; + upperLimit 2.684; + coefficients + ( + 4.13 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + ); + } + + Texp 2.0; + pexp -0.5; + CIn 10.2; +} + + +thermophysicalProperties +{ + thermoType hhuMixtureThermo<inhomogeneousMixture<sutherlandTransport<specieThermo<janafThermo<perfectGas>>>>>; + + stoichiometricAirFuelMassRatio 17.1667; + + fuel + { + specie + { + nMoles 1; + molWeight 16.043; + } + + thermodynamics + { + Tlow 20; + Thigh 5000; + Tcommon 1000; + highCpCoeffs (1.68348e+000 1.02372e-002 -3.87513e-006 6.78559e-010 -4.50342e-014 -10080.799805 9.623400); + lowCpCoeffs (7.78741e-001 1.74767e-002 -2.78341e-005 3.04971e-008 -1.22393e-011 -9825.230469 13.722200); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } + } + + oxidant + { + specie + { + nMoles 1; + molWeight 28.8504; + } + thermodynamics + { + Tlow 20; + Thigh 5000; + Tcommon 1000; + highCpCoeffs (3.08854e+000 1.30434e-003 -4.75532e-007 8.34944e-011 -5.57380e-015 -988.135710 5.394344); + lowCpCoeffs (3.28067e+000 1.34928e-003 -3.25182e-006 4.73272e-009 -2.11558e-012 -1017.613519 4.388088); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } + } + + burntProducts + { + specie + { + nMoles 1; + molWeight 27.633; + } + thermodynamics + { + Tlow 20; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 3.02337e+000 1.94303e-003 -6.93814e-007 1.17760e-010 -7.62884e-015 -10994.911525 5.489135); + lowCpCoeffs ( 3.21823e+000 2.61002e-003 -5.03021e-006 6.01014e-009 -2.42546e-012 -11067.319096 4.284645); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } + } +} diff --git a/tutorials/combustion/PDRFoam/pipeLattice/geometry/obstaclesDict b/tutorials/combustion/PDRFoam/pipeLattice/geometry/obstaclesDict new file mode 100644 index 0000000000000000000000000000000000000000..6f28d05f4f46f65973d1c6e3fc5225c71bcc64d8 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/geometry/obstaclesDict @@ -0,0 +1,22 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scale 1.0; +verbose 0; + +#include "pipeLattice" + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/geometry/pipeLattice b/tutorials/combustion/PDRFoam/pipeLattice/geometry/pipeLattice new file mode 100644 index 0000000000000000000000000000000000000000..c619493a6906e90fa7c9f4dc465a5c8ace84e7cf --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/geometry/pipeLattice @@ -0,0 +1,153 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_11z +{ + groupId 11; + + enabled true; + + // Dimensions + zpipe { direction z; length 2.132; diameter 0.082; } + + locations + ( + (0 0.13325 0) + (0 0.39975 0) + (0 0.66625 0) + (0 0.93275 0) + (0 1.19925 0) + (0 1.46575 0) + (0 1.73225 0) + (0 1.99875 0) + (0 2.26525 0) + (0 2.53175 0) + (0 2.79825 0) + (0 3.06475 0) + (0 3.33125 0) + (0 3.59775 0) + (0 3.86425 0) + (0 4.13075 0) + ); + + // z-direction + obstacles + ( + cyl { point (0.13325 0 0); $zpipe; } + cyl { point (0.39975 0 0); $zpipe; } + cyl { point (0.66625 0 0); $zpipe; } + cyl { point (0.93275 0 0); $zpipe; } + cyl { point (1.19925 0 0); $zpipe; } + cyl { point (1.46575 0 0); $zpipe; } + cyl { point (1.73225 0 0); $zpipe; } + cyl { point (1.99875 0 0); $zpipe; } + cyl { point (2.26525 0 0); $zpipe; } + cyl { point (2.53175 0 0); $zpipe; } + cyl { point (2.79825 0 0); $zpipe; } + cyl { point (3.06475 0 0); $zpipe; } + cyl { point (3.33125 0 0); $zpipe; } + cyl { point (3.59775 0 0); $zpipe; } + cyl { point (3.86425 0 0); $zpipe; } + cyl { point (4.13075 0 0); $zpipe; } + ); +} + + +_11y +{ + groupId 11; + enabled true; + + // Dimensions + ypipe { direction y; length 4.26; diameter 0.082; } + + locations + ( + (0.13325 0 0) + (0.39975 0 0) + (0.66625 0 0) + (0.93275 0 0) + (1.19925 0 0) + (1.46575 0 0) + (1.73225 0 0) + (1.99875 0 0) + (2.26525 0 0) + (2.53175 0 0) + (2.79825 0 0) + (3.06475 0 0) + (3.33125 0 0) + (3.59775 0 0) + (3.86425 0 0) + (4.13075 0 0) + ); + + // y-direction + obstacles + ( + cyl { point (0 0 0.13325); $ypipe; } + cyl { point (0 0 0.39975); $ypipe; } + cyl { point (0 0 0.66625); $ypipe; } + cyl { point (0 0 0.93275); $ypipe; } + cyl { point (0 0 1.19925); $ypipe; } + cyl { point (0 0 1.46575); $ypipe; } + cyl { point (0 0 1.73225); $ypipe; } + cyl { point (0 0 1.99875); $ypipe; } + ); +} + +_11x +{ + groupId 11; + enabled true; + + // Dimensions + xpipe { direction x; length 4.26; diameter 0.082; } + + locations + ( + (0 0.13325 0) + (0 0.39975 0) + (0 0.66625 0) + (0 0.93275 0) + (0 1.19925 0) + (0 1.46575 0) + (0 1.73225 0) + (0 1.99875 0) + (0 2.26525 0) + (0 2.53175 0) + (0 2.79825 0) + (0 3.06475 0) + (0 3.33125 0) + (0 3.59775 0) + (0 3.86425 0) + (0 4.13075 0) + ); + + // x-direction + obstacles + ( + cyl { point (0 0 0.13325); $xpipe; } + cyl { point (0 0 0.39975); $xpipe; } + cyl { point (0 0 0.66625); $xpipe; } + cyl { point (0 0 0.93275); $xpipe; } + cyl { point (0 0 1.19925); $xpipe; } + cyl { point (0 0 1.46575); $xpipe; } + cyl { point (0 0 1.73225); $xpipe; } + cyl { point (0 0 1.99875); $xpipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/PDRblockMeshDict b/tutorials/combustion/PDRFoam/pipeLattice/system/PDRblockMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..be0b184c482c7ba0eb29e335827a13495fbf31ee --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/PDRblockMeshDict @@ -0,0 +1,80 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object PDRblockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scale 1.0; + +x +{ + points ( -19.4 0 4.26 23.66 ); + nCells ( 14 13 14 ); + ratios ( 0.0887187064230887 1 10.6993205379072 ); +} + +y +{ + points ( -19.42 0 4.26 23.68 ); + nCells ( 14 13 14 ); + ratios ( 0.0887187064230887 1 10.6993205379072 ); +} + +z +{ + points (0 2.13 23.17 ); + nCells ( 6 14 ); + ratios ( 1 10.6993205379072 ); +} + + +// Or could use defaultFaces = outer instead +defaultPatch +{ + name defaultFaces; + type wall; +} + + +// Faces: 0 = xmin, 1 = xmax, 2 = ymin, 3 = ymax, 4 = zmin, 5 = zmax + +boundary +( + // Or with defaultFaces = outer + outer + { + type patch; + faces ( 0 1 2 3 5 ); + } + + mergingFaces + { + type wall; + faces (); + } + + blockedFaces + { + type wall; + faces (); + } + + wallFaces + { + type wall; + faces ( 4 ); + } +); + + +//***************************************************************************// diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/PDRsetFieldsDict b/tutorials/combustion/PDRFoam/pipeLattice/system/PDRsetFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..b7b56e52d492a000f72c04ca1e50aa619a7ab420 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/PDRsetFieldsDict @@ -0,0 +1,38 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object PDRsetFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Data dictionary for PDRsetFields + +// Replace by the relevant names + +obsFileDir "<case>/geometry"; + +obsFileNames (obstaclesDict); + +// legacyObsSpec true; +// +// obsFileNames (position.obs base.obs); + +// Some parameters for PDRfitMesh are read from this file, including + +cellWidth 0.22; + +outer (20 0); + +outerCombFac 0; + +sea_ground 0.0; + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/controlDict b/tutorials/combustion/PDRFoam/pipeLattice/system/controlDict new file mode 100644 index 0000000000000000000000000000000000000000..33f3ad490ed882edae33ad0aa5f5d4bf5208bad5 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/controlDict @@ -0,0 +1,58 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application PDRFoam; + +startFrom latestTime; + +startTime 0; + +stopAt endTime; + +endTime 0.125; + +deltaT 5e-06; + +writeControl runTime; + +writeInterval 0.001; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 8; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 0.3; + +maxDeltaT 1; + +functions +{ + #include "probes" +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/fvSchemes b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSchemes new file mode 100644 index 0000000000000000000000000000000000000000..80826a40dd424a4cdc4f4f667af2e0ae2cf9dcdb --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSchemes @@ -0,0 +1,124 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(p) Gauss linear; + grad(b) Gauss pointLinear; +} + +divSchemes +{ + default none; + + div(phi,U) Gauss limitedLinearV 1; + div(phiU,p) Gauss limitedLinear 1; + div(phid,p) Gauss limitedLinear 1; + div(phi,k) Gauss limitedLinear 1; + div(phi,epsilon) Gauss limitedLinear 1; + + div(phiXi,Xi) Gauss limitedLinear 1; + div(phiXi,Xp) Gauss limitedLinear 1; + + div(phi,Ep) Gauss limitedLinear 1; + div(phi,Xp) Gauss limitedLinear 1; + + div(phiXi,GRxp) Gauss limitedLinear 1; + div(phiXi,GRep) Gauss limitedLinear 1; + div(phiXi,Ep) Gauss limitedLinear 1; + div(phiSt,b) Gauss limitedLinear 1; + + div(phi,K) Gauss limitedLinear 1; + + div(phi,ft_b_ha_hau_H2OPS_Y) Gauss multivariateSelection + { + ft limitedLinear01 1; + b limitedLinear01 1; + Xi limitedLinear 1; + Xp limitedLinear 1; + Ep limitedLinear 1; + h limitedLinear 1; + hu limitedLinear 1; + ha limitedLinear 1; + hau limitedLinear 1; + H2OPS limitedLinear 1; + water limitedLinear 1; + Y limitedLinear 1; + AIR limitedLinear 1; + }; + + div(phi,ft_b_h_hu) Gauss multivariateSelection + { + ft limitedLinear01 1; + b limitedLinear01 1; + Xi limitedLinear 1; + Xp limitedLinear 1; + Ep limitedLinear 1; + h limitedLinear 1; + hu limitedLinear 1; + ha limitedLinear 1; + hau limitedLinear 1; + }; + + div(phi,ft_b_ha_hau) Gauss multivariateSelection + { + ft limitedLinear01 1; + b limitedLinear01 1; + Xi limitedLinear 1; + Xp limitedLinear 1; + Ep limitedLinear 1; + h limitedLinear 1; + hu limitedLinear 1; + ha limitedLinear 1; + hau limitedLinear 1; + }; + + div((Su*grad(b))) Gauss linear; + div((U+((Su*Xi)*grad(b)))) Gauss linear; + div((muEff*dev2(T(grad(U))))) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; + div(Ud) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear uncorrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default uncorrected; +} + +fluxRequired +{ + default no; + p; +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/fvSchemesUp b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSchemesUp new file mode 100644 index 0000000000000000000000000000000000000000..e1121ee86fc2b9540d040feacf74e2f22c813995 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSchemesUp @@ -0,0 +1,98 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(p) Gauss linear; + grad(b) fourth; +} + +divSchemes +{ + default Gauss upwind; +/* + div(phi,U) Gauss limitedLinearV 1; + div(phiU,p) Gauss limitedLinear 1; + div(phid,p) Gauss limitedLinear 1; + div(phi,k) Gauss limitedLinear 1; + div(phi,epsilon) Gauss limitedLinear 1; + + div(phiXi,Xi) Gauss limitedLinear 1; + div(phiSt,b) Gauss limitedLinear01 1; + + div(phi,K) Gauss limitedLinear 1; +*/ + div(phi,ft_b_h_hu) Gauss multivariateSelection + { + ft upwind;//limitedLinear01 1; + b upwind;//limitedLinear01 1; + Xi upwind;//limitedLinear 1; + h upwind;//limitedLinear 1; + hu upwind;//limitedLinear 1; + Xp upwind; + Ep upwind; + }; + + div((Su*grad(b))) Gauss linear; + div((U+((Su*Xi)*grad(b)))) Gauss linear; + //div((muEff*dev2(T(grad(U))))) Gauss linear; + div(U) Gauss linear; + div((muEff*dev2(T(grad(Ubet))))) Gauss linear; + div(phi,Ubet) Gauss linear; +} + +laplacianSchemes +{ + default none; + + laplacian(muEff,Ubet) Gauss linear limited 0.333; + laplacian(DkEff,k) Gauss linear limited 0.333; + laplacian(DepsilonEff,epsilon) Gauss linear limited 0.333; + laplacian((rho*inv((((1)*A(Ubet))+tDragDcu))),p) Gauss linear limited 0.333; + //laplacian((rho*inv((((1)*A(U))+((((0.5*rho)*CR)*mag(U))+((((Csu*(1))*betav)*muEff)*sqr(Aw)))))),p) Gauss linear limited 0.333; + laplacian(Db,b) Gauss linear limited 0.333; + laplacian(Db,ft) Gauss linear limited 0.333; + laplacian(Db,h) Gauss linear limited 0.333; + laplacian(Db,hu) Gauss linear limited 0.333; + laplacian(Db,Ep) Gauss linear limited 0.333; + laplacian(Db,GRxp) Gauss linear limited 0.333; + laplacian(Db,GRep) Gauss linear limited 0.333; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default limited 0.333; +} + +fluxRequired +{ + default no; + p; +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/fvSolution b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSolution new file mode 100644 index 0000000000000000000000000000000000000000..52a81a47ea2bf9abd61f5a317bf67e304b8954b4 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSolution @@ -0,0 +1,166 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + rho + { + solver PCG; + preconditioner DIC; + tolerance 1e-09; + relTol 0.0; + } + + rhoFinal + { + $rho; + } + + p + { + solver PCG; + preconditioner DIC; + tolerance 1e-09; + relTol 0.01; + } + + pFinal + { + $p; + relTol 0; + } + + /* "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-09; + relTol 0.01; + } + + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)Final" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-09; + relTol 0; + }*/ + + "(b|Xi|Xp|Ep|GRxp|GRep|ft|h|hu|ha|hau|k|epsilon)" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-09; + relTol 0.05; + } + "(b|Xi|Xp|Ep|GRxp|GRep|ft|h|hu|ha|hau|k|epsilon)Final" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-09; + relTol 0; + } +} + + +PIMPLE +{ + /* nCorrectors 3; + nOuterCorrectors 1; + nNonOrthogonalCorrectors 3; + momentumPredictor true;*/ + + nCorrectors 1; + nOuterCorrectors 10; + nNonOrthogonalCorrectors 3; + momentumPredictor true; + residualControl + { + b + { + tolerance 1e-5; + relTol 0; + } + p + { + tolerance 1e-5; + relTol 0; + } + Xi + { + tolerance 1e-5; + relTol 0; + } + Xp + { + tolerance 1e-5; + relTol 0; + } + Ep + { + tolerance 1e-5; + relTol 0; + } + ft + { + tolerance 1e-5; + relTol 0; + } + h + { + tolerance 1e-5; + relTol 0; + } + hu + { + tolerance 1e-5; + relTol 0; + } + k + { + tolerance 1e-5; + relTol 0; + } + epsilon + { + tolerance 1e-5; + relTol 0; + } + U + { + tolerance 1e-5; + relTol 0; + } + } +} + +relaxationFactors +{ + fields + { + } + equations + { + "U" 0.9; + "UFinal" 1.0; + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)" 0.9; + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)Final" 1.0; + } +} + + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/fvSolutionTrans b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSolutionTrans new file mode 100644 index 0000000000000000000000000000000000000000..9dfa3f82877003d5a4cc4e48ef0193bc262be206 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/fvSolutionTrans @@ -0,0 +1,168 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + rho + { + solver PCG; + preconditioner DIC; + tolerance 1e-09; + relTol 0.0; + } + + rhoFinal + { + $rho; + } + + p + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-9; + relTol 0.01; + } + + pFinal + { + $p; + relTol 0; + } + + /* "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-09; + relTol 0.01; + } + + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)Final" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-09; + relTol 0; + } + */ + "(b|Xi|Xp|Ep|GRxp|GRep|ft|h|hu|ha|hau|k|epsilon)" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-09; + relTol 0.05; + } + "(b|Xi|Xp|Ep|GRxp|GRep|ft|h|hu|ha|hau|k|epsilon)Final" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-09; + relTol 0; + } +} + + +PIMPLE +{ + /* nCorrectors 3; + nOuterCorrectors 1; + nNonOrthogonalCorrectors 3; + momentumPredictor true; + transonic true;*/ + + nCorrectors 1; + nOuterCorrectors 10; + nNonOrthogonalCorrectors 3; + momentumPredictor true; + transonic true; + + residualControl + { + b + { + tolerance 1e-5; + relTol 0; + } + p + { + tolerance 1e-5; + relTol 0; + } + Xi + { + tolerance 1e-5; + relTol 0; + } + Xp + { + tolerance 1e-5; + relTol 0; + } + Ep + { + tolerance 1e-5; + relTol 0; + } + ft + { + tolerance 1e-5; + relTol 0; + } + h + { + tolerance 1e-5; + relTol 0; + } + hu + { + tolerance 1e-5; + relTol 0; + } + k + { + tolerance 1e-5; + relTol 0; + } + epsilon + { + tolerance 1e-5; + relTol 0; + } + U + { + tolerance 1e-5; + relTol 0; + } + } +} + +relaxationFactors +{ + fields + { + } + equations + { + "U" 0.9; + "UFinal" 1.0; + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)" 0.9; + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)Final" 1.0; + } +} + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/probes b/tutorials/combustion/PDRFoam/pipeLattice/system/probes new file mode 100644 index 0000000000000000000000000000000000000000..6a6f2e3ebd1355089dcf42ab093c4c07eee09c61 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/probes @@ -0,0 +1,87 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ + +probes +{ + type probes; + libs (sampling); + + name probes; + + writeControl timeStep; + writeInterval 1; + + fields + ( + p + b + epsilon + ft + k + rho + St + Su + T + U + Xi + ); + + probeLocations + ( + (2. 1.95 0.1) + (2. 1.6 0.1) + (2. 1.2 0.1) + (2. 0.8 0.1) + (2. 0.4 0.1) + (2. 0.0 0.1) + (2.8 2.8 0.1) + (2 3.6 0.1) + (2. 2. 0.9) + (2. 2. 1.7) + (2. -0.2 0.1) + (2. -0.4 0.1) + + (2 2 0.1) + (2.8 2 0.1) + (3.6 2 0.1) + (4.6 2 0.1) + (5.6 2 0.1) + (2 2.8 0.1) + (2 3.6 0.1) + (2 8.448 0.1) + (2 5.6 0.1) + (2 2 0.9) + (2.8 2 0.9) + (3.6 2 0.9) + (4.6 2 0.9) + (5.6 2 0.9) + (2 2.8 0.9) + (2 3.6 0.9) + (2 8.448 0.9) + (2 5.6 0.9) + (2 2 1.9) + (2.8 2 1.9) + (3.6 2 1.9) + (4.6 2 1.9) + (5.6 2 1.9) + (2 2.8 1.9) + (2 3.6 1.9) + (2 8.448 1.9) + (2 5.6 1.9) + (2 2 2.9) + (2.8 2.8 0.1) + (2.8 2.8 0.9) + (2.8 2.8 1.9) + (3.6 3.6 0.1) + (3.6 3.6 0.9) + (3.6 3.6 1.9) + ); +} + + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/setFieldsDict b/tutorials/combustion/PDRFoam/pipeLattice/system/setFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..dbd9cc0f1cce858d49afe67669eeabf481a5ec03 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/setFieldsDict @@ -0,0 +1,40 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +defaultFieldValues +( + volScalarFieldValue p 100000 + volScalarFieldValue T 287 + volScalarFieldValue Tu 287 + volScalarFieldValue ft 0 +); + + +regions +( + boxToCell + { + box (0 0 0) (4.0 4.0 2.0); + + fieldValues + ( + volScalarFieldValue ft 0.0550457705582192 + ); + } +); + + +// ************************************************************************* // diff --git a/tutorials/combustion/PDRFoam/pipeLattice/system/topoSetDict b/tutorials/combustion/PDRFoam/pipeLattice/system/topoSetDict new file mode 100644 index 0000000000000000000000000000000000000000..3803ba26636fd59c9b2dcec4344db5aab8cd9593 --- /dev/null +++ b/tutorials/combustion/PDRFoam/pipeLattice/system/topoSetDict @@ -0,0 +1,55 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object topoSetDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Generated file +#include "<constant>/ignitionPoint" + +actions +( + { + name ignition; + type cellSet; + action new; + source nearestToCell; + points ( $location ); + } + + // Optionally grow cellSet by attached? + + /* + { + name corners; + type pointSet; + action new; + source cellToPoint; + set ignition; + option all; + } + + { + name ignition; + type cellSet; + action add; + source pointToCell; + + set corners; + option edge; + } + */ +); + + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/GRep b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/GRep new file mode 100644 index 0000000000000000000000000000000000000000..91573a0262e76574c33b87feeb659bc6a2a80445 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/GRep @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object GRep; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 -1 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/GRxp b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/GRxp new file mode 100644 index 0000000000000000000000000000000000000000..39e5b0d4d5ca401c26d932f43bc4512330988ff2 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/GRxp @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object GRxp; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/RPers b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/RPers new file mode 100644 index 0000000000000000000000000000000000000000..b908ab1d38a9111ef49e7c28df9bc0507e3b1c39 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/RPers @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object RPers; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Su b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Su new file mode 100644 index 0000000000000000000000000000000000000000..83506af59e1b53d770481a06c2c9b939ae98ecc7 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Su @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Su; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform 0.5; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/T b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/T new file mode 100644 index 0000000000000000000000000000000000000000..ec6430d27b2774c4fcf5dbb0ede676aea7213b21 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/T @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Tu b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Tu new file mode 100644 index 0000000000000000000000000000000000000000..3dd7d9ef60d0ebcc5931a5d3e3d354c66cc94f93 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Tu @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Tu; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/U b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/U new file mode 100644 index 0000000000000000000000000000000000000000..5af04f5243f2206733e048679e9bdcd30ca8405f --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/U @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} +// ************************************************************************* // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type fixedValue; + value uniform (0 0 0); + } + mergingFaces + { + type fixedValue; + value uniform (0 0 0); + } + wallFaces + { + type fixedValue; + value uniform (0 0 0); + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Xi b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Xi new file mode 100644 index 0000000000000000000000000000000000000000..8df42d17908e1af38cf503ef3c738431b73cc145 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Xi @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Xi; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Xp b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Xp new file mode 100644 index 0000000000000000000000000000000000000000..3561760892e973826d0cff631dfc38d0d18845ae --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/Xp @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object Xp; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/b b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/b new file mode 100644 index 0000000000000000000000000000000000000000..de1bd852a700e9def854ef248cfb1258d6ab8842 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/b @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object b; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/epsilon b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/epsilon new file mode 100644 index 0000000000000000000000000000000000000000..6499b26ea34756c763f1efa28219bcc730f91649 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/epsilon @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +internalField uniform 1e-05; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type compressible::epsilonWallFunction; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type compressible::epsilonWallFunction; + } + wallFaces + { + type compressible::epsilonWallFunction; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/ft b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/ft new file mode 100644 index 0000000000000000000000000000000000000000..3b93fe741f2f7c3e3b1b9a59af0f01035eff1750 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/ft @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object ft; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/k b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/k new file mode 100644 index 0000000000000000000000000000000000000000..645bc86628bae9cef2c9a8818ac363ccf979f8ae --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/k @@ -0,0 +1,54 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0.00015; + +boundaryField +{ + outer + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + seaGround + { + type compressible::kqRWallFunction; + value $internalField; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type compressible::kqRWallFunction; + value $internalField; + } + wallFaces + { + type compressible::kqRWallFunction; + value $internalField; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/p b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/p new file mode 100644 index 0000000000000000000000000000000000000000..dc7c467281112a0bfdf625b9b449f721b2207768 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/0.orig/p @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 100000; + +boundaryField +{ + outer + { + type waveTransmissive; + gamma 1.3; + fieldInf 100000; + lInf 5; + value $internalField; + } + seaGround + { + type zeroGradient; + } + blockedFaces + { + type zeroGradient; + } + mergingFaces + { + type zeroGradient; + } + wallFaces + { + type zeroGradient; + } + ySymmetry + { + type symmetryPlane; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/Allclean b/tutorials/preProcessing/PDRsetFields/simplePipeCage/Allclean new file mode 100755 index 0000000000000000000000000000000000000000..00bc8f41d32c3a8cb527a0e5ce1f555a1dfcbf40 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/Allclean @@ -0,0 +1,11 @@ +#!/bin/sh +cd "${0%/*}" || exit # Run from this directory +. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions # Tutorial clean functions +#------------------------------------------------------------------------------ + +cleanCase0 + +rm -f panelList +rm -f system/PDRMeshDict + +#------------------------------------------------------------------------------ diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/Allrun b/tutorials/preProcessing/PDRsetFields/simplePipeCage/Allrun new file mode 100755 index 0000000000000000000000000000000000000000..20c1699a003f1edf19ac07100949473296f4cb59 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/Allrun @@ -0,0 +1,15 @@ +#!/bin/sh +cd "${0%/*}" || exit # Run from this directory +. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions +#------------------------------------------------------------------------------ + +# Special version of blockMesh for i-j-k meshes +runApplication PDRblockMesh + +restore0Dir + +runApplication topoSet + +runApplication PDRsetFields + +#------------------------------------------------------------------------------ diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/PDRProperties b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/PDRProperties new file mode 100644 index 0000000000000000000000000000000000000000..4e6cdbaaef7d8e67a55ae8fd8d10ce153d9a961e --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/PDRProperties @@ -0,0 +1,98 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object PDRProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +PDRDragModel basic; + +basicCoeffs +{ + drag on; + Csu 0.5; + Csk 0.05; +} + +XiModel transport; + +transportCoeffs +{ + XiShapeCoef 1; +} + +XiEqModel instability; + +instabilityCoeffs +{ + XiEqIn 2.5; + + XiEqModel basicSubGrid; + + basicSubGridCoeffs + { + XiEqModel SCOPEBlend; + + SCOPEBlendCoeffs + { + XiEqModelL + { + XiEqModel Gulder; + + GulderCoeffs + { + XiEqCoef 0.62; + uPrimeCoef 1.0; + subGridSchelkin true; + } + } + + XiEqModelH + { + XiEqModel SCOPEXiEq; + + SCOPEXiEqCoeffs + { + XiEqCoef 1.6; + XiEqExp 0.33333; + lCoef 0.336; + uPrimeCoef 1.0; + subGridSchelkin true; + } + } + } + } +} + +XiGModel instabilityG; + +instabilityGCoeffs +{ + lambdaIn lambdaIn [0 1 0 0 0 0 0] 0.6; + GIn GIn [0 0 -1 0 0 0 0] 1.917; + + XiGModel basicSubGridG; + + basicSubGridGCoeffs + { + k1 0.5; + + XiGModel KTS; + + KTSCoeffs + { + GEtaCoef 0.28; + } + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/combustionProperties b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/combustionProperties new file mode 100644 index 0000000000000000000000000000000000000000..10285def2f989a23fbfb12277c2efc073a4f8aba --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/combustionProperties @@ -0,0 +1,45 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object combustionProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +laminarFlameSpeedCorrelation SCOPE; + +fuel Propane; + +fuelFile "fuels/propane.dat"; + +ignite yes; + +ignitionSites +( + + { + location (1.5 1.5 0.5); + diameter 0.1; + start 1E-05; + duration 0.05; + strength 60.0; + } +); + +ignitionSphereFraction 1; + +ignitionThickness ignitionThickness [0 1 0 0 0 0 0] 0; + +ignitionCircleFraction 0; + +ignitionKernelArea ignitionKernelArea [0 2 0 0 0 0 0] 0; + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/dynamicMeshDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/dynamicMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..5cc1535a20f341067a71c336a90d6b1835810137 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/dynamicMeshDict @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object dynamicMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dynamicFvMesh dynamicRefineFvMesh; + +// Refine every refineInterval timesteps +refineInterval 1; + +// Maximum refinement level (starts from 0) +maxRefinement 2; + +// Maximum cell limit (approximate) +maxCells 10000; + +// volScalarField to base refinement on +field normalisedGradP; + +nBufferLayers 1; + +dumpLevel true; + +lowerRefineLevel 0.5; +upperRefineLevel 1.5; + +unrefineLevel 0.5; + +nBufferLayers 1; +// Newly introduced patch points optionally get projected onto a surface +//projectSurfaces ("fixedWalls4.stl"); +//projectPatches (fixedWalls); +// Maximum project distance +//projectDistance 1; + +// Fluxes to adapt. For newly created faces or split faces the flux +// gets estimated from an interpolated volVectorField ('velocity') +// First is name of the flux to adapt, second is velocity that will +// be interpolated and inner-producted with the face area vector. +correctFluxes ((phi rhoU) (phi_0 none)); + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/g b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/g new file mode 100644 index 0000000000000000000000000000000000000000..bf2b7b10ab10e01d72e7b2937be35adc522c030c --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/g @@ -0,0 +1,20 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -2 0 0 0 0]; +value (0 0 -9.8); + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/thermophysicalProperties b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/thermophysicalProperties new file mode 100644 index 0000000000000000000000000000000000000000..02466ff11a14c094803ae069d070ad440bb620f3 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/thermophysicalProperties @@ -0,0 +1,93 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object thermophysicalProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heheuPsiThermo; + mixture inhomogeneousMixture; + transport sutherland; + thermo janaf; + equationOfState perfectGas; + specie specie; + energy absoluteEnthalpy; +} + +stoichiometricAirFuelMassRatio stoichiometricAirFuelMassRatio [0 0 0 0 0 0 0] 15.5776; + +fuel +{ + specie + { + molWeight 44.0962; + } + thermodynamics + { + Tlow 200; + Thigh 5000; + Tcommon 1000; + highCpCoeffs ( 7.53414 0.0188722 -6.27185e-06 9.14756e-10 -4.78381e-14 -16467.5 -17.8923 ); + lowCpCoeffs ( 0.933554 0.0264246 6.10597e-06 -2.19775e-08 9.51493e-12 -13958.5 19.2017 ); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } +} + +oxidant +{ + specie + { + molWeight 28.8504; + } + thermodynamics + { + Tlow 200; + Thigh 6000; + Tcommon 1000; + highCpCoeffs ( 3.10131 0.00124137 -4.18816e-07 6.64158e-11 -3.91274e-15 -985.266 5.35597 ); + lowCpCoeffs ( 3.58378 -0.000727005 1.67057e-06 -1.09203e-10 -4.31765e-13 -1050.53 3.11239 ); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } +} + +burntProducts +{ + specie + { + molWeight 28.3233; + } + thermodynamics + { + Tlow 200; + Thigh 6000; + Tcommon 1000; + highCpCoeffs ( 3.10558 0.00179747 -5.94696e-07 9.05605e-11 -5.08443e-15 -11003.6 5.12104 ); + lowCpCoeffs ( 3.49796 0.000638555 -1.83881e-07 1.20989e-09 -7.68691e-13 -11080.5 3.18188 ); + } + transport + { + As 1.67212e-06; + Ts 170.672; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/turbulenceProperties b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/turbulenceProperties new file mode 100644 index 0000000000000000000000000000000000000000..e15633083e18964ce7eedf94a8c01994a871afcf --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/constant/turbulenceProperties @@ -0,0 +1,40 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType RAS; + +RAS +{ + RASModel PDRkEpsilon; + + PDRkEpsilonCoeffs + { + Cmu 0.09; + C1 1.44; + C2 1.92; + C3 0; + C4 0.1; + alphah 1; + alphak 1; + alphaEps 0.76923; + } + + turbulence on; + + printCoeffs on; +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group01 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group01 new file mode 100644 index 0000000000000000000000000000000000000000..4d1c628811521c6888bca821efc5972c455204e8 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group01 @@ -0,0 +1,66 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_01 +{ + groupId 1; + + obstacles + ( + box { point (0 0 0); size (0.05 0.05 2); } + box { point (1 0 0); size (0.05 0.05 2); } + box { point (2 0 0); size (0.05 0.05 2); } + box { point (3 0 0); size (0.05 0.05 2); } + box { point (0 1 0); size (0.05 0.05 2); } + box { point (1 1 0); size (0.05 0.05 2); } + box { point (2 1 0); size (0.05 0.05 2); } + box { point (3 1 0); size (0.05 0.05 2); } + box { point (0 2 0); size (0.05 0.05 2); } + box { point (1 2 0); size (0.05 0.05 2); } + box { point (2 2 0); size (0.05 0.05 2); } + box { point (3 2 0); size (0.05 0.05 2); } + box { point (0 3 0); size (0.05 0.05 2); } + box { point (1 3 0); size (0.05 0.05 2); } + box { point (2 3 0); size (0.05 0.05 2); } + box { point (3 3 0); size (0.05 0.05 2); } + box { point (0 0 0); size (0.05 3.05 0.05); } + box { point (1 0 0); size (0.05 3.05 0.05); } + box { point (2 0 0); size (0.05 3.05 0.05); } + box { point (3 0 0); size (0.05 3.05 0.05); } + box { point (0 0 1); size (0.05 3.05 0.05); } + box { point (1 0 1); size (0.05 3.05 0.05); } + box { point (2 0 1); size (0.05 3.05 0.05); } + box { point (3 0 1); size (0.05 3.05 0.05); } + box { point (0 0 2); size (0.05 3.05 0.05); } + box { point (1 0 2); size (0.05 3.05 0.05); } + box { point (2 0 2); size (0.05 3.05 0.05); } + box { point (3 0 2); size (0.05 3.05 0.05); } + box { point (0 0 0); size (3.05 0.05 0.05); } + box { point (0 1 0); size (3.05 0.05 0.05); } + box { point (0 2 0); size (3.05 0.05 0.05); } + box { point (0 3 0); size (3.05 0.05 0.05); } + box { point (0 0 1); size (3.05 0.05 0.05); } + box { point (0 1 1); size (3.05 0.05 0.05); } + box { point (0 2 1); size (3.05 0.05 0.05); } + box { point (0 3 1); size (3.05 0.05 0.05); } + box { point (0 0 2); size (3.05 0.05 0.05); } + box { point (0 1 2); size (3.05 0.05 0.05); } + box { point (0 2 2); size (3.05 0.05 0.05); } + box { point (0 3 2); size (3.05 0.05 0.05); } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group11 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group11 new file mode 100644 index 0000000000000000000000000000000000000000..e90a7ecba8bb31c596d6f22c692381fbc80c552b --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group11 @@ -0,0 +1,58 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_11 +{ + groupId 11; + + zpipe { direction z; length 0.947; diameter 0.026; } + box1 { size (0.006 3.05 0.05); } + + obstacles + ( + box { point (1.012 0.95 0.05 ); size (1.038 0.05 0.006); } + box { point (1.012 0.95 0.997 ); size (1.038 0.05 0.006); } + box { point (1.012 2.05 0.05 ); size (1.038 0.05 0.006); } + box { point (1.012 2.05 0.997 ); size (1.038 0.05 0.006); } + box { point (0.95 1.012 0.05 ); size (0.05 1.038 0.006); } + box { point (0.95 1.012 0.997 ); size (0.05 1.038 0.006); } + box { point (2.05 1.012 0.05 ); size (0.05 1.038 0.006); } + box { point (2.05 1.012 0.997 ); size (0.05 1.038 0.006); } + + cyl { point (1.031 0.975 0.056); $zpipe; } + cyl { point (1.281 0.975 0.056); $zpipe; } + cyl { point (1.531 0.975 0.056); $zpipe; } + cyl { point (1.781 0.975 0.056); $zpipe; } + cyl { point (2.031 0.975 0.056); $zpipe; } + cyl { point (1.031 2.075 0.056); $zpipe; } + cyl { point (1.281 2.075 0.056); $zpipe; } + cyl { point (1.531 2.075 0.056); $zpipe; } + cyl { point (1.781 2.075 0.056); $zpipe; } + cyl { point (2.031 2.075 0.056); $zpipe; } + cyl { point (0.975 1.031 0.056); $zpipe; } + cyl { point (0.975 1.281 0.056); $zpipe; } + cyl { point (0.975 1.531 0.056); $zpipe; } + cyl { point (0.975 1.781 0.056); $zpipe; } + cyl { point (0.975 2.031 0.056); $zpipe; } + cyl { point (2.075 1.031 0.056); $zpipe; } + cyl { point (2.075 1.281 0.056); $zpipe; } + cyl { point (2.075 1.531 0.056); $zpipe; } + cyl { point (2.075 1.781 0.056); $zpipe; } + cyl { point (2.075 2.031 0.056); $zpipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group14 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group14 new file mode 100644 index 0000000000000000000000000000000000000000..b49e826db50952f40e6aee36185e0ea12b19281f --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group14 @@ -0,0 +1,81 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_14 +{ + groupId 14; + xpipe { direction x; length 0.947; diameter 0.026; } + box1 { size (0.006 3.05 0.05); } + + locations + ( + (0 0 0.15) + (0 0 0.45) + ); + + obstacles + ( + box { point (0.05 0 1.05 ); $box1; } + box { point (0.997 0 1.05 ); $box1; } + box { point (1.05 0 1.05 ); $box1; } + box { point (1.997 0 1.05 ); $box1; } + box { point (2.05 0 1.05 ); $box1; } + box { point (2.997 0 1.05 ); $box1; } + cyl { point (0.05 0.025 1.075); $xpipe; } + cyl { point (0.05 0.275 1.075); $xpipe; } + cyl { point (0.05 0.525 1.075); $xpipe; } + cyl { point (0.05 0.775 1.075); $xpipe; } + cyl { point (0.05 1.025 1.075); $xpipe; } + cyl { point (0.05 1.275 1.075); $xpipe; } + cyl { point (0.05 1.525 1.075); $xpipe; } + cyl { point (0.05 1.775 1.075); $xpipe; } + cyl { point (0.05 2.025 1.075); $xpipe; } + cyl { point (0.05 2.275 1.075); $xpipe; } + cyl { point (0.05 2.525 1.075); $xpipe; } + cyl { point (0.05 2.775 1.075); $xpipe; } + cyl { point (0.05 3.025 1.075); $xpipe; } + cyl { point (1.05 0.025 1.075); $xpipe; } + cyl { point (1.05 0.275 1.075); $xpipe; } + cyl { point (1.05 0.525 1.075); $xpipe; } + cyl { point (1.05 0.775 1.075); $xpipe; } + cyl { point (1.05 1.025 1.075); $xpipe; } + cyl { point (1.05 1.275 1.075); $xpipe; } + cyl { point (1.05 1.525 1.075); $xpipe; } + cyl { point (1.05 1.775 1.075); $xpipe; } + cyl { point (1.05 2.025 1.075); $xpipe; } + cyl { point (1.05 2.275 1.075); $xpipe; } + cyl { point (1.05 2.525 1.075); $xpipe; } + cyl { point (1.05 2.775 1.075); $xpipe; } + cyl { point (1.05 3.025 1.075); $xpipe; } + cyl { point (2.05 0.025 1.075); $xpipe; } + cyl { point (2.05 0.275 1.075); $xpipe; } + cyl { point (2.05 0.525 1.075); $xpipe; } + cyl { point (2.05 0.775 1.075); $xpipe; } + cyl { point (2.05 1.025 1.075); $xpipe; } + cyl { point (2.05 1.275 1.075); $xpipe; } + cyl { point (2.05 1.525 1.075); $xpipe; } + cyl { point (2.05 1.775 1.075); $xpipe; } + cyl { point (2.05 2.025 1.075); $xpipe; } + cyl { point (2.05 2.275 1.075); $xpipe; } + cyl { point (2.05 2.525 1.075); $xpipe; } + cyl { point (2.05 2.775 1.075); $xpipe; } + cyl { point (2.05 3.025 1.075); $xpipe; } + ); + + #remove (pipe box1) +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group15 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group15 new file mode 100644 index 0000000000000000000000000000000000000000..7e9565deacbe25a37c692e8ba3c052d86d1edec9 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group15 @@ -0,0 +1,110 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_15 +{ + groupId 15; + + xpipe { direction x; length 0.947; diameter 0.026; } + + obstacles + ( + box { point (0.05 0 1.05); size (0.006 3.05 0.05); } + box { point (0.997 0 1.05); size (0.006 3.05 0.05); } + box { point (1.05 0 1.05); size (0.006 3.05 0.05); } + box { point (1.997 0 1.05); size (0.006 3.05 0.05); } + box { point (2.05 0 1.05); size (0.006 3.05 0.05); } + box { point (2.997 0 1.05); size (0.006 3.05 0.05); } + + cyl { point (0.05 0.025 1.075); $xpipe; } + cyl { point (0.05 0.15 1.075); $xpipe; } + cyl { point (0.05 0.275 1.075); $xpipe; } + cyl { point (0.05 0.4 1.075); $xpipe; } + cyl { point (0.05 0.525 1.075); $xpipe; } + cyl { point (0.05 0.65 1.075); $xpipe; } + cyl { point (0.05 0.775 1.075); $xpipe; } + cyl { point (0.05 0.9 1.075); $xpipe; } + cyl { point (0.05 1.025 1.075); $xpipe; } + cyl { point (0.05 1.15 1.075); $xpipe; } + cyl { point (0.05 1.275 1.075); $xpipe; } + cyl { point (0.05 1.4 1.075); $xpipe; } + cyl { point (0.05 1.525 1.075); $xpipe; } + cyl { point (0.05 1.65 1.075); $xpipe; } + cyl { point (0.05 1.775 1.075); $xpipe; } + cyl { point (0.05 1.9 1.075); $xpipe; } + cyl { point (0.05 2.025 1.075); $xpipe; } + cyl { point (0.05 2.15 1.075); $xpipe; } + cyl { point (0.05 2.275 1.075); $xpipe; } + cyl { point (0.05 2.4 1.075); $xpipe; } + cyl { point (0.05 2.525 1.075); $xpipe; } + cyl { point (0.05 2.65 1.075); $xpipe; } + cyl { point (0.05 2.775 1.075); $xpipe; } + cyl { point (0.05 2.9 1.075); $xpipe; } + cyl { point (0.05 3.025 1.075); $xpipe; } + cyl { point (1.05 0.025 1.075); $xpipe; } + cyl { point (1.05 0.15 1.075); $xpipe; } + cyl { point (1.05 0.275 1.075); $xpipe; } + cyl { point (1.05 0.4 1.075); $xpipe; } + cyl { point (1.05 0.525 1.075); $xpipe; } + cyl { point (1.05 0.65 1.075); $xpipe; } + cyl { point (1.05 0.775 1.075); $xpipe; } + cyl { point (1.05 0.9 1.075); $xpipe; } + cyl { point (1.05 1.025 1.075); $xpipe; } + cyl { point (1.05 1.15 1.075); $xpipe; } + cyl { point (1.05 1.275 1.075); $xpipe; } + cyl { point (1.05 1.4 1.075); $xpipe; } + cyl { point (1.05 1.525 1.075); $xpipe; } + cyl { point (1.05 1.65 1.075); $xpipe; } + cyl { point (1.05 1.775 1.075); $xpipe; } + cyl { point (1.05 1.9 1.075); $xpipe; } + cyl { point (1.05 2.025 1.075); $xpipe; } + cyl { point (1.05 2.15 1.075); $xpipe; } + cyl { point (1.05 2.275 1.075); $xpipe; } + cyl { point (1.05 2.4 1.075); $xpipe; } + cyl { point (1.05 2.525 1.075); $xpipe; } + cyl { point (1.05 2.65 1.075); $xpipe; } + cyl { point (1.05 2.775 1.075); $xpipe; } + cyl { point (1.05 2.9 1.075); $xpipe; } + cyl { point (1.05 3.025 1.075); $xpipe; } + cyl { point (2.05 0.025 1.075); $xpipe; } + cyl { point (2.05 0.15 1.075); $xpipe; } + cyl { point (2.05 0.275 1.075); $xpipe; } + cyl { point (2.05 0.4 1.075); $xpipe; } + cyl { point (2.05 0.525 1.075); $xpipe; } + cyl { point (2.05 0.65 1.075); $xpipe; } + cyl { point (2.05 0.775 1.075); $xpipe; } + cyl { point (2.05 0.9 1.075); $xpipe; } + cyl { point (2.05 1.025 1.075); $xpipe; } + cyl { point (2.05 1.15 1.075); $xpipe; } + cyl { point (2.05 1.275 1.075); $xpipe; } + cyl { point (2.05 1.4 1.075); $xpipe; } + cyl { point (2.05 1.525 1.075); $xpipe; } + cyl { point (2.05 1.65 1.075); $xpipe; } + cyl { point (2.05 1.775 1.075); $xpipe; } + cyl { point (2.05 1.9 1.075); $xpipe; } + cyl { point (2.05 2.025 1.075); $xpipe; } + cyl { point (2.05 2.15 1.075); $xpipe; } + cyl { point (2.05 2.275 1.075); $xpipe; } + cyl { point (2.05 2.4 1.075); $xpipe; } + cyl { point (2.05 2.525 1.075); $xpipe; } + cyl { point (2.05 2.65 1.075); $xpipe; } + cyl { point (2.05 2.775 1.075); $xpipe; } + cyl { point (2.05 2.9 1.075); $xpipe; } + cyl { point (2.05 3.025 1.075); $xpipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group17 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group17 new file mode 100644 index 0000000000000000000000000000000000000000..661b534e0be6e1c38848c535e4940a903cfba626 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group17 @@ -0,0 +1,80 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_17 +{ + groupId 17; + + locations + ( + (0 0 0) + (0 0 0.30) + ); + + ypipe { direction y; length 0.947; diameter 0.026; } + + obstacles + ( + box { point (0 0.05 1.05); size (3.05 0.006 0.05); } + box { point (0 0.997 1.05); size (3.05 0.006 0.05); } + box { point (0 1.05 1.05); size (3.05 0.006 0.05); } + box { point (0 1.997 1.05); size (3.05 0.006 0.05); } + box { point (0 2.05 1.05); size (3.05 0.006 0.05); } + box { point (0 2.997 1.05); size (3.05 0.006 0.05); } + + cyl { point (0.025 0.05 1.075); $ypipe; } + cyl { point (0.275 0.05 1.075); $ypipe; } + cyl { point (0.525 0.05 1.075); $ypipe; } + cyl { point (0.775 0.05 1.075); $ypipe; } + cyl { point (1.025 0.05 1.075); $ypipe; } + cyl { point (1.275 0.05 1.075); $ypipe; } + cyl { point (1.525 0.05 1.075); $ypipe; } + cyl { point (1.775 0.05 1.075); $ypipe; } + cyl { point (2.025 0.05 1.075); $ypipe; } + cyl { point (2.275 0.05 1.075); $ypipe; } + cyl { point (2.525 0.05 1.075); $ypipe; } + cyl { point (2.775 0.05 1.075); $ypipe; } + cyl { point (3.025 0.05 1.075); $ypipe; } + cyl { point (0.025 1.05 1.075); $ypipe; } + cyl { point (0.275 1.05 1.075); $ypipe; } + cyl { point (0.525 1.05 1.075); $ypipe; } + cyl { point (0.775 1.05 1.075); $ypipe; } + cyl { point (1.025 1.05 1.075); $ypipe; } + cyl { point (1.275 1.05 1.075); $ypipe; } + cyl { point (1.525 1.05 1.075); $ypipe; } + cyl { point (1.775 1.05 1.075); $ypipe; } + cyl { point (2.025 1.05 1.075); $ypipe; } + cyl { point (2.275 1.05 1.075); $ypipe; } + cyl { point (2.525 1.05 1.075); $ypipe; } + cyl { point (2.775 1.05 1.075); $ypipe; } + cyl { point (3.025 1.05 1.075); $ypipe; } + cyl { point (0.025 2.05 1.075); $ypipe; } + cyl { point (0.275 2.05 1.075); $ypipe; } + cyl { point (0.525 2.05 1.075); $ypipe; } + cyl { point (0.775 2.05 1.075); $ypipe; } + cyl { point (1.025 2.05 1.075); $ypipe; } + cyl { point (1.275 2.05 1.075); $ypipe; } + cyl { point (1.525 2.05 1.075); $ypipe; } + cyl { point (1.775 2.05 1.075); $ypipe; } + cyl { point (2.025 2.05 1.075); $ypipe; } + cyl { point (2.275 2.05 1.075); $ypipe; } + cyl { point (2.525 2.05 1.075); $ypipe; } + cyl { point (2.775 2.05 1.075); $ypipe; } + cyl { point (3.025 2.05 1.075); $ypipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group21 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group21 new file mode 100644 index 0000000000000000000000000000000000000000..55896c2b56a69dbe7f8d82186ee67ac447e5090b --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group21 @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_21 +{ + groupId 21; + + zpipe { direction z; length 0.947; diameter 0.026; } + + obstacles + ( + box { point (0.831 0.8 0.05 ); size (1.338 0.05 0.006); } + box { point (0.831 0.8 0.997); size (1.338 0.05 0.006); } + box { point (0.8 0.831 0.05 ); size (0.05 1.338 0.006); } + box { point (0.8 0.831 0.997); size (0.05 1.338 0.006); } + box { point (0.831 2.2 0.05 ); size (1.338 0.05 0.006); } + box { point (0.831 2.2 0.997); size (1.338 0.05 0.006); } + box { point (2.2 0.831 0.05 ); size (0.05 1.338 0.006); } + box { point (2.2 0.831 0.997); size (0.05 1.338 0.006); } + + cyl { point (0.875 0.825 0.056); $zpipe; } + cyl { point (1.125 0.825 0.056); $zpipe; } + cyl { point (1.375 0.825 0.056); $zpipe; } + cyl { point (1.625 0.825 0.056); $zpipe; } + cyl { point (1.875 0.825 0.056); $zpipe; } + cyl { point (2.125 0.825 0.056); $zpipe; } + cyl { point (0.875 2.225 0.056); $zpipe; } + cyl { point (1.125 2.225 0.056); $zpipe; } + cyl { point (1.375 2.225 0.056); $zpipe; } + cyl { point (1.625 2.225 0.056); $zpipe; } + cyl { point (1.875 2.225 0.056); $zpipe; } + cyl { point (2.125 2.225 0.056); $zpipe; } + cyl { point (0.825 0.875 0.056); $zpipe; } + cyl { point (0.825 1.125 0.056); $zpipe; } + cyl { point (0.825 1.375 0.056); $zpipe; } + cyl { point (0.825 1.625 0.056); $zpipe; } + cyl { point (0.825 1.875 0.056); $zpipe; } + cyl { point (0.825 2.125 0.056); $zpipe; } + cyl { point (2.225 0.875 0.056); $zpipe; } + cyl { point (2.225 1.125 0.056); $zpipe; } + cyl { point (2.225 1.375 0.056); $zpipe; } + cyl { point (2.225 1.625 0.056); $zpipe; } + cyl { point (2.225 1.875 0.056); $zpipe; } + cyl { point (2.225 2.125 0.056); $zpipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group31 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group31 new file mode 100644 index 0000000000000000000000000000000000000000..34773281b42c5212ac33764f23efa82d0808ff85 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group31 @@ -0,0 +1,65 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_31 +{ + groupId 31; + + zpipe { direction z; length 0.947; diameter 0.026; } + + obstacles + ( + box { point (0.681 0.65 0.05 ); size (1.638 0.05 0.006); } + box { point (0.681 0.65 0.997); size (1.638 0.05 0.006); } + box { point (0.681 2.35 0.05 ); size (1.638 0.05 0.006); } + box { point (0.681 2.35 0.997); size (1.638 0.05 0.006); } + box { point (0.65 0.681 0.05 ); size (0.05 1.638 0.006); } + box { point (0.65 0.681 0.997); size (0.05 1.638 0.006); } + box { point (2.35 0.681 0.05 ); size (0.05 1.638 0.006); } + box { point (2.35 0.681 0.997); size (0.05 1.638 0.006); } + + cyl { point (0.75 0.675 0.056); $zpipe; } + cyl { point (1 0.675 0.056); $zpipe; } + cyl { point (1.25 0.675 0.056); $zpipe; } + cyl { point (1.5 0.675 0.056); $zpipe; } + cyl { point (1.75 0.675 0.056); $zpipe; } + cyl { point (2 0.675 0.056); $zpipe; } + cyl { point (2.25 0.675 0.056); $zpipe; } + cyl { point (0.75 2.375 0.056); $zpipe; } + cyl { point (1 2.375 0.056); $zpipe; } + cyl { point (1.25 2.375 0.056); $zpipe; } + cyl { point (1.5 2.375 0.056); $zpipe; } + cyl { point (1.75 2.375 0.056); $zpipe; } + cyl { point (2 2.375 0.056); $zpipe; } + cyl { point (2.25 2.375 0.056); $zpipe; } + cyl { point (0.675 0.75 0.056); $zpipe; } + cyl { point (0.675 1 0.056); $zpipe; } + cyl { point (0.675 1.25 0.056); $zpipe; } + cyl { point (0.675 1.5 0.056); $zpipe; } + cyl { point (0.675 1.75 0.056); $zpipe; } + cyl { point (0.675 2 0.056); $zpipe; } + cyl { point (0.675 2.25 0.056); $zpipe; } + cyl { point (2.375 0.75 0.056); $zpipe; } + cyl { point (2.375 1 0.056); $zpipe; } + cyl { point (2.375 1.25 0.056); $zpipe; } + cyl { point (2.375 1.5 0.056); $zpipe; } + cyl { point (2.375 1.75 0.056); $zpipe; } + cyl { point (2.375 2 0.056); $zpipe; } + cyl { point (2.375 2.25 0.056); $zpipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group41 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group41 new file mode 100644 index 0000000000000000000000000000000000000000..b97404e028faa4eb8fc9a051a1ed94525071cace --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/groups/group41 @@ -0,0 +1,69 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +_41 +{ + groupId 41; + + zpipe { direction z; length 0.947; diameter 0.026; } + + obstacles + ( + box { point (0.531 0.5 0.05 ); size (1.938 0.05 0.006); } + box { point (0.531 0.5 0.997); size (1.938 0.05 0.006); } + box { point (0.531 2.5 0.05 ); size (1.938 0.05 0.006); } + box { point (0.531 2.5 0.997); size (1.938 0.05 0.006); } + box { point (0.5 0.531 0.05 ); size (0.05 1.938 0.006); } + box { point (0.5 0.531 0.997); size (0.05 1.938 0.006); } + box { point (2.5 0.531 0.05 ); size (0.05 1.938 0.006); } + box { point (2.5 0.531 0.997); size (0.05 1.938 0.006); } + + cyl { point (0.625 0.525 0.056); $zpipe; } + cyl { point (0.875 0.525 0.056); $zpipe; } + cyl { point (1.125 0.525 0.056); $zpipe; } + cyl { point (1.375 0.525 0.056); $zpipe; } + cyl { point (1.625 0.525 0.056); $zpipe; } + cyl { point (1.875 0.525 0.056); $zpipe; } + cyl { point (2.125 0.525 0.056); $zpipe; } + cyl { point (2.375 0.525 0.056); $zpipe; } + cyl { point (0.625 2.525 0.056); $zpipe; } + cyl { point (0.875 2.525 0.056); $zpipe; } + cyl { point (1.125 2.525 0.056); $zpipe; } + cyl { point (1.375 2.525 0.056); $zpipe; } + cyl { point (1.625 2.525 0.056); $zpipe; } + cyl { point (1.875 2.525 0.056); $zpipe; } + cyl { point (2.125 2.525 0.056); $zpipe; } + cyl { point (2.375 2.525 0.056); $zpipe; } + cyl { point (0.525 0.625 0.056); $zpipe; } + cyl { point (0.525 0.875 0.056); $zpipe; } + cyl { point (0.525 1.125 0.056); $zpipe; } + cyl { point (0.525 1.375 0.056); $zpipe; } + cyl { point (0.525 1.625 0.056); $zpipe; } + cyl { point (0.525 1.875 0.056); $zpipe; } + cyl { point (0.525 2.125 0.056); $zpipe; } + cyl { point (0.525 2.375 0.056); $zpipe; } + cyl { point (2.525 0.625 0.056); $zpipe; } + cyl { point (2.525 0.875 0.056); $zpipe; } + cyl { point (2.525 1.125 0.056); $zpipe; } + cyl { point (2.525 1.375 0.056); $zpipe; } + cyl { point (2.525 1.625 0.056); $zpipe; } + cyl { point (2.525 1.875 0.056); $zpipe; } + cyl { point (2.525 2.125 0.056); $zpipe; } + cyl { point (2.525 2.375 0.056); $zpipe; } + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/obstaclesDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/obstaclesDict new file mode 100644 index 0000000000000000000000000000000000000000..d754d0dc2a2d917d159c23a3a4df92978309ba8e --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/geometry/obstaclesDict @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object obstaclesDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scale 1.0; + +verbose 0; + +#include "groups/group01" +#include "groups/group11" +#include "groups/group14" +#include "groups/group15" +#include "groups/group17" +#include "groups/group21" +#include "groups/group31" +#include "groups/group41" + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/PDRblockMeshDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/PDRblockMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..16ddb4db71a7c8488c37b1992da0be6cff1361a9 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/PDRblockMeshDict @@ -0,0 +1,77 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object PDRblockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scale 1.0; + +x +{ + points ( -11.87 0.03 1.03 2.03 3.05 15.32 ); + nCells ( 14 5 5 5 14 ); + ratios ( 0.0887187064230887 1 1 1.04060401 10.6993205379072 ); +} + +y +{ + points ( -11.64 0.04 1.03 2.03 3.05 15.31 ); + nCells ( 14 5 5 5 14 ); + ratios ( 0.0887187064230887 1 1 1.04060401 10.6993205379072 ); +} + +z +{ + points ( 0 1.02 2.05 14.19 ); + nCells ( 5 5 14 ); + ratios ( 1 1 10.6993205379072 ); +} + +// Or could use defaultFaces = outer instead +defaultPatch +{ + name defaultFaces; + type wall; +} + +// Faces: 0 = xmin, 1 = xmax, 2 = ymin, 3 = ymax, 4 = zmin, 5 = zmax + +boundary +( + // Or with defaultFaces = outer + outer + { + type patch; + faces ( 0 1 2 3 5 ); + } + + mergingFaces + { + type wall; + faces (); + } + + blockedFaces + { + type wall; + faces (); + } + + wallFaces + { + type wall; + faces ( 4 ); + } +); + +//***************************************************************************// diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/PDRsetFieldsDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/PDRsetFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..b7b56e52d492a000f72c04ca1e50aa619a7ab420 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/PDRsetFieldsDict @@ -0,0 +1,38 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object PDRsetFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Data dictionary for PDRsetFields + +// Replace by the relevant names + +obsFileDir "<case>/geometry"; + +obsFileNames (obstaclesDict); + +// legacyObsSpec true; +// +// obsFileNames (position.obs base.obs); + +// Some parameters for PDRfitMesh are read from this file, including + +cellWidth 0.22; + +outer (20 0); + +outerCombFac 0; + +sea_ground 0.0; + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/controlDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/controlDict new file mode 100644 index 0000000000000000000000000000000000000000..15bb4b8c04d36097a1dd4f8ae8bf1e87cf4ee97e --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/controlDict @@ -0,0 +1,58 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application PDRFoam; + +startFrom latestTime; + +startTime 0; + +stopAt endTime; + +endTime 0.3; + +deltaT 5e-06; + +writeControl runTime; + +writeInterval 0.01; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 8; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep yes; + +maxCo 0.3; + +maxDeltaT 1; + +functions +{ + #include "probes" +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/createPatchDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/createPatchDict new file mode 100644 index 0000000000000000000000000000000000000000..3ef842fce868b315d08e4bdf93f81d9c5eb4ce84 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/createPatchDict @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object createPatchDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +pointSync false; + +// Patches to create +patches +( + { + //- Master side patch + name inner_outer; + patchInfo + { + type cyclicAMI; + matchTolerance 0.0001; + neighbourPatch AMI2; + transform noOrdering; + } + constructFrom patches; + patches (inner_outer); + } + + { + //- Slave side patch + name outer_inner; + patchInfo + { + type cyclicAMI; + matchTolerance 0.0001; + neighbourPatch AMI1; + transform noOrdering; + } + constructFrom patches; + patches (outer_inner); + } +); + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/decomposeParDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/decomposeParDict new file mode 100644 index 0000000000000000000000000000000000000000..5042fea2a26fd51ce112976f04bef76d2352f9c8 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/decomposeParDict @@ -0,0 +1,26 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decompositionDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +numberOfSubdomains 4; + +method simple; + +coeffs +{ + n (2 2 1); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/fvSchemes b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/fvSchemes new file mode 100644 index 0000000000000000000000000000000000000000..2d812d9e2271e691cc1845233b65d7c235f2e39c --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/fvSchemes @@ -0,0 +1,111 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(p) Gauss linear; + grad(b) Gauss pointLinear; +} + +divSchemes +{ + default none; + + div(phi,U) Gauss limitedLinearV 1; + div(phiU,p) Gauss limitedLinear 1; + div(phid,p) Gauss limitedLinear 1; + div(phi,k) Gauss limitedLinear 1; + div(phi,epsilon) Gauss limitedLinear 1; + + div(phiXi,Xi) Gauss limitedLinear 1; + div(phiXi,Xp) Gauss limitedLinear 1; + + div(phi,Ep) Gauss limitedLinear 1; + div(phi,Xp) Gauss limitedLinear 1; + + div(phiXi,GRxp) Gauss limitedLinear 1; + div(phiXi,GRep) Gauss limitedLinear 1; + div(phiXi,Ep) Gauss limitedLinear 1; + div(phiSt,b) Gauss limitedLinear 1; + + div(phi,K) Gauss limitedLinear 1; + + div(phi,ft_b_ha_hau_H2OPS_Y) Gauss multivariateSelection + { + ft limitedLinear01 1; + b limitedLinear01 1; + Xi limitedLinear 1; + Xp limitedLinear 1; + Ep limitedLinear 1; + h limitedLinear 1; + hu limitedLinear 1; + ha limitedLinear 1; + hau limitedLinear 1; + H2OPS limitedLinear 1; + water limitedLinear 1; + Y limitedLinear 1; + AIR limitedLinear 1; + } + + div(phi,ft_b_h_hu) Gauss multivariateSelection + { + ft limitedLinear01 1; + b limitedLinear01 1; + Xi limitedLinear 1; + Xp limitedLinear 1; + Ep limitedLinear 1; + h limitedLinear 1; + hu limitedLinear 1; + ha limitedLinear 1; + hau limitedLinear 1; + } + + div((Su*grad(b))) Gauss linear; + div((U+((Su*Xi)*grad(b)))) Gauss linear; + div((muEff*dev2(T(grad(U))))) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; + + div(Ud) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear uncorrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default uncorrected; +} + +fluxRequired +{ + default no; + p; +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/fvSolution b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/fvSolution new file mode 100644 index 0000000000000000000000000000000000000000..7d0e81d6a1d5c16b6ad4826a98aca0b15b2b941c --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/fvSolution @@ -0,0 +1,161 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + rho + { + solver PCG; + preconditioner DIC; + tolerance 1e-09; + relTol 0.0; + } + + rhoFinal + { + $rho; + } + + p + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-9; + relTol 0.01; + } + + pFinal + { + $p; + relTol 0; + } + + /* + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-09; + relTol 0.01; + } + + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)Final" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-09; + relTol 0; + } +*/ + "(b|Xi|Xp|Ep|GRxp|GRep|ft|h|hu|ha|hau|k|epsilon)" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-09; + relTol 0.05; + } + "(b|Xi|Xp|Ep|GRxp|GRep|ft|h|hu|ha|hau|k|epsilon)Final" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-09; + relTol 0.0; + } +} + +PIMPLE +{ + nCorrectors 1; + nOuterCorrectors 10; + nNonOrthogonalCorrectors 3; + momentumPredictor true; + transonic true; + + residualControl + { + b + { + tolerance 1e-5; + relTol 0; + } + p + { + tolerance 1e-5; + relTol 0; + } + Xi + { + tolerance 1e-5; + relTol 0; + } + Xp + { + tolerance 1e-5; + relTol 0; + } + Ep + { + tolerance 1e-5; + relTol 0; + } + ft + { + tolerance 1e-5; + relTol 0; + } + h + { + tolerance 1e-5; + relTol 0; + } + hu + { + tolerance 1e-5; + relTol 0; + } + k + { + tolerance 1e-5; + relTol 0; + } + epsilon + { + tolerance 1e-5; + relTol 0; + } + U + { + tolerance 1e-5; + relTol 0; + } + } +} + +relaxationFactors +{ + fields + { + } + equations + { + U 0.9; + UFinal 1.0; + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)" 0.9; + "(b|Xi|Xp|Ep|GRxp|GRep|ft|ha|hau|k|epsilon|H2OPS)Final" 1.0; + } +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/mapFieldsDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/mapFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..a0f9e8e516deb4036e637faccc4c7db42b6348f7 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/mapFieldsDict @@ -0,0 +1,21 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object mapFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +patchMap ( ); + +cuttingPatches ( ); + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/probes b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/probes new file mode 100644 index 0000000000000000000000000000000000000000..20eeefe3783c5432715e47f784d560fb2165210f --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/probes @@ -0,0 +1,71 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object probes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +probes +{ + name probes; + type probes; + + libs ("libsampling.so"); + + writeControl timeStep; + writeInterval 1; + + probeLocations + ( + (1.5125 1.5125 0.5) + (1.6000 1.5125 0.5) + (1.7000 1.5125 0.5) + (1.8000 1.5125 0.5) + (1.9000 1.5125 0.5) + (2.0000 1.5125 0.5) + (2.1000 1.5125 0.5) + (2.2000 1.5125 0.5) + (2.3000 1.5125 0.5) + (2.4000 1.5125 0.5) + (2.5000 1.5125 0.5) + (2.6000 1.5125 0.5) + (2.7000 1.5125 0.5) + (2.8000 1.5125 0.5) + (2.9000 1.5125 0.5) + (3.0000 1.5125 0.5) + (3.2000 1.5125 0.5) + (3.4000 1.5125 0.5) + (3.6000 1.5125 0.5) + (3.8000 1.5125 0.5) + (4.0000 1.5125 0.5) + (4.3000 1.5125 0.5) + (4.6000 1.5125 0.5) + (5.0000 1.5125 0.5) + ); + + fields + ( + p + b + epsilon + ft + k + rho + St + Su + T + U + Xi + ); +} + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/refineMeshDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/refineMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..5fe7bd44fbe24c72c304ceb40ec1ab564bfae34d --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/refineMeshDict @@ -0,0 +1,64 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object refineMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Cells to refine; name of 'cellSet' +set c0; + +// Type of coordinate system: +// - global : coordinate system same for every cell. Usually aligned with +// x,y,z axis. Specify in globalCoeffs section below. +// - patchLocal : coordinate system different for every cell. Specify in +// patchLocalCoeffs section below. +coordinateSystem global; + +// Specifies 2 directions by a name and a vector. The normal direction is +// calculated as tan1^tan2 +globalCoeffs +{ + tan1 ( 1 0 0 ); + tan2 ( 0 1 0 ); +} + +patchLocalCoeffs +{ + // Normal direction is face normal of zero'th face of patch + patch outside; + tan1 ( 1 0 0 ); + tan2 ( 0 0 1 ); +} + +// Specifies the direction to be refined by the name used above +// To refine in the third direction, use the keyword 'normal' +directions +( + tan1 + tan2 + normal +); + +// Whether to use hex topology. This will +// - if patchLocal: all cells on selected patch should be hex +// - split all hexes in 2x2x2 through the middle of edges. +useHexTopology yes; + +// Cut purely geometric (will cut hexes through vertices) or take +// topology into account. Incompatible with 'useHexTopology' +geometricCut no; + +// Write meshes from intermediate steps +writeMesh no; + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/setFieldsDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/setFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..36595b78cce214eabed27d0374fa87e334448e34 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/setFieldsDict @@ -0,0 +1,38 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +defaultFieldValues +( + volScalarFieldValue p 100000 + volScalarFieldValue T 287 + volScalarFieldValue Tu 287 + volScalarFieldValue ft 0 +); + +regions +( + boxToCell + { + box (0 0 0) (3.0 3.0 2.0); + + fieldValues + ( + volScalarFieldValue ft 0.0659567323835564 + ); + } +); + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/setFieldsDict1 b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/setFieldsDict1 new file mode 100644 index 0000000000000000000000000000000000000000..9f342fbbe59bf86ed6ea82a6b9aa08749380f6f9 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/setFieldsDict1 @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +defaultFieldValues +( +); + +regions +( + boxToCell + { + box (0 0 0) (1 1 1); + + fieldValues + ( + volScalarFieldValue betav 1.0 + volScalarFieldValue Ep 0.0 + volScalarFieldValue Lobs 0.1 + volScalarFieldValue GRep 0.0 + volScalarFieldValue Xi 1.0 + volScalarFieldValue Xp 1.0 + volScalarFieldValue GRxp 0.0 + volScalarFieldValue Aw 0.0 + volScalarFieldValue Nv 0.0 + volSymmTensorFieldValue betai (1 0 0 1 0 1) + volSymmTensorFieldValue Blong (0 0 0 0 0 0) + volSymmTensorFieldValue Bv (0 0 0 0 0 0) + volSymmTensorFieldValue CR (0 0 0 0 0 0) + volSymmTensorFieldValue CT (0 0 0 0 0 0) + volSymmTensorFieldValue nsv (0 0 0 0 0 0) + ); + } +); + +// ************************************************************************* // diff --git a/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/topoSetDict b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/topoSetDict new file mode 100644 index 0000000000000000000000000000000000000000..eb7e519d4f56ebc9ea1c6c4dff9efceec915d9c3 --- /dev/null +++ b/tutorials/preProcessing/PDRsetFields/simplePipeCage/system/topoSetDict @@ -0,0 +1,28 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object topoSetDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +actions +( + { + name c0; + type cellSet; + action new; + source boxToCell; + box (1.505 1.505 0.4845) (1.555 1.555 0.5355); + } +); + +// ************************************************************************* //