cyclicACMIFvPatchField.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) 2013-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 "fvMatrix.H"
31 #include "transformField.H"
32 
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const fvPatch& p,
40 )
41 :
43  coupledFvPatchField<Type>(p, iF),
44  cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p)),
45  patchNeighbourFieldPtr_(nullptr)
46 {}
47 
48 
49 template<class Type>
51 (
52  const fvPatch& p,
54  const dictionary& dict
55 )
56 :
58  coupledFvPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
59  cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p, dict)),
60  patchNeighbourFieldPtr_(nullptr)
61 {
62  if (!isA<cyclicACMIFvPatch>(p))
63  {
65  << " patch type '" << p.type()
66  << "' not constraint type '" << typeName << "'"
67  << "\n for patch " << p.name()
68  << " of field " << this->internalField().name()
69  << " in file " << this->internalField().objectPath()
70  << exit(FatalIOError);
71  }
72 
73  if (cacheNeighbourField())
74  {
75  // Handle neighbour value first, before any evaluate()
76  const auto* hasNeighbValue =
77  dict.findEntry("neighbourValue", keyType::LITERAL);
78 
79  if (hasNeighbValue)
80  {
81  patchNeighbourFieldPtr_.reset
82  (
83  new Field<Type>(*hasNeighbValue, p.size())
84  );
85  }
86  }
87 
88  // Use 'value' supplied, or set to coupled field
89  if (!this->readValueEntry(dict) && this->coupled())
90  {
91  // Extra check: make sure that the non-overlap patch is before
92  // this so it has actually been read - evaluate will crash otherwise
93 
94  const auto& fld =
95  static_cast<const GeometricField<Type, fvPatchField, volMesh>&>
96  (
97  this->primitiveField()
98  );
99 
100  if (!fld.boundaryField().set(cyclicACMIPatch_.nonOverlapPatchID()))
101  {
103  << " patch " << p.name()
104  << " of field " << this->internalField().name()
105  << " refers to non-overlap patch "
106  << cyclicACMIPatch_.cyclicACMIPatch().nonOverlapPatchName()
107  << " which is not constructed yet." << nl
108  << " Either supply an initial value or change the ordering"
109  << " in the file"
110  << exit(FatalIOError);
111  }
112 
113  // Tricky: avoid call to evaluate without call to initEvaluate.
114  // For now just disable the localConsistency to make it use the
115  // old logic (ultimately calls the fully self contained
116  // patchNeighbourField)
117 
118  const auto oldConsistency = FieldBase::localBoundaryConsistency(0);
119 
121 
123  }
124 }
125 
126 
127 template<class Type>
129 (
130  const cyclicACMIFvPatchField<Type>& ptf,
131  const fvPatch& p,
132  const DimensionedField<Type, volMesh>& iF,
133  const fvPatchFieldMapper& mapper
134 )
135 :
136  cyclicACMILduInterfaceField(),
137  coupledFvPatchField<Type>(ptf, p, iF, mapper),
138  cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p)),
139  patchNeighbourFieldPtr_(nullptr)
140 {
141  //if (ptf.patchNeighbourFieldPtr_ && cacheNeighbourField())
142  //{
143  // patchNeighbourFieldPtr_.reset
144  // (
145  // new Field<Type>(ptf.patchNeighbourFieldPtr_(), mapper)
146  // );
147  //}
148 
149  if (!isA<cyclicACMIFvPatch>(this->patch()))
150  {
152  << "\n patch type '" << p.type()
153  << "' not constraint type '" << typeName << "'"
154  << "\n for patch " << p.name()
155  << " of field " << this->internalField().name()
156  << " in file " << this->internalField().objectPath()
157  << exit(FatalError);
158  }
159  if (debug && !ptf.all_ready())
160  {
162  << "Outstanding request(s) on patch " << cyclicACMIPatch_.name()
164  }
165 }
166 
167 
168 template<class Type>
170 (
171  const cyclicACMIFvPatchField<Type>& ptf
172 )
173 :
174  cyclicACMILduInterfaceField(),
175  coupledFvPatchField<Type>(ptf),
176  cyclicACMIPatch_(ptf.cyclicACMIPatch_),
177  patchNeighbourFieldPtr_(nullptr)
178 {
179  if (debug && !ptf.all_ready())
180  {
182  << "Outstanding request(s) on patch " << cyclicACMIPatch_.name()
184  }
185 }
186 
187 
188 template<class Type>
190 (
191  const cyclicACMIFvPatchField<Type>& ptf,
192  const DimensionedField<Type, volMesh>& iF
193 )
194 :
195  cyclicACMILduInterfaceField(),
196  coupledFvPatchField<Type>(ptf, iF),
197  cyclicACMIPatch_(ptf.cyclicACMIPatch_),
198  patchNeighbourFieldPtr_(nullptr)
199 {
200  if (debug && !ptf.all_ready())
201  {
203  << "Outstanding request(s) on patch " << cyclicACMIPatch_.name()
204  << abort(FatalError);
205  }
206 }
207 
208 
209 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
210 
211 template<class Type>
213 {
214  return cyclicACMIPatch_.coupled();
215 }
216 
217 
218 template<class Type>
220 {
221  int done = 0;
222 
223  if
224  (
226  (
227  recvRequests_.start(),
228  recvRequests_.size()
229  )
230  )
231  {
232  recvRequests_.clear();
233  ++done;
234  }
235 
236  if
237  (
239  (
240  sendRequests_.start(),
241  sendRequests_.size()
242  )
243  )
244  {
245  sendRequests_.clear();
246  ++done;
247  }
248 
249  return (done == 2);
250 }
251 
252 
253 template<class Type>
255 {
256  if
257  (
259  (
260  recvRequests_.start(),
261  recvRequests_.size()
262  )
263  )
264  {
265  recvRequests_.clear();
266 
267  if
268  (
270  (
271  sendRequests_.start(),
272  sendRequests_.size()
273  )
274  )
275  {
276  sendRequests_.clear();
277  }
278 
279  return true;
280  }
281 
282  return false;
283 }
284 
285 
286 template<class Type>
289 (
290  const UList<Type>& internalData
291 ) const
292 {
293  DebugPout
294  << "cyclicACMIFvPatchField::getNeighbourField(const UList<Type>&) :"
295  << " field:" << this->internalField().name()
296  << " patch:" << this->patch().name()
297  << endl;
298 
299  // By pass polyPatch to get nbrId. Instead use cyclicACMIFvPatch virtual
300  // neighbPatch()
301  const auto& neighbPatch = cyclicACMIPatch_.neighbPatch();
302  const labelUList& nbrFaceCells = neighbPatch.faceCells();
303 
304  tmp<Field<Type>> tpnf
305  (
306  cyclicACMIPatch_.interpolate
307  (
308  Field<Type>(internalData, nbrFaceCells)
309  )
310  );
311 
312  if (doTransform())
313  {
314  transform(tpnf.ref(), forwardT(), tpnf());
315  }
316 
317  return tpnf;
318 }
319 
320 
321 template<class Type>
323 {
324  /*
325  return (FieldBase::localBoundaryConsistency() != 0);
326  */
327  return false;
328 }
329 
330 
331 template<class Type>
334 (
335  const bool checkCommunicator
336 ) const
337 {
338  const auto& AMI = this->ownerAMI();
339 
340  if
341  (
342  AMI.distributed() && cacheNeighbourField()
343  && (!checkCommunicator || AMI.comm() != -1)
344  )
345  {
346  if (!this->ready())
347  {
349  << "Outstanding recv request(s) on patch "
350  << cyclicACMIPatch_.name()
351  << " field " << this->internalField().name()
352  << abort(FatalError);
353  }
354 
355  // Initialise if not done in construct-from-dictionary
356  if (!patchNeighbourFieldPtr_)
357  {
358  DebugPout
359  << "cyclicACMIFvPatchField::patchNeighbourField() :"
360  << " field:" << this->internalField().name()
361  << " patch:" << this->patch().name()
362  << " calculating&caching patchNeighbourField"
363  << endl;
364 
365  // Do interpolation and store result
366  patchNeighbourFieldPtr_.reset
367  (
368  getNeighbourField(this->primitiveField()).ptr()
369  );
370  }
371  else
372  {
373  DebugPout
374  << "cyclicACMIFvPatchField::patchNeighbourField() :"
375  << " field:" << this->internalField().name()
376  << " patch:" << this->patch().name()
377  << " returning cached patchNeighbourField"
378  << endl;
379  }
380  return patchNeighbourFieldPtr_();
381  }
382  else
383  {
384  // Do interpolation
385  DebugPout
386  << "cyclicACMIFvPatchField::evaluate() :"
387  << " field:" << this->internalField().name()
388  << " patch:" << this->patch().name()
389  << " calculating up-to-date patchNeighbourField"
390  << endl;
391 
392  return getNeighbourField(this->primitiveField());
393  }
394 }
395 
396 
397 template<class Type>
400 {
401  return this->getPatchNeighbourField(true); // checkCommunicator = true
402 }
403 
404 
405 template<class Type>
407 (
408  UList<Type>& pnf
409 ) const
410 {
411  // checkCommunicator = false
412  auto tpnf = this->getPatchNeighbourField(false);
413  pnf.deepCopy(tpnf());
414 }
415 
416 
417 template<class Type>
420 {
421  const auto& fld =
423  (
424  this->primitiveField()
425  );
426 
427  return refCast<const cyclicACMIFvPatchField<Type>>
428  (
429  fld.boundaryField()[cyclicACMIPatch_.neighbPatchID()]
430  );
431 }
432 
433 
434 template<class Type>
437 {
438  const auto& fld =
440  (
441  this->primitiveField()
442  );
443 
444  // WIP: Needs to re-direct nonOverlapPatchID to new patchId for assembly?
445  return fld.boundaryField()[cyclicACMIPatch_.nonOverlapPatchID()];
446 }
447 
448 
449 template<class Type>
451 (
452  const Pstream::commsTypes commsType
453 )
454 {
455  if (!this->updated())
456  {
457  this->updateCoeffs();
458  }
459 
460  const auto& AMI = this->ownerAMI();
461 
462  if (AMI.distributed() && cacheNeighbourField() && AMI.comm() != -1)
463  {
464  if (commsType != UPstream::commsTypes::nonBlocking)
465  {
466  // Invalidate old field - or flag as fatal?
467  patchNeighbourFieldPtr_.reset(nullptr);
468  return;
469  }
470 
471  // Start sending
472  DebugPout
473  << "cyclicACMIFvPatchField::initEvaluate() :"
474  << " field:" << this->internalField().name()
475  << " patch:" << this->patch().name()
476  << " starting send&receive"
477  << endl;
478 
479  // Bypass polyPatch to get nbrId.
480  // - use cyclicACMIFvPatch::neighbPatch() virtual instead
481  const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.neighbPatch();
482  const labelUList& nbrFaceCells = neighbPatch.faceCells();
483  const Field<Type> pnf(this->primitiveField(), nbrFaceCells);
484 
485  // Assert that all receives are known to have finished
486  if (!recvRequests_.empty())
487  {
489  << "Outstanding recv request(s) on patch "
490  << cyclicACMIPatch_.name()
491  << " field " << this->internalField().name()
492  << abort(FatalError);
493  }
494 
495  // Assume that sends are also OK
496  sendRequests_.clear();
497 
498  cyclicACMIPatch_.initInterpolate
499  (
500  pnf,
501  sendRequests_,
502  sendBufs_,
503  recvRequests_,
504  recvBufs_
505  );
506  }
507 }
508 
509 
510 template<class Type>
512 (
513  const Pstream::commsTypes commsType
514 )
515 {
516  if (!this->updated())
517  {
518  this->updateCoeffs();
519  }
520 
521  const auto& AMI = this->ownerAMI();
522 
523  if (AMI.distributed() && cacheNeighbourField() && AMI.comm() != -1)
524  {
525  // Calculate patchNeighbourField
526  if (commsType != UPstream::commsTypes::nonBlocking)
527  {
529  << "Can only evaluate distributed AMI with nonBlocking"
530  << exit(FatalError);
531  }
532 
533  patchNeighbourFieldPtr_.reset(nullptr);
534 
535  if (!this->ready())
536  {
538  << "Outstanding recv request(s) on patch "
539  << cyclicACMIPatch_.name()
540  << " field " << this->internalField().name()
541  << abort(FatalError);
542  }
543 
544  patchNeighbourFieldPtr_.reset
545  (
546  cyclicACMIPatch_.interpolate
547  (
548  Field<Type>::null(), // Not used for distributed
549  recvRequests_,
550  recvBufs_
551  ).ptr()
552  );
553 
554  // Receive requests all handled by last function call
555  recvRequests_.clear();
556 
557  if (doTransform())
558  {
559  // In-place transform
560  auto& pnf = *patchNeighbourFieldPtr_;
561  transform(pnf, forwardT(), pnf);
562  }
563  }
564 
565  // Use patchNeighbourField() and patchInternalField() to obtain face value
567 }
568 
569 
570 template<class Type>
572 (
573  solveScalarField& result,
574  const bool add,
575  const lduAddressing& lduAddr,
576  const label patchId,
577  const solveScalarField& psiInternal,
578  const scalarField& coeffs,
579  const direction cmpt,
580  const Pstream::commsTypes commsType
581 ) const
582 {
583  const auto& AMI = this->ownerAMI();
584 
585  if (AMI.distributed() && AMI.comm() != -1)
586  {
587  // Start sending
588  if (commsType != UPstream::commsTypes::nonBlocking)
589  {
591  << "Can only evaluate distributed AMI with nonBlocking"
592  << exit(FatalError);
593  }
594 
595  DebugPout
596  << "cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :"
597  << " field:" << this->internalField().name()
598  << " patch:" << this->patch().name()
599  << " starting send&receive"
600  << endl;
601 
602  const labelUList& nbrFaceCells =
603  lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
604 
605  solveScalarField pnf(psiInternal, nbrFaceCells);
606 
607  // Transform according to the transformation tensors
608  transformCoupleField(pnf, cmpt);
609 
610  // Assert that all receives are known to have finished
611  if (!recvRequests_.empty())
612  {
614  << "Outstanding recv request(s) on patch "
615  << cyclicACMIPatch_.name()
616  << " field " << this->internalField().name()
617  << abort(FatalError);
618  }
619 
620  // Assume that sends are also OK
621  sendRequests_.clear();
622 
623  cyclicACMIPatch_.initInterpolate
624  (
625  pnf,
626  sendRequests_,
627  scalarSendBufs_,
628  recvRequests_,
629  scalarRecvBufs_
630  );
631  }
633  this->updatedMatrix(false);
634 }
635 
636 
637 template<class Type>
639 (
640  solveScalarField& result,
641  const bool add,
642  const lduAddressing& lduAddr,
643  const label patchId,
644  const solveScalarField& psiInternal,
645  const scalarField& coeffs,
646  const direction cmpt,
647  const Pstream::commsTypes commsType
648 ) const
649 {
650  DebugPout<< "cyclicACMIFvPatchField::updateInterfaceMatrix() :"
651  << " field:" << this->internalField().name()
652  << " patch:" << this->patch().name()
653  << endl;
654 
655  // note: only applying coupled contribution
656 
657  const labelUList& faceCells = lduAddr.patchAddr(patchId);
658 
659  solveScalarField pnf;
660 
661  const auto& AMI = this->ownerAMI();
662 
663  if (AMI.distributed() && AMI.comm() != -1)
664  {
665  if (commsType != UPstream::commsTypes::nonBlocking)
666  {
668  << "Can only evaluate distributed AMI with nonBlocking"
669  << exit(FatalError);
670  }
671 
672  DebugPout
673  << "cyclicACMIFvPatchField::evaluate() :"
674  << " field:" << this->internalField().name()
675  << " patch:" << this->patch().name()
676  << " consuming received coupled neighbourfield"
677  << endl;
678 
679  pnf =
680  cyclicACMIPatch_.interpolate
681  (
682  solveScalarField::null(), // Not used for distributed
683  recvRequests_,
684  scalarRecvBufs_
685  );
686 
687  // Receive requests all handled by last function call
688  recvRequests_.clear();
689  }
690  else
691  {
692  const labelUList& nbrFaceCells =
693  lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
694 
695  pnf = solveScalarField(psiInternal, nbrFaceCells);
696 
697  // Transform according to the transformation tensors
698  transformCoupleField(pnf, cmpt);
699 
700  pnf = cyclicACMIPatch_.interpolate(pnf);
701  }
702 
703  this->addToInternalField(result, !add, faceCells, coeffs, pnf);
705  this->updatedMatrix(true);
706 }
707 
708 
709 template<class Type>
711 (
712  Field<Type>& result,
713  const bool add,
714  const lduAddressing& lduAddr,
715  const label patchId,
716  const Field<Type>& psiInternal,
717  const scalarField& coeffs,
718  const Pstream::commsTypes commsType
719 ) const
720 {
721  const auto& AMI = this->ownerAMI();
722 
723  if (AMI.distributed() && AMI.comm() != -1)
724  {
725  if (commsType != UPstream::commsTypes::nonBlocking)
726  {
728  << "Can only evaluate distributed AMI with nonBlocking"
729  << exit(FatalError);
730  }
731 
732  const labelUList& nbrFaceCells =
733  lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
734 
735  Field<Type> pnf(psiInternal, nbrFaceCells);
736 
737  // Transform according to the transformation tensors
738  transformCoupleField(pnf);
739 
740  // Assert that all receives are known to have finished
741  if (!recvRequests_.empty())
742  {
744  << "Outstanding recv request(s) on patch "
745  << cyclicACMIPatch_.name()
746  << " field " << this->internalField().name()
747  << abort(FatalError);
748  }
749 
750  // Assume that sends are also OK
751  sendRequests_.clear();
752 
753  cyclicACMIPatch_.initInterpolate
754  (
755  pnf,
756  sendRequests_,
757  sendBufs_,
758  recvRequests_,
759  recvBufs_
760  );
761  }
763  this->updatedMatrix(false);
764 }
765 
766 
767 template<class Type>
769 (
770  Field<Type>& result,
771  const bool add,
772  const lduAddressing& lduAddr,
773  const label patchId,
774  const Field<Type>& psiInternal,
775  const scalarField& coeffs,
776  const Pstream::commsTypes commsType
777 ) const
778 {
779  // note: only applying coupled contribution
780 
781  const labelUList& faceCells = lduAddr.patchAddr(patchId);
782 
783  const auto& AMI = this->ownerAMI();
784 
785  Field<Type> pnf;
786 
787  if (AMI.distributed() && AMI.comm() != -1)
788  {
789  if (commsType != UPstream::commsTypes::nonBlocking)
790  {
792  << "Can only evaluate distributed AMI with nonBlocking"
793  << exit(FatalError);
794  }
795 
796  pnf =
797  cyclicACMIPatch_.interpolate
798  (
799  Field<Type>::null(), // Not used for distributed
800  recvRequests_,
801  recvBufs_
802  );
803 
804  // Receive requests all handled by last function call
805  recvRequests_.clear();
806  }
807  else
808  {
809  const labelUList& nbrFaceCells =
810  lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
811 
812  pnf = Field<Type>(psiInternal, nbrFaceCells);
813 
814  // Transform according to the transformation tensors
815  transformCoupleField(pnf);
816 
817  pnf = cyclicACMIPatch_.interpolate(pnf);
818  }
819 
820  this->addToInternalField(result, !add, faceCells, coeffs, pnf);
822  this->updatedMatrix(true);
823 }
824 
825 
826 template<class Type>
828 (
829  fvMatrix<Type>& matrix
830 )
831 {
832  const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
833 
834  // Nothing to be done by the AMI, but re-direct to non-overlap patch
835  // with non-overlap patch weights
836  const fvPatchField<Type>& npf = nonOverlapPatchField();
838  const_cast<fvPatchField<Type>&>(npf).manipulateMatrix(matrix, 1.0 - mask);
839 }
840 
841 
842 template<class Type>
844 (
845  fvMatrix<Type>& matrix,
846  const label mat,
847  const direction cmpt
848 )
849 {
850  if (this->cyclicACMIPatch().owner())
851  {
852  label index = this->patch().index();
853 
854  const label globalPatchID =
855  matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index];
856 
857  const Field<scalar> intCoeffsCmpt
858  (
859  matrix.internalCoeffs()[globalPatchID].component(cmpt)
860  );
861 
862  const Field<scalar> boundCoeffsCmpt
863  (
864  matrix.boundaryCoeffs()[globalPatchID].component(cmpt)
865  );
866 
867  tmp<Field<scalar>> tintCoeffs(coeffs(matrix, intCoeffsCmpt, mat));
868  tmp<Field<scalar>> tbndCoeffs(coeffs(matrix, boundCoeffsCmpt, mat));
869  const Field<scalar>& intCoeffs = tintCoeffs.ref();
870  const Field<scalar>& bndCoeffs = tbndCoeffs.ref();
871 
872  const labelUList& u = matrix.lduAddr().upperAddr();
873  const labelUList& l = matrix.lduAddr().lowerAddr();
874 
875  label subFaceI = 0;
876 
877  const labelList& faceMap =
878  matrix.lduMeshAssembly().faceBoundMap()[mat][index];
879 
880  forAll (faceMap, j)
881  {
882  label globalFaceI = faceMap[j];
883 
884  const scalar boundCorr = -bndCoeffs[subFaceI];
885  const scalar intCorr = -intCoeffs[subFaceI];
886 
887  matrix.upper()[globalFaceI] += boundCorr;
888  matrix.diag()[u[globalFaceI]] -= intCorr;
889  matrix.diag()[l[globalFaceI]] -= boundCorr;
890 
891  if (matrix.asymmetric())
892  {
893  matrix.lower()[globalFaceI] += intCorr;
894  }
895  subFaceI++;
896  }
897 
898  // Set internalCoeffs and boundaryCoeffs in the assembly matrix
899  // on cyclicACMI patches to be used in the individual matrix by
900  // matrix.flux()
901  if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
902  {
903  matrix.internalCoeffs().set
904  (
905  globalPatchID, intCoeffs*pTraits<Type>::one
906  );
907  matrix.boundaryCoeffs().set
908  (
909  globalPatchID, bndCoeffs*pTraits<Type>::one
910  );
911 
912  const label nbrPathID =
913  cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID();
914 
915  const label nbrGlobalPatchID =
917  [mat][nbrPathID];
918 
919  matrix.internalCoeffs().set
920  (
921  nbrGlobalPatchID, intCoeffs*pTraits<Type>::one
922  );
923  matrix.boundaryCoeffs().set
924  (
925  nbrGlobalPatchID, bndCoeffs*pTraits<Type>::one
926  );
927  }
928  }
929 }
930 
931 
932 template<class Type>
935 (
936  fvMatrix<Type>& matrix,
937  const Field<scalar>& coeffs,
938  const label mat
939 ) const
940 {
941  const label index(this->patch().index());
942 
943  const label nSubFaces
944  (
945  matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
946  );
947 
948  auto tmapCoeffs = tmp<Field<scalar>>::New(nSubFaces, Zero);
949  auto& mapCoeffs = tmapCoeffs.ref();
950 
951  const scalarListList& srcWeight =
952  cyclicACMIPatch_.cyclicACMIPatch().AMI().srcWeights();
953 
954  const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
955 
956  const scalar tol = cyclicACMIPolyPatch::tolerance();
957  label subFaceI = 0;
958  forAll(mask, faceI)
959  {
960  const scalarList& w = srcWeight[faceI];
961  for(label i=0; i<w.size(); i++)
962  {
963  if (mask[faceI] > tol)
964  {
965  const label localFaceId =
966  matrix.lduMeshAssembly().facePatchFaceMap()
967  [mat][index][subFaceI];
968  mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
969  }
970  subFaceI++;
971  }
972  }
973 
974  return tmapCoeffs;
975 }
976 
977 
978 template<class Type>
980 {
981  // Update non-overlap patch - some will implement updateCoeffs, and
982  // others will implement evaluate
983 
984  // Pass in (1 - mask) to give non-overlap patch the chance to do
985  // manipulation of non-face based data
986 
987  const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
988  const fvPatchField<Type>& npf = nonOverlapPatchField();
989  const_cast<fvPatchField<Type>&>(npf).updateWeightedCoeffs(1.0 - mask);
990 }
991 
992 
993 template<class Type>
995 {
998 
999  if (patchNeighbourFieldPtr_)
1000  {
1001  patchNeighbourFieldPtr_->writeEntry("neighbourValue", os);
1002  }
1003 }
1004 
1005 
1006 // ************************************************************************* //
bool readValueEntry(const dictionary &dict, IOobjectOption::readOption readOpt=IOobjectOption::LAZY_READ)
Read the "value" entry into *this.
Definition: fvPatchField.C:32
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
label patchId(-1)
const scalarField & diag() const
Definition: lduMatrix.C:195
dictionary dict
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
uint8_t direction
Definition: direction.H:46
const labelListList & patchLocalToGlobalMap() const
Return patchLocalToGlobalMap.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const fvPatchField< Type > & nonOverlapPatchField() const
Return reference to non-overlapping patchField.
Field< solveScalar > solveScalarField
commsTypes
Communications types.
Definition: UPstream.H:77
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
void checkCommunicator(int comm, int rank)
Fatal if communicator is outside the allocated range.
const fvPatch & patch() const noexcept
Return the patch.
Definition: fvPatchField.H:250
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
virtual void updateInterfaceMatrix(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour coupled internal cell data.
const lduPrimitiveMeshAssembly & lduMeshAssembly()
Return optional lduAdressing.
Definition: fvMatrix.H:476
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition: typeInfo.H:172
virtual label nonOverlapPatchID() const
Return neighbour.
static const Field< Type > & null() noexcept
Return a null Field (reference to a nullObject). Behaves like an empty Field.
Definition: Field.H:186
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:70
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Generic GeometricField class.
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
void writeValueEntry(Ostream &os) const
Write *this field as a "value" entry.
Definition: fvPatchField.H:413
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:52
virtual void write(Ostream &) const
Write.
Definition: fvPatchField.C:374
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
virtual bool coupled() const
Return true if coupled. Note that the underlying patch.
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
static const char *const typeName
Typename for Field.
Definition: Field.H:87
Spatial transformation functions for primitive fields.
Cyclic patch for Arbitrarily Coupled Mesh Interface (ACMI)
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
Definition: fvMatrix.H:485
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
virtual bool ready() const
Are all (receive) data available?
virtual void write(Ostream &os) const
Write.
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:130
List< scalarList > scalarListList
List of scalarList.
Definition: scalarList.H:35
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
const scalarField & lower() const
Definition: lduMatrix.C:306
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: fvPatchField.H:64
const Field< Type > & primitiveField() const noexcept
Return const-reference to the internal field values.
Definition: fvPatchField.H:714
String literal.
Definition: keyType.H:82
const cyclicACMIFvPatchField< Type > & neighbourPatchField() const
Return reference to neighbour patchField.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
cyclicACMIFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Abstract base class for coupled patches.
Abstract base class for cyclic ACMI coupled interfaces.
const word & nonOverlapPatchName() const
Non-overlapping patch name.
bool asymmetric() const noexcept
Matrix is asymmetric (ie, full)
Definition: lduMatrix.H:850
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
int debug
Static debugging option.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
OBJstream os(runTime.globalPath()/outputName)
const labelListListList & faceBoundMap() const
Return boundary face map.
virtual void initInterfaceMatrixUpdate(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
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))
virtual void initEvaluate(const Pstream::commsTypes commsType)
Initialise the evaluation of the patch field.
const cyclicACMIPolyPatch & cyclicACMIPatch() const
Return local reference cast into the cyclic patch.
const scalarField & upper() const
Definition: lduMatrix.C:235
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:769
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const DimensionedField< Type, volMesh > & internalField() const noexcept
Return const-reference to the dimensioned internal field.
Definition: fvPatchField.H:706
const std::string patch
OpenFOAM patch number as a std::string.
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
#define DebugPout
Report an information message using Foam::Pout.
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
const FieldField< Field, Type > & internalCoeffs() const noexcept
fvBoundary scalar field containing pseudo-matrix coeffs for internal cells
Definition: fvMatrix.H:547
The class contains the addressing required by the lduMatrix: upper, lower and losort.
const FieldField< Field, Type > & boundaryCoeffs() const noexcept
fvBoundary scalar field containing pseudo-matrix coeffs for boundary cells
Definition: fvMatrix.H:565
void deepCopy(const UList< T > &list)
Copy elements of the given UList. Sizes must match!
Definition: UList.C:97
virtual const word & name() const
Return name.
Definition: fvPatch.H:210
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
"buffered" : (MPI_Bsend, MPI_Recv)
static int localBoundaryConsistency() noexcept
Get flag for local boundary consistency checks.
Definition: Field.H:127
static scalar tolerance()
Overlap tolerance.
static bool finishedRequests(const label pos, label len=-1)
Non-blocking comms: have all requests (from position onwards) finished? Corresponds to MPI_Testall() ...
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127