1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
28 View factors are calculated based on a face agglomeration array
29 (finalAgglom generated by faceAgglomerate utility).
31 Each view factor between the agglomerated faces i and j (Fij) is calculated
32 using a double integral of the sub-areas composing the agglomaration.
34 The patches involved in the view factor calculation are taken from the Qr
35 volScalarField (radiative flux) when is greyDiffusiveRadiationViewFactor
36 otherwise they are not included.
38 \*---------------------------------------------------------------------------*/
44 #include "volFields.H"
45 #include "surfaceFields.H"
46 #include "distributedTriSurfaceMesh.H"
47 #include "triSurfaceTools.H"
48 #include "mapDistribute.H"
51 #include "meshTools.H"
53 #include "uindirectPrimitivePatch.H"
54 #include "DynamicField.H"
56 #include "unitConversion.H"
58 #include "mathematicalConstants.H"
59 #include "scalarMatrices.H"
60 #include "CompactListList.H"
61 #include "labelIOList.H"
62 #include "labelListIOList.H"
63 #include "scalarListIOList.H"
65 #include "singleCellFvMesh.H"
66 #include "IOdictionary.H"
67 #include "fixedValueFvPatchFields.H"
73 const fileName& fName,
74 const pointField& compactCf,
75 const pointField& myFc,
76 const labelListList& visibleFaceFaces
82 Pout<< "Dumping rays to " << str.name() << endl;
86 const labelList visFaces = visibleFaceFaces[faceI];
87 forAll(visFaces, faceRemote)
89 label compactI = visFaces[faceRemote];
90 const point& remoteFc = compactCf[compactI];
92 meshTools::writeOBJ(str, myFc[faceI]);
94 meshTools::writeOBJ(str, remoteFc);
96 str << "l " << vertI-1 << ' ' << vertI << nl;
99 string cmd("objToVTK " + fName + " " + fName.lessExt() + ".vtk");
100 Pout<< "cmd:" << cmd << endl;
105 scalar calculateViewFactorFij
114 scalar rMag = mag(r);
115 scalar dAiMag = mag(dAi);
116 scalar dAjMag = mag(dAj);
118 vector ni = dAi/dAiMag;
119 vector nj = dAj/dAjMag;
120 scalar cosThetaJ = mag(nj & r)/rMag;
121 scalar cosThetaI = mag(ni & r)/rMag;
125 (cosThetaI*cosThetaJ*dAjMag*dAiMag)
126 /(sqr(rMag)*constant::mathematical::pi)
131 void insertMatrixElements
133 const globalIndex& globalNumbering,
134 const label fromProcI,
135 const labelListList& globalFaceFaces,
136 const scalarListList& viewFactors,
137 scalarSquareMatrix& matrix
140 forAll(viewFactors, faceI)
142 const scalarList& vf = viewFactors[faceI];
143 const labelList& globalFaces = globalFaceFaces[faceI];
145 label globalI = globalNumbering.toGlobal(fromProcI, faceI);
146 forAll(globalFaces, i)
148 matrix[globalI][globalFaces[i]] = vf[i];
154 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
156 int main(int argc, char *argv[])
158 #include "addRegionOption.H"
159 #include "setRootCase.H"
160 #include "createTime.H"
161 #include "createNamedMesh.H"
163 // Read view factor dictionary
164 IOdictionary viewFactorDict
171 IOobject::MUST_READ_IF_MODIFIED,
176 const bool writeViewFactors =
177 viewFactorDict.lookupOrDefault<bool>("writeViewFactorMatrix", false);
179 const bool dumpRays =
180 viewFactorDict.lookupOrDefault<bool>("dumpRays", false);
182 const label debug = viewFactorDict.lookupOrDefault<label>("debug", 0);
197 // Read agglomeration map
198 labelListIOList finalAgglom
203 mesh.facesInstance(),
211 // Create the coarse mesh using agglomeration
212 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216 Info << "\nCreating single cell mesh..." << endl;
219 singleCellFvMesh coarseMesh
234 // Calculate total number of fine and coarse faces
235 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237 label nCoarseFaces = 0; //total number of coarse faces
238 label nFineFaces = 0; //total number of fine faces
240 const polyBoundaryMesh& patches = mesh.boundaryMesh();
241 const polyBoundaryMesh& coarsePatches = coarseMesh.boundaryMesh();
243 labelList viewFactorsPatches(patches.size());
245 const volScalarField::GeometricBoundaryField& Qrb = Qr.boundaryField();
250 const fvPatchScalarField& QrpI = Qrb[patchI];
252 if ((isA<fixedValueFvPatchScalarField>(QrpI)))// && (pp.size() > 0))
254 viewFactorsPatches[count] = QrpI.patch().index();
255 nCoarseFaces += coarsePatches[patchI].size();
256 nFineFaces += patches[patchI].size();
261 viewFactorsPatches.resize(count--);
263 // total number of coarse faces
264 label totalNCoarseFaces = nCoarseFaces;
266 reduce(totalNCoarseFaces, sumOp<label>());
268 if (Pstream::master())
270 Info << "\nTotal number of coarse faces: "<< totalNCoarseFaces << endl;
273 if (Pstream::master() && debug)
275 Pout << "\nView factor patches included in the calculation : "
276 << viewFactorsPatches << endl;
279 // Collect local Cf and Sf on coarse mesh
280 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282 DynamicList<point> localCoarseCf(nCoarseFaces);
283 DynamicList<point> localCoarseSf(nCoarseFaces);
285 forAll (viewFactorsPatches, i)
287 const label patchID = viewFactorsPatches[i];
289 const polyPatch& pp = patches[patchID];
293 const labelList& agglom = finalAgglom[patchID];
294 label nAgglom = max(agglom)+1;
295 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
296 const labelList& coarsePatchFace =
297 coarseMesh.patchFaceMap()[patchID];
299 const pointField& coarseCf =
300 coarseMesh.Cf().boundaryField()[patchID];
302 const pointField& coarseSf =
303 coarseMesh.Sf().boundaryField()[patchID];
305 forAll(coarseCf, faceI)
307 point cf = coarseCf[faceI];
308 const label coarseFaceI = coarsePatchFace[faceI];
309 const labelList& fineFaces = coarseToFine[coarseFaceI];
310 // Construct single face
311 uindirectPrimitivePatch upp
313 UIndirectList<face>(pp, fineFaces),
317 List<point> availablePoints
319 upp.faceCentres().size()
320 + upp.localPoints().size()
326 upp.faceCentres().size()
327 ).assign(upp.faceCentres());
332 upp.localPoints().size(),
333 upp.faceCentres().size()
334 ).assign(upp.localPoints());
338 forAll(availablePoints, iPoint)
340 point cfFine = availablePoints[iPoint];
341 if(mag(cfFine-cfo) < dist)
343 dist = mag(cfFine-cfo);
348 point sf = coarseSf[faceI];
349 localCoarseCf.append(cf);
350 localCoarseSf.append(sf);
355 // Collect remote Cf and Sf on coarse mesh
356 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
358 List<pointField> remoteCoarseCf(Pstream::nProcs());
359 List<pointField> remoteCoarseSf(Pstream::nProcs());
361 remoteCoarseCf[Pstream::myProcNo()] = localCoarseCf;
362 remoteCoarseSf[Pstream::myProcNo()] = localCoarseSf;
364 // Collect remote Cf and Sf on fine mesh
365 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367 List<pointField> remoteFineCf(Pstream::nProcs());
368 List<pointField> remoteFineSf(Pstream::nProcs());
370 remoteCoarseCf[Pstream::myProcNo()] = localCoarseCf;
371 remoteCoarseSf[Pstream::myProcNo()] = localCoarseSf;
373 // Distribute local coarse Cf and Sf for shooting rays
374 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376 Pstream::gatherList(remoteCoarseCf);
377 Pstream::scatterList(remoteCoarseCf);
378 Pstream::gatherList(remoteCoarseSf);
379 Pstream::scatterList(remoteCoarseSf);
382 // Set up searching engine for obstacles
383 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
384 #include "searchingEngine.H"
387 // Determine rays between coarse face centres
388 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
389 DynamicList<label> rayStartFace(nCoarseFaces + 0.01*nCoarseFaces);
391 DynamicList<label> rayEndFace(rayStartFace.size());
393 globalIndex globalNumbering(nCoarseFaces);
396 // Return rayStartFace in local index andrayEndFace in global index
397 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
398 #include "shootRays.H"
400 // Calculate number of visible faces from local index
401 labelList nVisibleFaceFaces(nCoarseFaces, 0);
403 forAll(rayStartFace, i)
405 nVisibleFaceFaces[rayStartFace[i]]++;
408 labelListList visibleFaceFaces(nCoarseFaces);
410 label nViewFactors = 0;
411 forAll(nVisibleFaceFaces, faceI)
413 visibleFaceFaces[faceI].setSize(nVisibleFaceFaces[faceI]);
414 nViewFactors += nVisibleFaceFaces[faceI];
418 // - Construct compact numbering
419 // - return map from remote to compact indices
420 // (per processor (!= myProcNo) a map from remote index to compact index)
421 // - construct distribute map
422 // - renumber rayEndFace into compact addressing
424 List<Map<label> > compactMap(Pstream::nProcs());
426 mapDistribute map(globalNumbering, rayEndFace, compactMap);
428 labelListIOList IOsubMap
433 mesh.facesInstance(),
444 labelListIOList IOconstructMap
449 mesh.facesInstance(),
457 IOconstructMap.write();
460 IOList<label> consMapDim
465 mesh.facesInstance(),
471 List<label>(1, map.constructSize())
475 // visibleFaceFaces has:
476 // (local face, local viewed face) = compact viewed face
477 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
479 nVisibleFaceFaces = 0;
480 forAll(rayStartFace, i)
482 label faceI = rayStartFace[i];
483 label compactI = rayEndFace[i];
484 visibleFaceFaces[faceI][nVisibleFaceFaces[faceI]++] = compactI;
488 // Construct data in compact addressing
489 // I need coarse Sf (Ai), fine Sf (dAi) and fine Cf(r) to calculate Fij
490 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
492 pointField compactCoarseCf(map.constructSize(), pTraits<vector>::zero);
493 pointField compactCoarseSf(map.constructSize(), pTraits<vector>::zero);
494 List<List<point> > compactFineSf(map.constructSize());
495 List<List<point> > compactFineCf(map.constructSize());
497 DynamicList<label> compactPatchId(map.constructSize());
499 // Insert my coarse local values
500 SubList<point>(compactCoarseSf, nCoarseFaces).assign(localCoarseSf);
501 SubList<point>(compactCoarseCf, nCoarseFaces).assign(localCoarseCf);
503 // Insert my fine local values
505 forAll(viewFactorsPatches, i)
507 label patchID = viewFactorsPatches[i];
508 const polyPatch& pp = patches[patchID];
512 const labelList& agglom = finalAgglom[patchID];
513 label nAgglom = max(agglom)+1;
514 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
515 const labelList& coarsePatchFace =
516 coarseMesh.patchFaceMap()[patchID];
518 forAll(coarseToFine, coarseI)
520 compactPatchId.append(patchID);
521 List<point>& fineCf = compactFineCf[compactI];
522 List<point>& fineSf = compactFineSf[compactI++];
524 const label coarseFaceI = coarsePatchFace[coarseI];
525 const labelList& fineFaces = coarseToFine[coarseFaceI];
527 fineCf.setSize(fineFaces.size());
528 fineSf.setSize(fineFaces.size());
530 fineCf = UIndirectList<point>
532 mesh.Cf().boundaryField()[patchID],
533 coarseToFine[coarseFaceI]
535 fineSf = UIndirectList<point>
537 mesh.Sf().boundaryField()[patchID],
538 coarseToFine[coarseFaceI]
545 map.distribute(compactCoarseSf);
546 map.distribute(compactCoarseCf);
547 map.distribute(compactFineCf);
548 map.distribute(compactFineSf);
550 map.distribute(compactPatchId);
553 // Plot all rays between visible faces.
558 runTime.path()/"allVisibleFaces.obj",
560 remoteCoarseCf[Pstream::myProcNo()],
566 // Fill local view factor matrix
567 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
574 mesh.facesInstance(),
583 label totalPatches = coarsePatches.size();
584 reduce(totalPatches, maxOp<label>());
586 // Matrix sum in j(Fij) for each i (if enclosure sum = 1
587 scalarSquareMatrix sumViewFactorPatch
594 scalarList patchArea(totalPatches, 0.0);
596 if (Pstream::master())
598 Info<< "\nCalculating view factors..." << endl;
601 if (mesh.nSolutionD() == 3)
603 forAll (localCoarseSf, coarseFaceI)
605 const List<point>& localFineSf = compactFineSf[coarseFaceI];
606 const vector Ai = sum(localFineSf);
607 const List<point>& localFineCf = compactFineCf[coarseFaceI];
608 const label fromPatchId = compactPatchId[coarseFaceI];
609 patchArea[fromPatchId] += mag(Ai);
611 const labelList& visCoarseFaces = visibleFaceFaces[coarseFaceI];
613 forAll(visCoarseFaces, visCoarseFaceI)
615 F[coarseFaceI].setSize(visCoarseFaces.size());
616 label compactJ = visCoarseFaces[visCoarseFaceI];
617 const List<point>& remoteFineSj = compactFineSf[compactJ];
618 const List<point>& remoteFineCj = compactFineCf[compactJ];
620 const label toPatchId = compactPatchId[compactJ];
623 forAll (localFineSf, i)
625 const vector& dAi = localFineSf[i];
626 const vector& dCi = localFineCf[i];
628 forAll (remoteFineSj, j)
630 const vector& dAj = remoteFineSj[j];
631 const vector& dCj = remoteFineCj[j];
633 scalar dIntFij = calculateViewFactorFij
644 F[coarseFaceI][visCoarseFaceI] = Fij/mag(Ai);
645 sumViewFactorPatch[fromPatchId][toPatchId] += Fij;
649 else if (mesh.nSolutionD() == 2)
651 const boundBox& box = mesh.bounds();
652 const Vector<label>& dirs = mesh.geometricD();
653 vector emptyDir = vector::zero;
662 scalar wideBy2 = (box.span() & emptyDir)*2.0;
664 forAll(localCoarseSf, coarseFaceI)
666 const vector& Ai = localCoarseSf[coarseFaceI];
667 const vector& Ci = localCoarseCf[coarseFaceI];
668 vector Ain = Ai/mag(Ai);
669 vector R1i = Ci + (mag(Ai)/wideBy2)*(Ain ^ emptyDir);
670 vector R2i = Ci - (mag(Ai)/wideBy2)*(Ain ^ emptyDir) ;
672 const label fromPatchId = compactPatchId[coarseFaceI];
673 patchArea[fromPatchId] += mag(Ai);
675 const labelList& visCoarseFaces = visibleFaceFaces[coarseFaceI];
676 forAll (visCoarseFaces, visCoarseFaceI)
678 F[coarseFaceI].setSize(visCoarseFaces.size());
679 label compactJ = visCoarseFaces[visCoarseFaceI];
680 const vector& Aj = compactCoarseSf[compactJ];
681 const vector& Cj = compactCoarseCf[compactJ];
683 const label toPatchId = compactPatchId[compactJ];
685 vector Ajn = Aj/mag(Aj);
686 vector R1j = Cj + (mag(Aj)/wideBy2)*(Ajn ^ emptyDir);
687 vector R2j = Cj - (mag(Aj)/wideBy2)*(Ajn ^ emptyDir);
689 scalar d1 = mag(R1i - R2j);
690 scalar d2 = mag(R2i - R1j);
691 scalar s1 = mag(R1i - R1j);
692 scalar s2 = mag(R2i - R2j);
694 scalar Fij = mag((d1 + d2) - (s1 + s2))/(4.0*mag(Ai)/wideBy2);
696 F[coarseFaceI][visCoarseFaceI] = Fij;
697 sumViewFactorPatch[fromPatchId][toPatchId] += Fij*mag(Ai);
702 if (Pstream::master())
704 Info << "Writing view factor matrix..." << endl;
707 // Write view factors matrix in listlist form
710 reduce(sumViewFactorPatch, sumOp<scalarSquareMatrix>());
711 reduce(patchArea, sumOp<scalarList>());
714 if (Pstream::master() && debug)
716 forAll(viewFactorsPatches, i)
718 label patchI = viewFactorsPatches[i];
719 forAll(viewFactorsPatches, i)
721 label patchJ = viewFactorsPatches[i];
722 Info << "F" << patchI << patchJ << ": "
723 << sumViewFactorPatch[patchI][patchJ]/patchArea[patchI]
730 if (writeViewFactors)
732 volScalarField viewFactorField
737 mesh.time().timeName(),
743 dimensionedScalar("viewFactorField", dimless, 0)
747 forAll(viewFactorsPatches, i)
749 label patchID = viewFactorsPatches[i];
750 const polyPatch& pp = patches[patchID];
754 const labelList& agglom = finalAgglom[patchID];
755 label nAgglom = max(agglom)+1;
756 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
757 const labelList& coarsePatchFace =
758 coarseMesh.patchFaceMap()[patchID];
760 forAll(coarseToFine, coarseI)
762 const scalar Fij = sum(F[compactI]);
763 const label coarseFaceID = coarsePatchFace[coarseI];
764 const labelList& fineFaces = coarseToFine[coarseFaceID];
765 forAll (fineFaces, fineId)
767 const label faceID = fineFaces[fineId];
768 viewFactorField.boundaryField()[patchID][faceID] = Fij;
774 viewFactorField.write();
778 // Invert compactMap (from processor+localface to compact) to go
779 // from compact to processor+localface (expressed as a globalIndex)
780 // globalIndex globalCoarFaceNum(coarseMesh.nFaces());
781 labelList compactToGlobal(map.constructSize());
783 // Local indices first (note: are not in compactMap)
784 for (label i = 0; i < globalNumbering.localSize(); i++)
786 compactToGlobal[i] = globalNumbering.toGlobal(i);
790 forAll(compactMap, procI)
792 const Map<label>& localToCompactMap = compactMap[procI];
794 forAllConstIter(Map<label>, localToCompactMap, iter)
796 compactToGlobal[iter()] = globalNumbering.toGlobal
805 labelListList globalFaceFaces(visibleFaceFaces.size());
807 // Create globalFaceFaces needed to insert view factors
808 // in F to the global matrix Fmatrix
809 forAll(globalFaceFaces, faceI)
811 globalFaceFaces[faceI] = renumber
814 visibleFaceFaces[faceI]
818 labelListIOList IOglobalFaceFaces
823 mesh.facesInstance(),
831 IOglobalFaceFaces.write();
833 Info<< "End\n" << endl;
837 // ************************************************************************* //