dynamicOversetFvMeshTemplates.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) 2014-2019 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "volFields.H"
29 #include "fvMatrix.H"
30 #include "cellCellStencilObject.H"
31 #include "oversetFvPatchField.H"
34 #include "processorFvPatch.H"
35 #include "syncTools.H"
36 
37 // * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
38 
39 template<class T>
41 {
42  const cellCellStencil& overlap = Stencil::New(*this);
43  const labelListList& stencil = overlap.cellStencil();
44 
45  if (stencil.size() != nCells())
46  {
47  return;
48  }
49 
50  const mapDistribute& map = overlap.cellInterpolationMap();
51  const List<scalarList>& wghts = overlap.cellInterpolationWeights();
52  const labelList& cellIDs = overlap.interpolationCells();
53  const scalarList& factor = overlap.cellInterpolationWeight();
54 
55  Field<T> work(psi);
56  map.mapDistributeBase::distribute(work, UPstream::msgType()+1);
57 
58  forAll(cellIDs, i)
59  {
60  label celli = cellIDs[i];
61 
62  const scalarList& w = wghts[celli];
63  const labelList& nbrs = stencil[celli];
64  const scalar f = factor[celli];
65 
67  forAll(nbrs, nbrI)
68  {
69  s += w[nbrI]*work[nbrs[nbrI]];
70  }
71  //Pout<< "Interpolated value:" << s << endl;
72  //T oldPsi = psi[celli];
73  psi[celli] = (1.0-f)*psi[celli] + f*s;
74  //Pout<< "psi was:" << oldPsi << " now:" << psi[celli] << endl;
75  }
76 }
77 
78 
79 template<class GeoField>
81 {
84 }
85 
86 
87 template<class GeoField>
89 {
90  auto flds(this->lookupClass<GeoField>());
91  for (auto fldPtr : flds)
92  {
93  const word& name = fldPtr->name();
94  if (!suppressed.found(baseName(name)))
95  {
96  if (debug)
97  {
98  Pout<< "dynamicOversetFvMesh::interpolate: interpolating : "
99  << name << endl;
100  }
101  interpolate(fldPtr->primitiveFieldRef());
102  }
103  else
104  {
105  if (debug)
106  {
107  Pout<< "dynamicOversetFvMesh::interpolate: skipping : " << name
108  << endl;
109  }
110  }
111  }
112 }
113 
114 
115 template<class GeoField, class PatchType>
117 (
118  typename GeoField::Boundary& bfld,
119  const bool typeOnly
120 )
121 {
122  const label nReq = Pstream::nRequests();
123 
124  forAll(bfld, patchi)
125  {
126  if (typeOnly == (isA<PatchType>(bfld[patchi]) != nullptr))
127  {
128  bfld[patchi].initEvaluate(Pstream::defaultCommsType);
129  }
130  }
131 
132  // Block for any outstanding requests
133  if (Pstream::parRun())
134  {
135  Pstream::waitRequests(nReq);
136  }
137 
138  forAll(bfld, patchi)
139  {
140  if (typeOnly == (isA<PatchType>(bfld[patchi]) != nullptr))
141  {
142  bfld[patchi].evaluate(Pstream::defaultCommsType);
143  }
144  }
145 }
146 
147 
148 template<class Type>
150 (
151  const fvMatrix<Type>& m
152 ) const
153 {
154  // Determine normalisation. This is normally the original diagonal plus
155  // remote contributions. This needs to be stabilised for hole cells
156  // which can have a zero diagonal. Assume that if any component has
157  // a non-zero diagonal the cell does not need stabilisation.
158  tmp<scalarField> tnorm(tmp<scalarField>::New(m.diag()));
159  scalarField& norm = tnorm.ref();
160 
161  // Add remote coeffs to duplicate behaviour of fvMatrix::addBoundaryDiag
162  const FieldField<Field, Type>& internalCoeffs = m.internalCoeffs();
163  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
164  {
165  forAll(internalCoeffs, patchi)
166  {
167  const labelUList& fc = lduAddr().patchAddr(patchi);
168  const Field<Type>& intCoeffs = internalCoeffs[patchi];
169  const scalarField cmptCoeffs(intCoeffs.component(cmpt));
170  forAll(fc, i)
171  {
172  norm[fc[i]] += cmptCoeffs[i];
173  }
174  }
175  }
176 
177  // Count number of problematic cells
178  label nZeroDiag = 0;
179  forAll(norm, celli)
180  {
181  const scalar& n = norm[celli];
182  if (magSqr(n) < sqr(SMALL))
183  {
184  //Pout<< "For field " << m.psi().name()
185  // << " have diagonal " << n << " for cell " << celli
186  // << " at:" << cellCentres()[celli] << endl;
187  nZeroDiag++;
188  }
189  }
190 
191  reduce(nZeroDiag, sumOp<label>());
192 
193  if (debug)
194  {
195  Pout<< "For field " << m.psi().name() << " have zero diagonals for "
196  << nZeroDiag << " cells" << endl;
197  }
198 
199  if (nZeroDiag > 0)
200  {
201  // Walk out the norm across hole cells
202 
203  const labelList& own = faceOwner();
204  const labelList& nei = faceNeighbour();
206  const labelUList& types = overlap.cellTypes();
207 
208  label nHoles = 0;
209  scalarField extrapolatedNorm(norm);
210  forAll(types, celli)
211  {
212  if (types[celli] == cellCellStencil::HOLE)
213  {
214  extrapolatedNorm[celli] = -GREAT;
215  nHoles++;
216  }
217  }
218 
219  bitSet isFront(nFaces());
220  for (label facei = 0; facei < nInternalFaces(); facei++)
221  {
222  label ownType = types[own[facei]];
223  label neiType = types[nei[facei]];
224  if
225  (
226  (ownType == cellCellStencil::HOLE)
227  != (neiType == cellCellStencil::HOLE)
228  )
229  {
230  isFront.set(facei);
231  }
232  }
233  labelList nbrTypes;
234  syncTools::swapBoundaryCellList(*this, types, nbrTypes);
235  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
236  {
237  label ownType = types[own[facei]];
238  label neiType = nbrTypes[facei-nInternalFaces()];
239  if
240  (
241  (ownType == cellCellStencil::HOLE)
242  != (neiType == cellCellStencil::HOLE)
243  )
244  {
245  isFront.set(facei);
246  }
247  }
248 
249 
250  while (true)
251  {
252  scalarField nbrNorm;
253  syncTools::swapBoundaryCellList(*this, extrapolatedNorm, nbrNorm);
254 
255  bitSet newIsFront(nFaces());
256  scalarField newNorm(extrapolatedNorm);
257 
258  label nChanged = 0;
259  for (const label facei : isFront)
260  {
261  if (extrapolatedNorm[own[facei]] == -GREAT)
262  {
263  // Average owner cell, add faces to newFront
264  newNorm[own[facei]] = cellAverage
265  (
266  types,
267  nbrTypes,
268  extrapolatedNorm,
269  nbrNorm,
270  own[facei],
271  newIsFront
272  );
273  nChanged++;
274  }
275  if
276  (
277  isInternalFace(facei)
278  && extrapolatedNorm[nei[facei]] == -GREAT
279  )
280  {
281  // Average nei cell, add faces to newFront
282  newNorm[nei[facei]] = cellAverage
283  (
284  types,
285  nbrTypes,
286  extrapolatedNorm,
287  nbrNorm,
288  nei[facei],
289  newIsFront
290  );
291  nChanged++;
292  }
293  }
294 
295  reduce(nChanged, sumOp<label>());
296  if (nChanged == 0)
297  {
298  break;
299  }
300 
301  // Transfer new front
302  extrapolatedNorm.transfer(newNorm);
303  isFront.transfer(newIsFront);
305  }
306 
307 
308  forAll(norm, celli)
309  {
310  scalar& n = norm[celli];
311  if (magSqr(n) < sqr(SMALL))
312  {
313  //Pout<< "For field " << m.psi().name()
314  // << " for cell " << celli
315  // << " at:" << cellCentres()[celli]
316  // << " have norm " << n
317  // << " have extrapolated norm " << extrapolatedNorm[celli]
318  // << endl;
319  // Override the norm
320  n = extrapolatedNorm[celli];
321  }
322  }
323  }
324  return tnorm;
325 }
326 
327 
328 template<class Type>
330 (
331  fvMatrix<Type>& m,
332  const scalarField& normalisation
333 ) const
334 {
337  const labelListList& stencil = overlap.cellStencil();
338  const labelList& cellIDs = overlap.interpolationCells();
339  const scalarList& factor = overlap.cellInterpolationWeight();
340  const labelUList& types = overlap.cellTypes();
341 
342 
343  // Force asymmetric matrix (if it wasn't already)
344  scalarField& lower = m.lower();
345  scalarField& upper = m.upper();
346  Field<Type>& source = m.source();
347  scalarField& diag = m.diag();
348 
349 
350  // Get the addressing. Note that the addressing is now extended with
351  // any interpolation faces.
352  const lduAddressing& addr = lduAddr();
353  const labelUList& upperAddr = addr.upperAddr();
354  const labelUList& lowerAddr = addr.lowerAddr();
355  const labelUList& ownerStartAddr = addr.ownerStartAddr();
356  const labelUList& losortAddr = addr.losortAddr();
357  const lduInterfacePtrsList& interfaces = allInterfaces_;
358 
359  if (!isA<fvMeshPrimitiveLduAddressing>(addr))
360  {
362  << "Problem : addressing is not fvMeshPrimitiveLduAddressing"
363  << exit(FatalError);
364  }
365 
366 
367 
368  // 1. Adapt lduMatrix for additional faces and new ordering
369  upper.setSize(upperAddr.size(), 0.0);
370  inplaceReorder(reverseFaceMap_, upper);
371  lower.setSize(lowerAddr.size(), 0.0);
372  inplaceReorder(reverseFaceMap_, lower);
373 
374 
375  //const label nOldInterfaces = dynamicMotionSolverFvMesh::interfaces().size();
376  const label nOldInterfaces = dynamicFvMesh::interfaces().size();
377 
378 
379  if (interfaces.size() > nOldInterfaces)
380  {
381  // Extend matrix coefficients
382  m.internalCoeffs().setSize(interfaces.size());
383  m.boundaryCoeffs().setSize(interfaces.size());
384 
385  // 1b. Adapt for additional interfaces
386  for
387  (
388  label patchi = nOldInterfaces;
389  patchi < interfaces.size();
390  patchi++
391  )
392  {
393  const labelUList& fc = interfaces[patchi].faceCells();
394  m.internalCoeffs().set(patchi, new Field<Type>(fc.size(), Zero));
395  m.boundaryCoeffs().set(patchi, new Field<Type>(fc.size(), Zero));
396  }
397 
398  // 1c. Adapt field for additional interfaceFields (note: solver uses
399  // GeometricField::scalarInterfaces() to get hold of interfaces)
401 
402  typename GeoField::Boundary& bfld =
403  const_cast<GeoField&>(m.psi()).boundaryFieldRef();
404 
405  bfld.setSize(interfaces.size());
406 
407 
408  // This gets quite interesting: we do not want to add additional
409  // fvPatches (since direct correspondence to polyMesh) so instead
410  // add a reference to an existing processor patch
411  label addPatchi = 0;
412  for (label patchi = 0; patchi < nOldInterfaces; patchi++)
413  {
414  if (isA<processorFvPatch>(bfld[patchi].patch()))
415  {
416  addPatchi = patchi;
417  break;
418  }
419  }
420 
421  for
422  (
423  label patchi = nOldInterfaces;
424  patchi < interfaces.size();
425  patchi++
426  )
427  {
428  bfld.set
429  (
430  patchi,
432  (
433  interfaces[patchi],
434  bfld[addPatchi].patch(), // dummy processorFvPatch
435  m.psi()
436  )
437  );
438  }
439  }
440 
441 
442  // 2. Adapt fvMatrix level: faceFluxCorrectionPtr
443  // Question: do we need to do this?
444  // This seems to be set/used only by the gaussLaplacianScheme and
445  // fvMatrix:correction, both of which are outside the linear solver.
446 
447 
448 
449  // Clear out existing connections on cells to be interpolated
450  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
451  // Note: could avoid doing the zeroing of the new faces since these
452  // are set to zero anyway.
453 
454  forAll(upperAddr, facei)
455  {
456  if (types[upperAddr[facei]] == cellCellStencil::INTERPOLATED)
457  {
458  // Disconnect upper from lower
459  label celli = upperAddr[facei];
460  lower[facei] *= 1.0-factor[celli];
461  }
462  if (types[lowerAddr[facei]] == cellCellStencil::INTERPOLATED)
463  {
464  // Disconnect lower from upper
465  label celli = lowerAddr[facei];
466  upper[facei] *= 1.0-factor[celli];
467  }
468  }
469 
470  for (label patchi = 0; patchi < nOldInterfaces; ++patchi)
471  {
472  const labelUList& fc = addr.patchAddr(patchi);
473  Field<Type>& intCoeffs = m.internalCoeffs()[patchi];
474  Field<Type>& bouCoeffs = m.boundaryCoeffs()[patchi];
475  forAll(fc, i)
476  {
477  label celli = fc[i];
478  {
479  if (types[celli] == cellCellStencil::INTERPOLATED)
480  {
481  scalar f = factor[celli];
482  intCoeffs[i] *= 1.0-f;
483  bouCoeffs[i] *= 1.0-f;
484  }
485  else if (types[celli] == cellCellStencil::HOLE)
486  {
487  intCoeffs[i] = pTraits<Type>::zero;
488  bouCoeffs[i] = pTraits<Type>::zero;
489  }
490  }
491  }
492  }
493 
494 
495 
496  // Modify matrix
497  // ~~~~~~~~~~~~~
498 
499  // Do hole cells. Note: maybe put into interpolationCells() loop above?
500  forAll(types, celli)
501  {
502  if (types[celli] == cellCellStencil::HOLE)
503  {
504  label startLabel = ownerStartAddr[celli];
505  label endLabel = ownerStartAddr[celli + 1];
506 
507  for (label facei = startLabel; facei < endLabel; facei++)
508  {
509  upper[facei] = 0.0;
510  }
511 
512  startLabel = addr.losortStartAddr()[celli];
513  endLabel = addr.losortStartAddr()[celli + 1];
514 
515  for (label i = startLabel; i < endLabel; i++)
516  {
517  label facei = losortAddr[i];
518  lower[facei] = 0.0;
519  }
520 
521  diag[celli] = normalisation[celli];
522  source[celli] = normalisation[celli]*m.psi()[celli];
523  }
524  }
525 
526 
527  //const globalIndex globalNumbering(V().size());
528  //labelList globalCellIDs(overlap.cellInterpolationMap().constructSize());
529  //forAll(V(), cellI)
530  //{
531  // globalCellIDs[cellI] = globalNumbering.toGlobal(cellI);
532  //}
533  //overlap.cellInterpolationMap().distribute(globalCellIDs);
534 
535 
536  forAll(cellIDs, i)
537  {
538  label celli = cellIDs[i];
539 
540  const scalar f = factor[celli];
541  const scalarList& w = wghts[celli];
542  const labelList& nbrs = stencil[celli];
543  const labelList& nbrFaces = stencilFaces_[celli];
544  const labelList& nbrPatches = stencilPatches_[celli];
545 
546  if (types[celli] == cellCellStencil::HOLE)
547  {
548  FatalErrorInFunction << "Found HOLE cell " << celli
549  << " at:" << C()[celli]
550  << " . Should this be in interpolationCells()????"
551  << abort(FatalError);
552  }
553  else
554  {
555  // Create interpolation stencil
556 
557  diag[celli] *= (1.0-f);
558  source[celli] *= (1.0-f);
559 
560  forAll(nbrs, nbri)
561  {
562  label patchi = nbrPatches[nbri];
563  label facei = nbrFaces[nbri];
564 
565  if (patchi == -1)
566  {
567  label nbrCelli = nbrs[nbri];
568 
569  // Add the coefficients
570  const scalar s = normalisation[celli]*f*w[nbri];
571 
572  scalar& u = upper[facei];
573  scalar& l = lower[facei];
574  if (celli < nbrCelli)
575  {
576  diag[celli] += s;
577  u += -s;
578  }
579  else
580  {
581  diag[celli] += s;
582  l += -s;
583  }
584  }
585  else
586  {
587  // Patch face. Store in boundaryCoeffs. Note sign change.
588  //const label globalCelli = globalCellIDs[nbrs[nbri]];
589  //const label proci =
590  // globalNumbering.whichProcID(globalCelli);
591  //const label remoteCelli =
592  // globalNumbering.toLocal(proci, globalCelli);
593  //
594  //Pout<< "for cell:" << celli
595  // << " need weight from remote slot:" << nbrs[nbri]
596  // << " proc:" << proci << " remote cell:" << remoteCelli
597  // << " patch:" << patchi
598  // << " patchFace:" << facei
599  // << " weight:" << w[nbri]
600  // << endl;
601 
602  const scalar s = normalisation[celli]*f*w[nbri];
603  m.boundaryCoeffs()[patchi][facei] += pTraits<Type>::one*s;
604  m.internalCoeffs()[patchi][facei] += pTraits<Type>::one*s;
605 
606  // Note: do NOT add to diagonal - this is in the
607  // internalCoeffs and gets added to the diagonal
608  // inside fvMatrix::solve
609  }
610  }
611 
612  //if (mag(diag[celli]) < SMALL)
613  //{
614  // Pout<< "for cell:" << celli
615  // << " at:" << this->C()[celli]
616  // << " diag:" << diag[celli] << endl;
617  //
618  // forAll(nbrs, nbri)
619  // {
620  // label patchi = nbrPatches[nbri];
621  // label facei = nbrFaces[nbri];
622  //
623  // const label globalCelli = globalCellIDs[nbrs[nbri]];
624  // const label proci =
625  // globalNumbering.whichProcID(globalCelli);
626  // const label remoteCelli =
627  // globalNumbering.toLocal(proci, globalCelli);
628  //
629  // Pout<< " need weight from slot:" << nbrs[nbri]
630  // << " proc:" << proci << " remote cell:"
631  // << remoteCelli
632  // << " patch:" << patchi
633  // << " patchFace:" << facei
634  // << " weight:" << w[nbri]
635  // << endl;
636  // }
637  // Pout<< endl;
638  //}
639  }
640  }
641 }
642 
643 
644 template<class Type>
646 (
647  fvMatrix<Type>& m,
648  const dictionary& dict
649 ) const
650 {
652  // Check we're running with bcs that can handle implicit matrix manipulation
653  typename GeoField::Boundary& bpsi =
654  const_cast<GeoField&>(m.psi()).boundaryFieldRef();
655 
656  bool hasOverset = false;
657  forAll(bpsi, patchi)
658  {
659  if (isA<oversetFvPatchField<Type>>(bpsi[patchi]))
660  {
661  hasOverset = true;
662  break;
663  }
664  }
665 
666  if (!hasOverset)
667  {
668  if (debug)
669  {
670  Pout<< "dynamicOversetFvMesh::solve() :"
671  << " bypassing matrix adjustment for field " << m.psi().name()
672  << endl;
673  }
674  //return dynamicMotionSolverFvMesh::solve(m, dict);
675  return dynamicFvMesh::solve(m, dict);
676  }
677 
678  if (debug)
679  {
680  Pout<< "dynamicOversetFvMesh::solve() :"
681  << " adjusting matrix for interpolation for field "
682  << m.psi().name() << endl;
683  }
684 
685  // Calculate stabilised diagonal as normalisation for interpolation
686  const scalarField norm(normalisation(m));
687 
688  if (debug)
689  {
690  volScalarField scale
691  (
692  IOobject
693  (
694  m.psi().name() + "_normalisation",
695  this->time().timeName(),
696  *this,
699  false
700  ),
701  *this,
703  );
704  scale.ref().field() = norm;
706  <
709  >(scale.boundaryFieldRef(), false);
710  scale.write();
711 
712  if (debug)
713  {
714  Pout<< "dynamicOversetFvMesh::solve() :"
715  << " writing matrix normalisation for field " << m.psi().name()
716  << " to " << scale.name() << endl;
717  }
718  }
719 
720 
721  // Switch to extended addressing (requires mesh::update() having been
722  // called)
723  active(true);
724 
725  // Adapt matrix
726  scalarField oldUpper(m.upper());
727  scalarField oldLower(m.lower());
730  const label oldSize = bpsi.size();
731 
732  addInterpolation(m, norm);
733 
734  // Swap psi values so added patches have patchNeighbourField
735  correctBoundaryConditions<GeoField, calculatedProcessorFvPatchField<Type>>
736  (
737  bpsi,
738  true
739  );
740 
741 
742  // Print a bit
743  //write(Pout, m, lduAddr(), interfaces());
744  //{
745  // const fvSolution& sol = static_cast<const fvSolution&>(*this);
746  // const dictionary& pDict = sol.subDict("solvers").subDict("p");
747  // writeAgglomeration(GAMGAgglomeration::New(m, pDict));
748  //}
749 
750  // Use lower level solver
751  //SolverPerformance<Type> s(dynamicMotionSolverFvMesh::solve(m, dict));
753 
754  // Restore boundary field
755  bpsi.setSize(oldSize);
756 
757  // Restore matrix
758  m.upper().transfer(oldUpper);
759  m.lower().transfer(oldLower);
760  m.internalCoeffs().transfer(oldInt);
761  m.boundaryCoeffs().transfer(oldBou);
762 
763  // Switch to original addressing
764  active(false);
765 
766  return s;
767 }
768 
769 
770 template<class Type>
772 (
773  Ostream& os,
774  const fvMatrix<Type>& m,
775  const lduAddressing& addr,
776  const lduInterfacePtrsList& interfaces
777 ) const
778 {
779  os << "** Matrix **" << endl;
780  const labelUList& upperAddr = addr.upperAddr();
781  const labelUList& lowerAddr = addr.lowerAddr();
782  const labelUList& ownerStartAddr = addr.ownerStartAddr();
783  const labelUList& losortAddr = addr.losortAddr();
784 
785  const scalarField& lower = m.lower();
786  const scalarField& upper = m.upper();
787  const Field<Type>& source = m.source();
788  const scalarField& diag = m.diag();
789 
790 
791  // Invert patch addressing
792  labelListList cellToPatch(addr.size());
793  labelListList cellToPatchFace(addr.size());
794  {
795  forAll(interfaces, patchi)
796  {
797  if (interfaces.set(patchi))
798  {
799  const labelUList& fc = interfaces[patchi].faceCells();
800 
801  forAll(fc, i)
802  {
803  cellToPatch[fc[i]].append(patchi);
804  cellToPatchFace[fc[i]].append(i);
805  }
806  }
807  }
808  }
809 
810  forAll(source, celli)
811  {
812  os << "cell:" << celli << " diag:" << diag[celli]
813  << " source:" << source[celli] << endl;
814 
815  label startLabel = ownerStartAddr[celli];
816  label endLabel = ownerStartAddr[celli + 1];
817 
818  for (label facei = startLabel; facei < endLabel; facei++)
819  {
820  os << " face:" << facei
821  << " nbr:" << upperAddr[facei] << " coeff:" << upper[facei]
822  << endl;
823  }
824 
825  startLabel = addr.losortStartAddr()[celli];
826  endLabel = addr.losortStartAddr()[celli + 1];
827 
828  for (label i = startLabel; i < endLabel; i++)
829  {
830  label facei = losortAddr[i];
831  os << " face:" << facei
832  << " nbr:" << lowerAddr[facei] << " coeff:" << lower[facei]
833  << endl;
834  }
835 
836  forAll(cellToPatch[celli], i)
837  {
838  label patchi = cellToPatch[celli][i];
839  label patchFacei = cellToPatchFace[celli][i];
840 
841  os << " patch:" << patchi
842  << " patchface:" << patchFacei
843  << " intcoeff:" << m.internalCoeffs()[patchi][patchFacei]
844  << " boucoeff:" << m.boundaryCoeffs()[patchi][patchFacei]
845  << endl;
846  }
847  }
848  forAll(m.internalCoeffs(), patchi)
849  {
850  if (m.internalCoeffs().set(patchi))
851  {
852  const labelUList& fc = addr.patchAddr(patchi);
853 
854  os << "patch:" << patchi
855  //<< " type:" << interfaces[patchi].type()
856  << " size:" << fc.size() << endl;
857  if
858  (
859  interfaces.set(patchi)
860  && isA<processorLduInterface>(interfaces[patchi])
861  )
862  {
863  const processorLduInterface& ppp =
864  refCast<const processorLduInterface>(interfaces[patchi]);
865  os << "(processor with my:" << ppp.myProcNo()
866  << " nbr:" << ppp.neighbProcNo()
867  << ")" << endl;
868  }
869 
870  forAll(fc, i)
871  {
872  os << " cell:" << fc[i]
873  << " int:" << m.internalCoeffs()[patchi][i]
874  << " boun:" << m.boundaryCoeffs()[patchi][i]
875  << endl;
876  }
877  }
878  }
879 
880 
881  lduInterfaceFieldPtrsList interfaceFields =
882  m.psi().boundaryField().scalarInterfaces();
883  forAll(interfaceFields, inti)
884  {
885  if (interfaceFields.set(inti))
886  {
887  os << "interface:" << inti
888  << " if type:" << interfaceFields[inti].interface().type()
889  << " fld type:" << interfaceFields[inti].type() << endl;
890  }
891  }
892 
893  os << "** End of Matrix **" << endl;
894 }
895 
896 
897 template<class GeoField>
899 {
900  typename GeoField::Boundary& bfld = fld.boundaryFieldRef();
901 
902  const label nReq = Pstream::nRequests();
903 
904  forAll(bfld, patchi)
905  {
906  if (bfld[patchi].coupled())
907  {
908  //Pout<< "initEval of " << bfld[patchi].patch().name() << endl;
909  bfld[patchi].initEvaluate(Pstream::defaultCommsType);
910  }
911  }
912 
913  // Block for any outstanding requests
914  if (Pstream::parRun())
915  {
916  Pstream::waitRequests(nReq);
917  }
918 
919  forAll(bfld, patchi)
920  {
921  if (bfld[patchi].coupled())
922  {
923  //Pout<< "eval of " << bfld[patchi].patch().name() << endl;
924  bfld[patchi].evaluate(Pstream::defaultCommsType);
925  }
926  }
927 }
928 
929 
930 template<class GeoField>
932 {
933  Pout<< "** starting checking of " << fld.name() << endl;
934 
935  GeoField fldCorr(fld.name()+"_correct", fld);
936  correctCoupledBoundaryConditions(fldCorr);
937 
938  const typename GeoField::Boundary& bfld = fld.boundaryField();
939  const typename GeoField::Boundary& bfldCorr = fldCorr.boundaryField();
940 
941  forAll(bfld, patchi)
942  {
943  const typename GeoField::Patch& pfld = bfld[patchi];
944  const typename GeoField::Patch& pfldCorr = bfldCorr[patchi];
945 
946  Pout<< "Patch:" << pfld.patch().name() << endl;
947 
948  forAll(pfld, i)
949  {
950  if (pfld[i] != pfldCorr[i])
951  {
952  Pout<< " " << i << " orig:" << pfld[i]
953  << " corrected:" << pfldCorr[i] << endl;
954  }
955  }
956  }
957  Pout<< "** end of " << fld.name() << endl;
958 }
959 
960 
961 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::lduAddressing
The class contains the addressing required by the lduMatrix: upper, lower and losort.
Definition: lduAddressing.H:114
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
volFields.H
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::UPtrList::size
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Foam::cellCellStencil::HOLE
Definition: cellCellStencil.H:76
Foam::dynamicOversetFvMesh::correctBoundaryConditions
static void correctBoundaryConditions(typename GeoField::Boundary &bfld, const bool typeOnly)
Correct boundary conditions of certain type (typeOnly = true)
Definition: dynamicOversetFvMeshTemplates.C:117
processorFvPatch.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::FieldField
A field of fields is a PtrList of fields with reference counting.
Definition: FieldField.H:53
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DimensionedField::field
const Field< Type > & field() const
Return field.
Definition: DimensionedFieldI.H:90
Foam::diag
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
Definition: pointPatchFieldFunctions.H:287
Foam::processorLduInterface
An abstract base class for processor coupled interfaces.
Definition: processorLduInterface.H:53
Foam::cellCellStencilObject::cellTypes
virtual const labelUList & cellTypes() const
Return the cell type list.
Definition: cellCellStencilObject.H:121
Foam::MeshObject::New
static const Type & New(const Mesh &mesh, Args &&... args)
Get existing or create a new MeshObject.
Definition: MeshObject.C:48
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::UPstream::waitRequests
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:262
Foam::fvMatrix::boundaryCoeffs
const FieldField< Field, Type > & boundaryCoeffs() const
Definition: fvMatrix.H:471
fvMatrix.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::UPstream::defaultCommsType
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:281
Foam::lduAddressing::losortStartAddr
const labelUList & losortStartAddr() const
Return losort start addressing.
Definition: lduAddressing.C:210
Foam::cellCellStencilObject::cellInterpolationWeight
virtual const scalarList & cellInterpolationWeight() const
Per interpolated cell the interpolation factor. (0 = use.
Definition: cellCellStencilObject.H:153
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::dynamicOversetFvMesh::interpolate
void interpolate(Field< T > &psi) const
Explicit interpolation of acceptor cells from donor cells.
Definition: dynamicOversetFvMeshTemplates.C:40
lduInterfaceFieldPtrsList.H
Foam::HashSet< word, Hash< word > >
Foam::lduAddressing::ownerStartAddr
const labelUList & ownerStartAddr() const
Return owner start addressing.
Definition: lduAddressing.C:199
syncTools.H
Foam::lduAddressing::size
label size() const
Return number of equations.
Definition: lduAddressing.H:171
Foam::lduAddressing::upperAddr
virtual const labelUList & upperAddr() const =0
Return upper addressing.
C
volScalarField & C
Definition: readThermalProperties.H:102
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::lduAddressing::losortAddr
const labelUList & losortAddr() const
Return losort addressing.
Definition: lduAddressing.C:188
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
calculatedProcessorFvPatchField.H
Foam::oversetFvPatchField::write
virtual void write(Ostream &os) const
Write.
Definition: oversetFvPatchField.C:222
correctBoundaryConditions
cellMask correctBoundaryConditions()
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::fvMesh::solve
virtual SolverPerformance< scalar > solve(fvMatrix< scalar > &, const dictionary &) const
Definition: fvMesh.C:550
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::syncTools::syncFaceList
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:396
Foam::primitiveMesh::nCells
label nCells() const noexcept
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:227
Foam::stringOps::lower
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1184
Foam::interpolate
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition: curveTools.C:75
Foam::Field< T >
Foam::fvMesh::interfaces
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition: fvMesh.C:708
Foam::OSstream::name
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
Foam::cellCellStencil::INTERPOLATED
Definition: cellCellStencil.H:75
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
Foam::T
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Definition: FieldFieldFunctions.C:58
Foam::dynamicOversetFvMesh::addInterpolation
void addInterpolation(fvMatrix< Type > &, const scalarField &norm) const
Add interpolation to matrix (coefficients)
Definition: dynamicOversetFvMeshTemplates.C:330
Foam::UPtrList< const lduInterface >
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:42
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::processorLduInterface::neighbProcNo
virtual int neighbProcNo() const =0
Return neighbour processor number (rank in communicator)
Foam::syncTools::swapBoundaryCellList
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
Definition: syncToolsTemplates.C:1392
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::fvMatrix::psi
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
Definition: fvMatrix.H:399
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
Foam::dynamicOversetFvMesh::correctCoupledBoundaryConditions
static void correctCoupledBoundaryConditions(GeoField &fld)
Debug: correct coupled bc.
Definition: dynamicOversetFvMeshTemplates.C:898
oversetFvPatchField.H
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::Field::component
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:539
Foam::maxEqOp
Definition: ops.H:80
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::GeometricField::primitiveFieldRef
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field.
Definition: GeometricField.C:766
Foam::GeometricField::correctBoundaryConditions
void correctBoundaryConditions()
Correct boundary field.
Definition: GeometricField.C:940
Foam::calculatedProcessorFvPatchField
A processorFvPatchField type bypassing fvPatch.
Definition: calculatedProcessorFvPatchField.H:63
Foam::isA
const TargetType * isA(const Type &t)
Check if dynamic_cast to TargetType is possible.
Definition: typeInfo.H:197
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::processorLduInterface::myProcNo
virtual int myProcNo() const =0
Return processor number (rank in communicator)
Foam::UPtrList::set
const T * set(const label i) const
Definition: UPtrList.H:176
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::cellCellStencilObject::cellStencil
virtual const labelListList & cellStencil() const
Per interpolated cell the neighbour cells (in terms of slots as.
Definition: cellCellStencilObject.H:140
Foam::UPstream::msgType
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:540
Foam::UPstream::nRequests
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:252
f
labelList f(nPoints)
Foam::cellCellStencil
Calculation of interpolation stencils.
Definition: cellCellStencil.H:61
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::GeometricField::ref
Internal & ref(const bool updateAccessTime=true)
Return a reference to the dimensioned internal field.
Definition: GeometricField.C:749
Foam::dynamicOversetFvMesh::checkCoupledBC
static void checkCoupledBC(const GeoField &fld)
Debug: check halo swap is ok.
Definition: dynamicOversetFvMeshTemplates.C:931
Foam::lduAddressing::lowerAddr
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
Foam::dynamicOversetFvMesh::normalisation
tmp< scalarField > normalisation(const fvMatrix< Type > &m) const
Freeze values at holes.
Foam::UPstream::parRun
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Foam::List< labelList >
Foam::pTraits
A traits class, which is primarily used for primitives.
Definition: pTraits.H:56
Foam::cellCellStencilObject::cellInterpolationWeights
virtual const List< scalarList > & cellInterpolationWeights() const
Weights for cellStencil.
Definition: cellCellStencilObject.H:146
Foam::fvMatrix::source
Field< Type > & source()
Definition: fvMatrix.H:445
Foam::UList< label >
Foam::dynamicOversetFvMesh::write
void write(Ostream &, const fvMatrix< Type > &, const lduAddressing &, const lduInterfacePtrsList &) const
Debug: print matrix.
Definition: dynamicOversetFvMeshTemplates.C:772
Foam::direction
uint8_t direction
Definition: direction.H:52
Foam::fvMatrix
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvPatchField.H:68
Foam::dynamicOversetFvMesh::solve
SolverPerformance< Type > solve(fvMatrix< Type > &, const dictionary &) const
Solve given dictionary with settings.
Foam::lduAddressing::patchAddr
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
Foam::oversetFvPatchField
Boundary condition for use on overset patches. To be run in combination with special dynamicFvMesh ty...
Definition: oversetFvPatchField.H:56
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
overlap
const cellCellStencilObject & overlap
Definition: correctPhi.H:57
Foam::cellCellStencilObject::interpolationCells
virtual const labelUList & interpolationCells() const
Indices of interpolated cells.
Definition: cellCellStencilObject.H:127
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
coupled
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
Foam::stringOps::upper
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1200
Foam::fvMatrix::internalCoeffs
const FieldField< Field, Type > & internalCoeffs() const
Definition: fvMatrix.H:457
Foam::GeometricField< Type, fvPatchField, volMesh >
psi
const volScalarField & psi
Definition: createFieldRefs.H:1
Foam::IOobject::NO_READ
Definition: IOobject.H:188
cellCellStencilObject.H
Foam::SolverPerformance
SolverPerformance is the class returned by the LduMatrix solver containing performance statistics.
Definition: SolverPerformance.H:52
Foam::cellCellStencilObject
Definition: cellCellStencilObject.H:57
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62
Foam::dimless
const dimensionSet dimless
Dimensionless.
Definition: dimensionSets.C:189