viewFactor.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2016-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "viewFactor.H"
30#include "surfaceFields.H"
31#include "constants.H"
33#include "typeInfo.H"
37
38using namespace Foam::constant;
39
40// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41
42namespace Foam
43{
44 namespace radiation
45 {
48 }
49}
50
52 = "viewFactorWall";
53
54// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55
57{
58 const polyBoundaryMesh& coarsePatches = coarseMesh_.boundaryMesh();
59
61
62 for (const label patchi : selectedPatches_)
63 {
64 nLocalCoarseFaces_ += coarsePatches[patchi].size();
65 }
66
67 if (debug)
68 {
69 Pout<< "radiation::viewFactor::initialise() Selected patches:"
71 Pout<< "radiation::viewFactor::initialise() Number of coarse faces:"
73 }
74
77
79 << "Total number of clusters : " << totalNCoarseFaces_ << endl;
80
81 useDirect_ = coeffs_.getOrDefault<bool>("useDirectSolver", true);
82
83 map_.reset
84 (
86 (
88 (
89 "mapDist",
91 mesh_,
94 false
95 )
96 )
97 );
98
99 FmyProc_.reset
100 (
102 (
104 (
105 "F",
107 mesh_,
110 false
111 )
112 )
113 );
114
115 globalFaceFaces_.reset
116 (
118 (
120 (
121 "globalFaceFaces",
123 mesh_,
126 false
127 )
128 )
129 );
130
131
132 globalIndex globalNumbering(nLocalCoarseFaces_);
133
134 // Size coarse qr
136 forAll (qrBandI_, bandI)
137 {
139 }
140
141 if (!useDirect_)
142 {
143 DynamicList<label> dfaceJ;
144
145 // Per processor to owner (local)/neighbour (remote)
147 List<DynamicList<label>> dynProcNeighbour(Pstream::nProcs());
148
149 forAll (globalFaceFaces_(), iFace)
150 {
151 const labelList& visFaces = globalFaceFaces_()[iFace];
152 forAll (visFaces, j)
153 {
154 label gFacej = visFaces[j];
155 label proci = globalNumbering.whichProcID(gFacej);
156 label faceJ = globalNumbering.toLocal(proci, gFacej);
157
158 if (Pstream::myProcNo() == proci)
159 {
160 edge e(iFace, faceJ);
161 if (rays_.insert(e))
162 {
163 dfaceJ.append(j);
164 }
165 }
166 else
167 {
168 label gFaceI =
169 globalNumbering.toGlobal(Pstream::myProcNo(), iFace);
170
171 label proci = globalNumbering.whichProcID(gFacej);
172
173 label facei =
174 globalNumbering.toLocal(Pstream::myProcNo(), gFaceI);
175
176 label remoteFacei = globalNumbering.toLocal(proci, gFacej);
177
178 procOwner[proci].append(facei);
179 dynProcNeighbour[proci].append(remoteFacei);
180 }
181 }
182 }
183
184 mapRayToFmy_.transfer(dfaceJ);
185
186 labelList upper(rays_.size(), -1);
187 labelList lower(rays_.size(), -1);
188
189 const edgeList& raysLst = rays_.sortedToc();
190 label rayI = 0;
191 for (const auto& e : raysLst)
192 {
193 label faceI = e.start();
194 label faceJ = e.end();
195 upper[rayI] = max(faceI, faceJ);
196 lower[rayI] = min(faceI, faceJ);
197 rayI++;
198 }
199
200 labelListList procNeighbour(dynProcNeighbour.size());
201 forAll(procNeighbour, i)
202 {
203 procNeighbour[i] = std::move(dynProcNeighbour[i]);
204 }
205 labelListList mySendCells;
206 Pstream::exchange<labelList, label>(procNeighbour, mySendCells);
207
208 label nbri = 0;
209 forAll(procOwner, proci)
210 {
211 if (procOwner[proci].size())
212 {
213 nbri++;
214 }
215 if (mySendCells[proci].size())
216 {
217 nbri++;
218 }
219 }
220
221 DebugInFunction<< "Number of procBound : " << nbri << endl;
222
224
225 primitiveInterfaces.setSize(nbri);
228
229 nbri = 0;
230
232
233 forAll(procOwner, proci)
234 {
235 if (proci < Pstream::myProcNo() && procOwner[proci].size())
236 {
237 if (debug)
238 {
239 Pout<< "Adding interface " << nbri
240 << " to receive my " << procOwner[proci].size()
241 << " from " << proci << endl;
242 }
243 procToInterface_[proci] = nbri;
244 primitiveInterfaces.set
245 (
246 nbri++,
248 (
249 procOwner[proci],
251 proci,
252 tensorField(0),
254 )
255 );
256 }
257 else if (proci > Pstream::myProcNo() && mySendCells[proci].size())
258 {
259 if (debug)
260 {
261 Pout<< "Adding interface " << nbri
262 << " to send my " << mySendCells[proci].size()
263 << " to " << proci << endl;
264 }
265 primitiveInterfaces.set
266 (
267 nbri++,
269 (
270 mySendCells[proci],
272 proci,
273 tensorField(0),
275 )
276 );
277 }
278 }
279 forAll(procOwner, proci)
280 {
281 if (proci > Pstream::myProcNo() && procOwner[proci].size())
282 {
283 if (debug)
284 {
285 Pout<< "Adding interface " << nbri
286 << " to receive my " << procOwner[proci].size()
287 << " from " << proci << endl;
288 }
289 procToInterface_[proci] = nbri;
290 primitiveInterfaces.set
291 (
292 nbri++,
294 (
295 procOwner[proci],
297 proci,
298 tensorField(0),
300 )
301 );
302 }
303 else if (proci < Pstream::myProcNo() && mySendCells[proci].size())
304 {
305 if (debug)
306 {
307 Pout<< "Adding interface " << nbri
308 << " to send my " << mySendCells[proci].size()
309 << " to " << proci << endl;
310 }
311 primitiveInterfaces.set
312 (
313 nbri++,
315 (
316 mySendCells[proci],
318 proci,
319 tensorField(0),
321 )
322 );
323 }
324 }
325
326 forAll (boundaryCoeffs_, proci)
327 {
329 (
330 proci,
331 new Field<scalar>
332 (
333 primitiveInterfaces[proci].faceCells().size(),
334 Zero
335 )
336 );
337 }
338
339 lduInterfacePtrsList allInterfaces;
340 allInterfaces.setSize(primitiveInterfaces.size());
341
342 forAll(primitiveInterfaces, i)
343 {
344 const lduPrimitiveProcessorInterface& pp = primitiveInterfaces[i];
345
346 allInterfaces.set(i, &pp);
347 }
348
349 const lduSchedule ps
350 (
352 <lduPrimitiveProcessorInterface>(allInterfaces)
353 );
354
355 PtrList<const lduInterface> allInterfacesPtr(allInterfaces.size());
356 forAll (allInterfacesPtr, i)
357 {
358 const lduPrimitiveProcessorInterface& pp = primitiveInterfaces[i];
359
360 allInterfacesPtr.set
361 (
362 i,
364 );
365 }
366
367 lduPtr_.reset
368 (
370 (
371 rays_.size(),
372 lower,
373 upper,
374 allInterfacesPtr,
375 ps,
377 )
378 );
379
380 // Set size for local lduMatrix
381 matrixPtr_.reset(new lduMatrix(lduPtr_()));
382
383 scalarListList& myF = FmyProc_();
384
385 if (coeffs_.get<bool>("smoothing"))
386 {
387 scalar maxDelta = 0;
388 scalar totalDelta = 0;
389 forAll (myF, i)
390 {
391 scalar sumF = 0.0;
392 scalarList& myFij = myF[i];
393 forAll (myFij, j)
394 {
395 sumF += myFij[j];
396 }
397 const scalar delta = sumF - 1.0;
398 forAll (myFij, j)
399 {
400 myFij[j] *= (1.0 - delta/(sumF + 0.001));
401 }
402 totalDelta += delta;
403 if (delta > maxDelta)
404 {
405 maxDelta = delta;
406 }
407 }
408 totalDelta /= myF.size();
409 reduce(totalDelta, sumOp<scalar>());
410 reduce(maxDelta, maxOp<scalar>());
411 Info << "Smoothng average delta : " << totalDelta << endl;
412 Info << "Smoothng maximum delta : " << maxDelta << nl << endl;
413 }
414 }
415
416 if (useDirect_)
417 {
418 List<labelListList> globalFaceFacesProc(Pstream::nProcs());
419 globalFaceFacesProc[Pstream::myProcNo()] = globalFaceFaces_();
420 Pstream::gatherList(globalFaceFacesProc);
421
425
426 if (Pstream::master())
427 {
428 Fmatrix_.reset
429 (
431 );
432
434 << "Insert elements in the matrix..." << endl;
435
436 for (const int procI : Pstream::allProcs())
437 {
439 (
440 globalNumbering,
441 procI,
442 globalFaceFacesProc[procI],
443 F[procI],
444 Fmatrix_()
445 );
446 }
447
448 if (coeffs_.get<bool>("smoothing"))
449 {
450 DebugInFunction << "Smoothing the matrix..." << endl;
451
452 for (label i=0; i<totalNCoarseFaces_; i++)
453 {
454 scalar sumF = 0.0;
455 for (label j=0; j<totalNCoarseFaces_; j++)
456 {
457 sumF += Fmatrix_()(i, j);
458 }
459
460 const scalar delta = sumF - 1.0;
461 for (label j=0; j<totalNCoarseFaces_; j++)
462 {
463 Fmatrix_()(i, j) *= (1.0 - delta/(sumF + 0.001));
464 }
465 }
466 }
467
468 coeffs_.readEntry("constantEmissivity", constEmissivity_);
470 {
471 CLU_.reset
472 (
474 );
475
477 }
478 }
479 }
480
481 coeffs_.readIfPresent("useSolarLoad", useSolarLoad_);
482
483 if (useSolarLoad_)
484 {
485 const dictionary& solarDict = this->subDict("solarLoadCoeffs");
486 solarLoad_.reset(new solarLoad(solarDict, T_));
487
488 if (solarLoad_->nBands() != nBands_)
489 {
491 << "Solar radiation and view factor band numbers "
492 << "are different"
493 << abort(FatalError);
494 }
495
496 Info<< "Creating Solar Load Model " << nl;
497 }
498}
499
500
501// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
502
504:
505 radiationModel(typeName, T),
506 finalAgglom_
507 (
509 (
510 "finalAgglom",
511 mesh_.facesInstance(),
512 mesh_,
513 IOobject::MUST_READ,
514 IOobject::NO_WRITE,
515 false
516 )
517 ),
518 map_(),
519 coarseMesh_
520 (
522 (
523 "coarse:" + mesh_.name(),
524 mesh_.polyMesh::instance(),
525 mesh_.time(),
526 IOobject::NO_READ,
527 IOobject::NO_WRITE,
528 false
529 ),
530 mesh_,
531 finalAgglom_
532 ),
533 qr_
534 (
536 (
537 "qr",
538 mesh_.time().timeName(),
539 mesh_,
540 IOobject::MUST_READ,
541 IOobject::AUTO_WRITE
542 ),
543 mesh_
544 ),
545 Fmatrix_(),
546 CLU_(),
547 selectedPatches_(mesh_.boundary().size(), -1),
548 totalNCoarseFaces_(0),
549 nLocalCoarseFaces_(0),
550 constEmissivity_(false),
551 iterCounter_(0),
552 pivotIndices_(0),
553 useSolarLoad_(false),
554 solarLoad_(),
555 nBands_(coeffs_.getOrDefault<label>("nBands", 1)),
556 FmyProc_()
557{
558 initialise();
559}
560
561
563(
564 const dictionary& dict,
565 const volScalarField& T
566)
567:
568 radiationModel(typeName, dict, T),
569 finalAgglom_
570 (
572 (
573 "finalAgglom",
574 mesh_.facesInstance(),
575 mesh_,
576 IOobject::MUST_READ,
577 IOobject::NO_WRITE,
578 false
579 )
580 ),
581 map_(),
582 coarseMesh_
583 (
585 (
586 "coarse:" + mesh_.name(),
587 mesh_.polyMesh::instance(),
588 mesh_.time(),
589 IOobject::NO_READ,
590 IOobject::NO_WRITE,
591 false
592 ),
593 mesh_,
594 finalAgglom_
595 ),
596 qr_
597 (
599 (
600 "qr",
601 mesh_.time().timeName(),
602 mesh_,
603 IOobject::MUST_READ,
604 IOobject::AUTO_WRITE
605 ),
606 mesh_
607 ),
608 Fmatrix_(),
609 CLU_(),
610 selectedPatches_(mesh_.boundary().size(), -1),
611 totalNCoarseFaces_(0),
612 nLocalCoarseFaces_(0),
613 constEmissivity_(false),
614 iterCounter_(0),
615 pivotIndices_(0),
616 useSolarLoad_(false),
617 solarLoad_(),
618 nBands_(coeffs_.getOrDefault<label>("nBands", 1)),
619 FmyProc_()
620{
621 initialise();
622}
623
624
625// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
626
628{
630 {
631 return true;
632 }
633
634 return false;
635}
636
637
639(
640 const globalIndex& globalNumbering,
641 const label procI,
642 const labelListList& globalFaceFaces,
643 const scalarListList& viewFactors,
644 scalarSquareMatrix& Fmatrix
645)
646{
647 forAll(viewFactors, faceI)
648 {
649 const scalarList& vf = viewFactors[faceI];
650 const labelList& globalFaces = globalFaceFaces[faceI];
651
652 label globalI = globalNumbering.toGlobal(procI, faceI);
653 forAll(globalFaces, i)
654 {
655 Fmatrix[globalI][globalFaces[i]] = vf[i];
656 }
657 }
658}
659
660
662{
663 // Store previous iteration
664 qr_.storePrevIter();
665
666 if (useSolarLoad_)
667 {
668 solarLoad_->calculate();
669 }
670
671 // Global net radiation
672 scalarField qNet(totalNCoarseFaces_, 0.0);
673
674 // Local net radiation
675 scalarField qTotalCoarse(nLocalCoarseFaces_, 0.0);
676
677 // Referen to fvMesh qr field
678 volScalarField::Boundary& qrBf = qr_.boundaryFieldRef();
679
680 globalIndex globalNumbering(nLocalCoarseFaces_);
681
682 const boundaryRadiationProperties& boundaryRadiation =
684
685 for (label bandI = 0; bandI < nBands_; bandI++)
686 {
687 // Global bandI radiation
688 scalarField qBandI(totalNCoarseFaces_, 0.0);
689
690 scalarField compactCoarseT4(map_->constructSize(), 0.0);
691 scalarField compactCoarseE(map_->constructSize(), 0.0);
692 scalarField compactCoarseHo(map_->constructSize(), 0.0);
693
694 // Fill local averaged(T), emissivity(E) and external heatFlux(Ho)
695 DynamicList<scalar> localCoarseT4ave(nLocalCoarseFaces_);
696 DynamicList<scalar> localCoarseEave(nLocalCoarseFaces_);
697 DynamicList<scalar> localCoarseHoave(nLocalCoarseFaces_);
698
699 forAll(selectedPatches_, i)
700 {
701 label patchID = selectedPatches_[i];
702
703 const scalarField& Tp = T_.boundaryField()[patchID];
704 const scalarField& sf = mesh_.magSf().boundaryField()[patchID];
705
706 fvPatchScalarField& qrPatch = qrBf[patchID];
707
709 refCast
710 <
712 >(qrPatch);
713
714 const tmp<scalarField> teb =
715 boundaryRadiation.emissivity(patchID, bandI);
716
717 const scalarField& eb = teb();
718
719 const tmp<scalarField> tHoi = qrp.qro(bandI);
720 const scalarField& Hoi = tHoi();
721
722 const polyPatch& pp = coarseMesh_.boundaryMesh()[patchID];
723
724 const labelList& coarsePatchFace =
725 coarseMesh_.patchFaceMap()[patchID];
726
727 scalarList T4ave(pp.size(), 0.0);
728 scalarList Eave(pp.size(), 0.0);
729 scalarList Hoiave(pp.size(), 0.0);
730
731 if (pp.size() > 0)
732 {
733 const labelList& agglom = finalAgglom_[patchID];
734 label nAgglom = max(agglom) + 1;
735
736 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
737
738 forAll(coarseToFine, coarseI)
739 {
740 const label coarseFaceID = coarsePatchFace[coarseI];
741 const labelList& fineFaces = coarseToFine[coarseFaceID];
743 (
744 sf,
745 fineFaces
746 );
747
748 const scalar area = sum(fineSf());
749
750 // Temperature, emissivity and external flux area weighting
751 forAll(fineFaces, j)
752 {
753 label facei = fineFaces[j];
754 T4ave[coarseI] += (pow4(Tp[facei])*sf[facei])/area;
755 Eave[coarseI] += (eb[facei]*sf[facei])/area;
756 Hoiave[coarseI] += (Hoi[facei]*sf[facei])/area;
757 }
758 }
759 }
760
761 localCoarseT4ave.append(T4ave);
762 localCoarseEave.append(Eave);
763 localCoarseHoave.append(Hoiave);
764
765 }
766
767 // Fill the local values to distribute
768 SubList<scalar>(compactCoarseT4, nLocalCoarseFaces_) =
769 localCoarseT4ave;
770 SubList<scalar>(compactCoarseE, nLocalCoarseFaces_) = localCoarseEave;
771 SubList<scalar>(compactCoarseHo, nLocalCoarseFaces_) =
772 localCoarseHoave;
773
774
775 // Distribute data
776 map_->distribute(compactCoarseT4);
777 map_->distribute(compactCoarseE);
778 map_->distribute(compactCoarseHo);
779
780 // Distribute local global ID
781 labelList compactGlobalIds(map_->constructSize(), Zero);
782
784 (
785 compactGlobalIds,
786 nLocalCoarseFaces_
787 ) = identity
788 (
789 globalNumbering.localSize(),
790 globalNumbering.localStart()
791 );
792
793 map_->distribute(compactGlobalIds);
794
795 if (!useDirect_)
796 {
797 const labelList globalToCompact
798 (
799 invert(totalNCoarseFaces_, compactGlobalIds)
800 );
801
802 scalarField& diag = matrixPtr_->diag(localCoarseEave.size());
803 scalarField& upper = matrixPtr_->upper(rays_.size());
804 scalarField& lower = matrixPtr_->lower(rays_.size());
805
806 scalarField source(nLocalCoarseFaces_, 0);
807
808
809 // Local diag and source
810 forAll(source, i)
811 {
812 const scalar sigmaT4 =
813 physicoChemical::sigma.value()*localCoarseT4ave[i];
814
815 diag[i] = 1/localCoarseEave[i];
816
817 source[i] += -sigmaT4 + localCoarseHoave[i];
818 }
819
820 // Local matrix coefficients
821 if (!constEmissivity_ || iterCounter_ == 0)
822 {
823 const edgeList& raysLst = rays_.sortedToc();
824
825 label rayI = 0;
826 for (const auto& e : raysLst)
827 {
828 label facelJ = e.end();
829 label faceI = e.start();
830
831 label faceJ = mapRayToFmy_[rayI];
832
833 lower[rayI] =
834 (1-1/localCoarseEave[faceI])*FmyProc_()[faceI][faceJ];
835
836 upper[rayI] =
837 (1-1/localCoarseEave[facelJ])*FmyProc_()[faceI][faceJ];
838
839 rayI++;
840 }
841 iterCounter_++;
842 }
843
844 // Extra local contribution to the source and extra matrix coefs
845 // from other procs (boundaryCoeffs)
846 label nInterfaces = lduPtr_().interfaces().size();
847 labelList boundCoeffI(nInterfaces, Zero);
848 forAll (globalFaceFaces_(), iFace)
849 {
850 const labelList& visFaces = globalFaceFaces_()[iFace];
851 forAll (visFaces, jFace)
852 {
853 label gFacej = visFaces[jFace];
854 label proci = globalNumbering.whichProcID(gFacej);
855 if (Pstream::myProcNo() == proci)
856 {
857 label lFacej =
858 globalNumbering.toLocal
859 (
861 gFacej
862 );
863
864 const scalar sigmaT4 =
866 *localCoarseT4ave[lFacej];
867
868 source[iFace] += FmyProc_()[iFace][jFace]*sigmaT4;
869 }
870 else
871 {
872 label compactFaceJ = globalToCompact[gFacej];
873 const scalar sigmaT4 =
875 *compactCoarseT4[compactFaceJ];
876
877 source[iFace] += FmyProc_()[iFace][jFace]*sigmaT4;
878
879 label interfaceI = procToInterface_[proci];
880
881 boundaryCoeffs_
882 [interfaceI][boundCoeffI[interfaceI]++] =
883 -(1-1/compactCoarseE[compactFaceJ])
884 *FmyProc_()[iFace][jFace];
885 }
886 }
887 }
888
889 PtrList<const lduInterfaceField> interfaces(nInterfaces);
890 for(label i = 0; i < interfaces.size(); i++)
891 {
892 interfaces.set
893 (
894 i,
896 (
897 lduPtr_().interfaces()[i],
898 qrBandI_[bandI]
899 )
900 );
901 }
902
903 const dictionary& solverControls =
904 qr_.mesh().solverDict
905 (
906 qr_.select
907 (
908 qr_.mesh().data::template getOrDefault<bool>
909 ("finalIteration", false)
910 )
911 );
912
913 // Solver call
915 (
916 "qr",
917 matrixPtr_(),
918 boundaryCoeffs_,
919 internalCoeffs_,
920 interfaces,
921 solverControls
922 )->solve(qrBandI_[bandI], source);
923
924 solverPerf.print(Info.masterStream(qr_.mesh().comm()));
925
926 qTotalCoarse += qrBandI_[bandI];
927 }
928
929 if (useDirect_)
930 {
931 // Create global size vectors
932 scalarField T4(totalNCoarseFaces_, 0.0);
933 scalarField E(totalNCoarseFaces_, 0.0);
934 scalarField qrExt(totalNCoarseFaces_, 0.0);
935
936 // Fill lists from compact to global indexes.
937 forAll(compactCoarseT4, i)
938 {
939 T4[compactGlobalIds[i]] = compactCoarseT4[i];
940 E[compactGlobalIds[i]] = compactCoarseE[i];
941 qrExt[compactGlobalIds[i]] = compactCoarseHo[i];
942 }
943
947
951
952 if (Pstream::master())
953 {
954 // Variable emissivity
955 if (!constEmissivity_)
956 {
957 scalarSquareMatrix C(totalNCoarseFaces_, 0.0);
958
959 for (label i=0; i<totalNCoarseFaces_; i++)
960 {
961 for (label j=0; j<totalNCoarseFaces_; j++)
962 {
963 const scalar invEj = 1.0/E[j];
964 const scalar sigmaT4 =
966
967 if (i==j)
968 {
969 C(i, j) = invEj;
970 qBandI[i] += -sigmaT4 + qrExt[j];
971 }
972 else
973 {
974 C(i, j) = (1.0 - invEj)*Fmatrix_()(i, j);
975 qBandI[i] += Fmatrix_()(i, j)*sigmaT4;
976 }
977 }
978 }
979
980 Info<< "Solving view factor equations for band :"
981 << bandI << endl;
982
983 // Negative coming into the fluid
984 LUsolve(C, qBandI);
985 }
986 else //Constant emissivity
987 {
988 // Initial iter calculates CLU and caches it
989 if (iterCounter_ == 0)
990 {
991 for (label i=0; i<totalNCoarseFaces_; i++)
992 {
993 for (label j=0; j<totalNCoarseFaces_; j++)
994 {
995 const scalar invEj = 1.0/E[j];
996 if (i==j)
997 {
998 CLU_()(i, j) = invEj;
999 }
1000 else
1001 {
1002 CLU_()(i, j) =
1003 (1.0-invEj)*Fmatrix_()(i, j);
1004 }
1005 }
1006 }
1007
1008 DebugInFunction << "\nDecomposing C matrix..." << endl;
1009
1010 LUDecompose(CLU_(), pivotIndices_);
1011 }
1012
1013 for (label i=0; i<totalNCoarseFaces_; i++)
1014 {
1015 for (label j=0; j<totalNCoarseFaces_; j++)
1016 {
1017 const scalar sigmaT4 =
1019
1020 if (i==j)
1021 {
1022 qBandI[i] += -sigmaT4 + qrExt[j];
1023 }
1024 else
1025 {
1026 qBandI[i] += Fmatrix_()(i, j)*sigmaT4;
1027 }
1028 }
1029 }
1030
1031 Info<< "Solving view factor equations for band : "
1032 << bandI << endl;
1033
1034 LUBacksubstitute(CLU_(), pivotIndices_, qBandI);
1035 iterCounter_ ++;
1036 }
1037 }
1038 // Broadcast qBandI and fill qr
1039 Pstream::broadcast(qBandI);
1040
1041 qNet += qBandI;
1042 }
1043 }
1044
1045 label globCoarseId = 0;
1046 for (const label patchID : selectedPatches_)
1047 {
1048 const polyPatch& pp = coarseMesh_.boundaryMesh()[patchID];
1049
1050 if (pp.size() > 0)
1051 {
1052 scalarField& qrp = qrBf[patchID];
1053 //const scalarField& sf = mesh_.magSf().boundaryField()[patchID];
1054 const labelList& agglom = finalAgglom_[patchID];
1055 label nAgglom = max(agglom)+1;
1056
1057 labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
1058
1059 const labelList& coarsePatchFace =
1060 coarseMesh_.patchFaceMap()[patchID];
1061
1062 //scalar heatFlux = 0.0;
1063 forAll(coarseToFine, coarseI)
1064 {
1065 label globalCoarse = globalNumbering.toGlobal
1066 (
1068 globCoarseId
1069 );
1070
1071 const label coarseFaceID = coarsePatchFace[coarseI];
1072 const labelList& fineFaces = coarseToFine[coarseFaceID];
1073
1074 for (const label facei : fineFaces)
1075 {
1076 if (useDirect_)
1077 {
1078 qrp[facei] = qNet[globalCoarse];
1079 }
1080 else
1081 {
1082 qrp[facei] = qTotalCoarse[globCoarseId];
1083 }
1084 //heatFlux += qrp[facei]*sf[facei];
1085 }
1086 globCoarseId++;
1087 }
1088 }
1089 }
1090
1091 if (debug)
1092 {
1093 forAll(qrBf, patchID)
1094 {
1095 const scalarField& qrp = qrBf[patchID];
1096 const scalarField& magSf = mesh_.magSf().boundaryField()[patchID];
1097 const scalar heatFlux = gSum(qrp*magSf);
1098
1099 Info<< "Total heat transfer rate at patch: "
1100 << patchID << " "
1101 << heatFlux << endl;
1102 }
1103 }
1104
1105 // Relax qr if necessary
1106 qr_.relax();
1107}
1108
1109
1111{
1113 (
1114 IOobject
1115 (
1116 "Rp",
1117 mesh_.time().timeName(),
1118 mesh_,
1121 false
1122 ),
1123 mesh_,
1125 (
1127 )
1128 );
1129}
1130
1131
1134{
1136 (
1137 IOobject
1138 (
1139 "Ru",
1140 mesh_.time().timeName(),
1141 mesh_,
1144 false
1145 ),
1146 mesh_,
1148 );
1149}
1150
1151
1152// ************************************************************************* //
scalar delta
Macros for easy insertion into run-time selection tables.
Graphite solid properties.
Definition: C.H:53
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
Generic templated field type.
Definition: Field.H:82
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:137
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
A List of objects of type <T> with automated input and output.
Definition: IOList.H:58
IOmapDistribute is derived from mapDistribute and IOobject to give the mapDistribute automatic IO fun...
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
void transfer(List< T > &list)
Definition: List.C:447
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
UPstream::rangeType allProcs() const noexcept
Range of ranks indices associated with PstreamBuffers.
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &value, const int tag, const label comm)
Broadcast data: Distribute without modification.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
static void listCombineGather(const List< commsStruct > &comms, List< T > &values, const CombineOp &cop, const int tag, const label comm)
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:151
SolverPerformance is the class returned by the LduMatrix solver containing performance statistics.
void print(Ostream &os) const
Print summary of solver performance to the given stream.
A List obtained as a section of another List.
Definition: SubList.H:70
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
A List with indirect addressing. Like IndirectList but does not store addressing.
Definition: IndirectList.H:79
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:350
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:556
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:293
const T * set(const label i) const
Definition: UPtrList.H:248
void setSize(const label n)
Alias for resize()
Definition: UPtrList.H:261
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
const Type & value() const
Return const reference to value.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:66
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:59
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
label localSize() const
My local size.
Definition: globalIndexI.H:207
label localStart() const
My local start.
Definition: globalIndexI.H:195
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:260
label toLocal(const label i) const
From global to local on current processor.
Definition: globalIndexI.H:325
A lduProcessorField type bypassing coupledFvPatchField and holding a reference to the Field<Type>.
lduMatrix is a general matrix class in which the coefficients are stored as three arrays,...
Definition: lduMatrix.H:84
Simplest concrete lduMesh that stores the addressing needed by lduMatrix.
static lduSchedule nonBlockingSchedule(const lduInterfacePtrsList &)
Get non-scheduled send/receive schedule.
Concrete implementation of processor interface. Used to temporarily store settings.
OSstream & masterStream(const label communicator)
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
labelList indices(const wordRe &matcher, const bool useGroups=true) const
Return (sorted) patch indices for all matches.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
const fileName & facesInstance() const
Return the current instance directory for faces.
Definition: polyMesh.C:866
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:315
int myProcNo() const noexcept
Return processor number.
tmp< scalarField > emissivity(const label patchI, const label bandI=0, vectorField *incomingDirection=nullptr, scalarField *T=nullptr) const
Access boundary emissivity on patch.
This boundary condition provides a grey-diffuse condition for radiative heat flux,...
tmp< scalarField > qro(label bandI=0) const
Return external + solar load radiative heat flux.
Top level model for radiation modelling.
const fvMesh & mesh_
Reference to the mesh database.
virtual bool read()=0
Read radiationProperties dictionary.
dictionary coeffs_
Radiation model dictionary.
const volScalarField & T_
Reference to the temperature field.
The solarLoad radiation model includes Sun primary hits, their reflective fluxes and diffusive sky ra...
Definition: solarLoad.H:165
View factor radiation model. The system solved is: C q = b where: Cij = deltaij/Ej - (1/Ej - 1)Fij q ...
Definition: viewFactor.H:80
void initialise()
Initialise.
Definition: viewFactor.C:56
autoPtr< scalarSquareMatrix > Fmatrix_
View factor matrix.
Definition: viewFactor.H:118
autoPtr< lduMatrix > matrixPtr_
Matrix formed from view factors.
Definition: viewFactor.H:157
virtual tmp< volScalarField::Internal > Ru() const
Source term component (constant)
Definition: viewFactor.C:1133
singleCellFvMesh coarseMesh_
Coarse mesh.
Definition: viewFactor.H:109
autoPtr< scalarSquareMatrix > CLU_
Inverse of C matrix.
Definition: viewFactor.H:121
label nLocalCoarseFaces_
Total local coarse faces.
Definition: viewFactor.H:133
static const word viewFactorWalls
Static name for view factor walls.
Definition: viewFactor.H:97
label nBands_
Number of bands.
Definition: viewFactor.H:151
virtual tmp< volScalarField > Rp() const
Source term component (for power of T^4)
Definition: viewFactor.C:1110
autoPtr< solarLoad > solarLoad_
Solar load radiation model.
Definition: viewFactor.H:148
autoPtr< scalarListIOList > FmyProc_
Local view factors.
Definition: viewFactor.H:174
autoPtr< IOmapDistribute > map_
Map distributed.
Definition: viewFactor.H:106
FieldField< Field, scalar > boundaryCoeffs_
Definition: viewFactor.H:165
labelList procToInterface_
Map from proc to interafce.
Definition: viewFactor.H:177
List< label > mapRayToFmy_
Map local-ray to j-column for F.
Definition: viewFactor.H:171
FieldField< Field, scalar > internalCoeffs_
Definition: viewFactor.H:161
labelList pivotIndices_
Pivot Indices for LU decomposition.
Definition: viewFactor.H:142
bool useDirect_
Use direct or iterative solver.
Definition: viewFactor.H:180
autoPtr< labelListIOList > globalFaceFaces_
Visible global faces.
Definition: viewFactor.H:124
List< scalarField > qrBandI_
Coarse radiative heat flux.
Definition: viewFactor.H:115
label totalNCoarseFaces_
Total global coarse faces.
Definition: viewFactor.H:130
edgeHashSet rays_
Rays on local proc.
Definition: viewFactor.H:168
bool constEmissivity_
Constant emissivity.
Definition: viewFactor.H:136
autoPtr< lduPrimitiveMesh > lduPtr_
Primitive addressing for lduMatrix.
Definition: viewFactor.H:154
labelList selectedPatches_
Selected patches.
Definition: viewFactor.H:127
bool useSolarLoad_
Use Solar Load model.
Definition: viewFactor.H:145
void insertMatrixElements(const globalIndex &index, const label fromProci, const labelListList &globalFaceFaces, const scalarListList &viewFactors, scalarSquareMatrix &matrix)
Insert view factors into main matrix.
Definition: viewFactor.C:639
bool read()
Read radiation properties dictionary.
Definition: viewFactor.C:627
void calculate()
Solve system of equation(s)
Definition: viewFactor.C:661
splitCell * master() const
Definition: splitCell.H:113
A class for managing temporary objects.
Definition: tmp.H:65
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
const volScalarField & T
faceListList boundary
autoPtr< radiation::radiationModel > radiation(radiation::radiationModel::New(T))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
word timeName
Definition: getTimeIndex.H:3
#define DebugInFunction
Report an information message using Foam::Info.
volVectorField F(fluid.F())
const dimensionedScalar sigma
Stefan-Boltzmann constant: default SI units: [W/m2/K4].
Different types of constants.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Type gSum(const FieldField< Field, Type > &f)
To & refCast(From &r)
Reference type cast template function.
Definition: typeInfo.H:131
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
dimensionedScalar pow3(const dimensionedScalar &ds)
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:53
void LUBacksubstitute(const scalarSquareMatrix &luMmatrix, const labelList &pivotIndices, List< Type > &source)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
void LUDecompose(scalarSquareMatrix &matrix, labelList &pivotIndices)
LU decompose the matrix with pivoting.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
const dimensionSet dimTemperature(0, 0, 0, 1, 0, 0, 0)
Definition: dimensionSets.H:54
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
dimensionedScalar pow4(const dimensionedScalar &ds)
errorManip< error > abort(error &err)
Definition: errorManip.H:144
SquareMatrix< scalar > scalarSquareMatrix
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
error FatalError
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition: ListOps.C:36
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
void LUsolve(scalarSquareMatrix &matrix, List< Type > &source)
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:114
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:51
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define addToRadiationRunTimeSelectionTables(model)
dictionary dict
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Foam::surfaceFields.