1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011-2011 OpenCFD Ltd.
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 polyPatch& pp = patches[patchI];
251 const fvPatchScalarField& QrpI = Qrb[patchI];
253 if ((isA<fixedValueFvPatchScalarField>(QrpI)) && (pp.size() > 0))
255 viewFactorsPatches[count] = QrpI.patch().index();
256 nCoarseFaces += coarsePatches[patchI].size();
257 nFineFaces += patches[patchI].size();
262 viewFactorsPatches.resize(count--);
264 // total number of coarse faces
265 label totalNCoarseFaces = nCoarseFaces;
267 reduce(totalNCoarseFaces, sumOp<label>());
269 if (Pstream::master())
271 Info << "\nTotal number of coarse faces: "<< totalNCoarseFaces << endl;
274 if (Pstream::master() && debug)
276 Pout << "\nView factor patches included in the calculation : "
277 << viewFactorsPatches << endl;
280 // Collect local Cf and Sf on coarse mesh
281 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
283 DynamicList<point> localCoarseCf(nCoarseFaces);
284 DynamicList<point> localCoarseSf(nCoarseFaces);
286 forAll (viewFactorsPatches, i)
288 const label patchID = viewFactorsPatches[i];
290 const polyPatch& pp = patches[patchID];
291 const labelList& agglom = finalAgglom[patchID];
292 label nAgglom = max(agglom)+1;
293 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
294 const labelList& coarsePatchFace = coarseMesh.patchFaceMap()[patchID];
296 const pointField& coarseCf = coarseMesh.Cf().boundaryField()[patchID];
297 const pointField& coarseSf = coarseMesh.Sf().boundaryField()[patchID];
299 forAll(coarseCf, faceI)
301 point cf = coarseCf[faceI];
302 const label coarseFaceI = coarsePatchFace[faceI];
303 const labelList& fineFaces = coarseToFine[coarseFaceI];
304 // Construct single face
305 uindirectPrimitivePatch upp
307 UIndirectList<face>(pp, fineFaces),
311 List<point> availablePoints
313 upp.faceCentres().size()
314 + upp.localPoints().size()
320 upp.faceCentres().size()
321 ).assign(upp.faceCentres());
326 upp.localPoints().size(),
327 upp.faceCentres().size()
328 ).assign(upp.localPoints());
332 forAll(availablePoints, iPoint)
334 point cfFine = availablePoints[iPoint];
335 if(mag(cfFine-cfo) < dist)
337 dist = mag(cfFine-cfo);
342 point sf = coarseSf[faceI];
343 localCoarseCf.append(cf);
344 localCoarseSf.append(sf);
348 // Collect remote Cf and Sf on coarse mesh
349 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
351 List<pointField> remoteCoarseCf(Pstream::nProcs());
352 List<pointField> remoteCoarseSf(Pstream::nProcs());
354 remoteCoarseCf[Pstream::myProcNo()] = localCoarseCf;
355 remoteCoarseSf[Pstream::myProcNo()] = localCoarseSf;
357 // Collect remote Cf and Sf on fine mesh
358 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
360 List<pointField> remoteFineCf(Pstream::nProcs());
361 List<pointField> remoteFineSf(Pstream::nProcs());
363 remoteCoarseCf[Pstream::myProcNo()] = localCoarseCf;
364 remoteCoarseSf[Pstream::myProcNo()] = localCoarseSf;
366 // Distribute local coarse Cf and Sf for shooting rays
367 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
369 Pstream::gatherList(remoteCoarseCf);
370 Pstream::scatterList(remoteCoarseCf);
371 Pstream::gatherList(remoteCoarseSf);
372 Pstream::scatterList(remoteCoarseSf);
375 // Set up searching engine for obstacles
376 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
377 #include "searchingEngine.H"
380 // Determine rays between coarse face centres
381 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
382 DynamicList<label> rayStartFace(nCoarseFaces + 0.01*nCoarseFaces);
384 DynamicList<label> rayEndFace(rayStartFace.size());
386 globalIndex globalNumbering(nCoarseFaces);
389 // Return rayStartFace in local index andrayEndFace in global index
390 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
392 #include "shootRays.H"
394 // Calculate number of visible faces from local index
395 labelList nVisibleFaceFaces(nCoarseFaces, 0);
397 forAll(rayStartFace, i)
399 nVisibleFaceFaces[rayStartFace[i]]++;
402 labelListList visibleFaceFaces(nCoarseFaces);
404 label nViewFactors = 0;
405 forAll(nVisibleFaceFaces, faceI)
407 visibleFaceFaces[faceI].setSize(nVisibleFaceFaces[faceI]);
408 nViewFactors += nVisibleFaceFaces[faceI];
412 // - Construct compact numbering
413 // - return map from remote to compact indices
414 // (per processor (!= myProcNo) a map from remote index to compact index)
415 // - construct distribute map
416 // - renumber rayEndFace into compact addressing
418 List<Map<label> > compactMap(Pstream::nProcs());
420 mapDistribute map(globalNumbering, rayEndFace, compactMap);
422 labelListIOList IOsubMap
427 mesh.facesInstance(),
438 labelListIOList IOconstructMap
443 mesh.facesInstance(),
451 IOconstructMap.write();
454 IOList<label> consMapDim
459 mesh.facesInstance(),
465 List<label>(1, map.constructSize())
470 // visibleFaceFaces has:
471 // (local face, local viewed face) = compact viewed face
472 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
474 nVisibleFaceFaces = 0;
475 forAll(rayStartFace, i)
477 label faceI = rayStartFace[i];
478 label compactI = rayEndFace[i];
479 visibleFaceFaces[faceI][nVisibleFaceFaces[faceI]++] = compactI;
483 // Construct data in compact addressing
484 // I need coarse Sf (Ai), fine Sf (dAi) and fine Cf(r) to calculate Fij
485 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
487 pointField compactCoarseCf(map.constructSize(), pTraits<vector>::zero);
488 pointField compactCoarseSf(map.constructSize(), pTraits<vector>::zero);
489 List<List<point> > compactFineSf(map.constructSize());
490 List<List<point> > compactFineCf(map.constructSize());
492 DynamicList<label> compactPatchId(map.constructSize());
494 // Insert my coarse local values
495 SubList<point>(compactCoarseSf, nCoarseFaces).assign(localCoarseSf);
496 SubList<point>(compactCoarseCf, nCoarseFaces).assign(localCoarseCf);
498 // Insert my fine local values
500 forAll(viewFactorsPatches, i)
502 label patchID = viewFactorsPatches[i];
503 const labelList& agglom = finalAgglom[patchID];
504 label nAgglom = max(agglom)+1;
505 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
506 const labelList& coarsePatchFace = coarseMesh.patchFaceMap()[patchID];
508 forAll(coarseToFine, coarseI)
510 compactPatchId.append(patchID);
511 List<point>& fineCf = compactFineCf[compactI];
512 List<point>& fineSf = compactFineSf[compactI++];
514 const label coarseFaceI = coarsePatchFace[coarseI];
515 const labelList& fineFaces = coarseToFine[coarseFaceI];
517 fineCf.setSize(fineFaces.size());
518 fineSf.setSize(fineFaces.size());
520 fineCf = UIndirectList<point>
522 mesh.Cf().boundaryField()[patchID],
523 coarseToFine[coarseFaceI]
525 fineSf = UIndirectList<point>
527 mesh.Sf().boundaryField()[patchID],
528 coarseToFine[coarseFaceI]
534 map.distribute(compactCoarseSf);
535 map.distribute(compactCoarseCf);
536 map.distribute(compactFineCf);
537 map.distribute(compactFineSf);
539 map.distribute(compactPatchId);
542 // Plot all rays between visible faces.
547 runTime.path()/"allVisibleFaces.obj",
549 remoteCoarseCf[Pstream::myProcNo()],
555 // Fill local view factor matrix
556 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
563 mesh.facesInstance(),
572 label totalPatches = coarsePatches.size();
573 reduce(totalPatches, maxOp<label>());
575 // Matrix sum in j(Fij) for each i (if enclosure sum = 1
576 scalarSquareMatrix sumViewFactorPatch
583 scalarList patchArea(totalPatches, 0.0);
585 if (Pstream::master())
587 Info<< "\nCalculating view factors..." << endl;
590 if (mesh.nSolutionD() == 3)
592 forAll (localCoarseSf, coarseFaceI)
594 const List<point>& localFineSf = compactFineSf[coarseFaceI];
595 const vector Ai = sum(localFineSf);
596 const List<point>& localFineCf = compactFineCf[coarseFaceI];
597 const label fromPatchId = compactPatchId[coarseFaceI];
598 patchArea[fromPatchId] += mag(Ai);
600 const labelList& visCoarseFaces = visibleFaceFaces[coarseFaceI];
602 forAll(visCoarseFaces, visCoarseFaceI)
604 F[coarseFaceI].setSize(visCoarseFaces.size());
605 label compactJ = visCoarseFaces[visCoarseFaceI];
606 const List<point>& remoteFineSj = compactFineSf[compactJ];
607 const List<point>& remoteFineCj = compactFineCf[compactJ];
609 const label toPatchId = compactPatchId[compactJ];
612 forAll (localFineSf, i)
614 const vector& dAi = localFineSf[i];
615 const vector& dCi = localFineCf[i];
617 forAll (remoteFineSj, j)
619 const vector& dAj = remoteFineSj[j];
620 const vector& dCj = remoteFineCj[j];
622 scalar dIntFij = calculateViewFactorFij
633 F[coarseFaceI][visCoarseFaceI] = Fij/mag(Ai);
634 sumViewFactorPatch[fromPatchId][toPatchId] += Fij;
638 else if (mesh.nSolutionD() == 2)
640 const boundBox& box = mesh.bounds();
641 const Vector<label>& dirs = mesh.geometricD();
642 vector emptyDir = vector::zero;
651 scalar wideBy2 = (box.span() & emptyDir)*2.0;
653 forAll(localCoarseSf, coarseFaceI)
655 const vector& Ai = localCoarseSf[coarseFaceI];
656 const vector& Ci = localCoarseCf[coarseFaceI];
657 vector Ain = Ai/mag(Ai);
658 vector R1i = Ci + (mag(Ai)/wideBy2)*(Ain ^ emptyDir);
659 vector R2i = Ci - (mag(Ai)/wideBy2)*(Ain ^ emptyDir) ;
661 const label fromPatchId = compactPatchId[coarseFaceI];
662 patchArea[fromPatchId] += mag(Ai);
664 const labelList& visCoarseFaces = visibleFaceFaces[coarseFaceI];
665 forAll (visCoarseFaces, visCoarseFaceI)
667 F[coarseFaceI].setSize(visCoarseFaces.size());
668 label compactJ = visCoarseFaces[visCoarseFaceI];
669 const vector& Aj = compactCoarseSf[compactJ];
670 const vector& Cj = compactCoarseCf[compactJ];
672 const label toPatchId = compactPatchId[compactJ];
674 vector Ajn = Aj/mag(Aj);
675 vector R1j = Cj + (mag(Aj)/wideBy2)*(Ajn ^ emptyDir);
676 vector R2j = Cj - (mag(Aj)/wideBy2)*(Ajn ^ emptyDir);
678 scalar d1 = mag(R1i - R2j);
679 scalar d2 = mag(R2i - R1j);
680 scalar s1 = mag(R1i - R1j);
681 scalar s2 = mag(R2i - R2j);
683 scalar Fij = mag((d1 + d2) - (s1 + s2))/(4.0*mag(Ai)/wideBy2);
685 F[coarseFaceI][visCoarseFaceI] = Fij;
686 sumViewFactorPatch[fromPatchId][toPatchId] += Fij*mag(Ai);
691 if (Pstream::master())
693 Info << "Writing view factor matrix..." << endl;
696 // Write view factors matrix in listlist form
699 reduce(sumViewFactorPatch, sumOp<scalarSquareMatrix>());
700 reduce(patchArea, sumOp<scalarList>());
703 if (Pstream::master() && debug)
705 forAll(viewFactorsPatches, i)
707 label patchI = viewFactorsPatches[i];
708 forAll(viewFactorsPatches, i)
710 label patchJ = viewFactorsPatches[i];
711 Info << "F" << patchI << patchJ << ": "
712 << sumViewFactorPatch[patchI][patchJ]/patchArea[patchI]
719 if (writeViewFactors)
721 volScalarField viewFactorField
726 mesh.time().timeName(),
732 dimensionedScalar("viewFactorField", dimless, 0)
736 forAll(viewFactorsPatches, i)
738 label patchID = viewFactorsPatches[i];
739 const labelList& agglom = finalAgglom[patchID];
740 label nAgglom = max(agglom)+1;
741 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
742 const labelList& coarsePatchFace =
743 coarseMesh.patchFaceMap()[patchID];
745 forAll(coarseToFine, coarseI)
747 const scalar Fij = sum(F[compactI]);
748 const label coarseFaceID = coarsePatchFace[coarseI];
749 const labelList& fineFaces = coarseToFine[coarseFaceID];
750 forAll (fineFaces, fineId)
752 const label faceID = fineFaces[fineId];
753 viewFactorField.boundaryField()[patchID][faceID] = Fij;
758 viewFactorField.write();
762 // Invert compactMap (from processor+localface to compact) to go
763 // from compact to processor+localface (expressed as a globalIndex)
764 // globalIndex globalCoarFaceNum(coarseMesh.nFaces());
765 labelList compactToGlobal(map.constructSize());
767 // Local indices first (note: are not in compactMap)
768 for (label i = 0; i < globalNumbering.localSize(); i++)
770 compactToGlobal[i] = globalNumbering.toGlobal(i);
774 forAll(compactMap, procI)
776 const Map<label>& localToCompactMap = compactMap[procI];
778 forAllConstIter(Map<label>, localToCompactMap, iter)
780 compactToGlobal[iter()] = globalNumbering.toGlobal
789 if (Pstream::master())
791 scalarSquareMatrix Fmatrix(totalNCoarseFaces, totalNCoarseFaces, 0.0);
793 labelListList globalFaceFaces(visibleFaceFaces.size());
795 // Create globalFaceFaces needed to insert view factors
796 // in F to the global matrix Fmatrix
797 forAll(globalFaceFaces, faceI)
799 globalFaceFaces[faceI] = renumber
802 visibleFaceFaces[faceI]
806 labelListIOList IOglobalFaceFaces
811 mesh.facesInstance(),
819 IOglobalFaceFaces.write();
823 labelListList globalFaceFaces(visibleFaceFaces.size());
824 forAll(globalFaceFaces, faceI)
826 globalFaceFaces[faceI] = renumber
829 visibleFaceFaces[faceI]
833 labelListIOList IOglobalFaceFaces
838 mesh.facesInstance(),
847 IOglobalFaceFaces.write();
850 Info<< "End\n" << endl;
855 // ************************************************************************* //