surfaceNoise.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) 2015-2023 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 "surfaceNoise.H"
29 #include "surfaceReader.H"
30 #include "surfaceWriter.H"
31 #include "globalIndex.H"
32 #include "argList.H"
34 
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 namespace noiseModels
40 {
41 
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 
46 
47 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
48 
49 void surfaceNoise::initialise(const fileName& fName)
50 {
51  Info<< "Reading data file: "
52  << fileObr_.time().relativePath(fName) << endl;
53 
54  instantList allTimes;
55  label nAvailableTimes = 0;
56 
57  // All reading performed on the master processor only
58  if (Pstream::master())
59  {
60  // Create the surface reader
62 
63  // Find the index of the pressure data
64  const wordList fieldNames(readerPtr_->fieldNames(0));
65  pIndex_ = fieldNames.find(pName_);
66  if (pIndex_ == -1)
67  {
69  << "Unable to find pressure field name " << pName_
70  << " in list of available fields: " << fieldNames
71  << exit(FatalError);
72  }
73 
74  // Create the surface writer
75  // - Could be done later, but since this utility can process a lot of
76  // data we can ensure that the user-input is correct prior to doing
77  // the heavy lifting
78 
79  // Set the time range
80  allTimes = readerPtr_->times();
82 
83  // Determine the windowing
84  nAvailableTimes = allTimes.size() - startTimeIndex_;
85  }
86 
88  (
90  pIndex_,
92  nAvailableTimes
93  );
94 
95 
96  // Note: all processors should call the windowing validate function
97  label nRequiredTimes = windowModelPtr_->validate(nAvailableTimes);
98 
99  if (UPstream::master())
100  {
101  // Restrict times
102  times_.resize_nocopy(nRequiredTimes);
103  forAll(times_, timei)
104  {
105  times_[timei] = allTimes[timei + startTimeIndex_].value();
106  }
107 
108  deltaT_ =
109  (
110  sampleFreq_ > 0
111  ? (1.0/sampleFreq_)
113  );
114 
115  // Read the surface geometry
116  // Note: hard-coded to read mesh from first time index
117  const meshedSurface& surf = readerPtr_->geometry(0);
118 
119  nFaces_ = surf.nFaces();
120  }
121 
123  (
125  times_,
127  nFaces_
128  );
129 }
130 
131 
133 (
134  const globalIndex& procFaceAddr,
135  List<scalarField>& pData
136 )
137 {
138  // Data is stored as pressure on surface at a given time. Now we need to
139  // pivot the data so that we have the complete pressure time history per
140  // surface face. In serial mode, this results in all pressure data being
141  // loaded into memory (!)
142 
143  const label nLocalFace = procFaceAddr.localSize();
144 
145  // Complete pressure time history data for subset of faces
146  pData.resize_nocopy(nLocalFace);
147  const label nTimes = times_.size();
148  for (scalarField& pf : pData)
149  {
150  pf.resize_nocopy(nTimes);
151  }
152 
153  Info<< "Reading pressure data" << endl;
154 
155  // Master only
156  scalarField allData;
157 
158  if (Pstream::parRun())
159  {
160  // Procedure:
161  // 1. Master processor reads pressure data for all faces for all times
162  // 2. Master sends each processor a subset of faces
163  // 3. Local processor reconstructs the full time history for the subset
164  // of faces
165  // Note: reading all data on master to avoid potential NFS problems...
166 
167  scalarField scratch;
168 
169  if (!useBroadcast_)
170  {
171  scratch.resize(nLocalFace);
172  }
173 
174  // Read data and send to sub-ranks
175  forAll(times_, timei)
176  {
177  const label fileTimeIndex = timei + startTimeIndex_;
178 
179  if (Pstream::master())
180  {
181  Info<< " time: " << times_[timei] << endl;
182 
183  // Read pressure at all faces for time timeI
184  allData = readerPtr_->field(fileTimeIndex, pIndex_, scalar(0));
185  }
186 
187  if (useBroadcast_)
188  {
189  Pstream::broadcast(allData);
190  }
191  else
192  {
193  procFaceAddr.scatter
194  (
195  allData,
196  scratch,
198  commType_,
200  );
201  }
202 
203  scalarField::subField procData =
204  (
206  ? allData.slice(procFaceAddr.range())
207  : scratch.slice(0, nLocalFace)
208  );
209 
210  // Apply conversions
211  procData *= rhoRef_;
212 
213  // Transcribe this time snapshot (transpose)
214  forAll(procData, facei)
215  {
216  pData[facei][timei] = procData[facei];
217  }
218  }
219  }
220  else
221  {
222  // Read data - no sub-ranks
223  forAll(times_, timei)
224  {
225  const label fileTimeIndex = timei + startTimeIndex_;
226 
227  Info<< " time: " << times_[timei] << endl;
228 
229  allData = readerPtr_->field(fileTimeIndex, pIndex_, scalar(0));
230 
231  auto& procData = allData;
232 
233  // Apply conversions
234  procData *= rhoRef_;
235 
236  // Transcribe this time snapshot (transpose)
237  forAll(procData, facei)
238  {
239  pData[facei][timei] = procData[facei];
240  }
241  }
242  }
243 
244  forAll(pData, facei)
245  {
246  pData[facei] -= average(pData[facei]);
247  }
248 
249 
250  Info<< "Read "
251  << returnReduce(pData.size(), sumOp<label>())
252  << " pressure traces with "
253  << times_.size()
254  << " time values" << nl << endl;
255 }
256 
257 
259 (
260  const scalarField& data,
261  const globalIndex& procFaceAddr
262 ) const
263 {
264  if (!nFaces_)
265  {
266  // Already reduced, can use as sanity check
267  return 0;
268  }
269 
270  scalar areaAverage = 0;
271 
272  if (areaAverage_)
273  {
274  if (Pstream::parRun())
275  {
276  // Collect the surface data so that we can output the surfaces
277  scalarField allData;
278 
279  procFaceAddr.gather
280  (
281  data,
282  allData,
284  commType_,
286  );
287 
288  if (Pstream::master())
289  {
290  // Note: hard-coded to read mesh from first time index
291  const meshedSurface& surf = readerPtr_->geometry(0);
292 
293  areaAverage = sum(allData*surf.magSf())/sum(surf.magSf());
294  }
295  }
296  else
297  {
298  // Note: hard-coded to read mesh from first time index
299  const meshedSurface& surf = readerPtr_->geometry(0);
300 
301  areaAverage = sum(data*surf.magSf())/sum(surf.magSf());
302  }
303 
304  Pstream::broadcast(areaAverage);
305  }
306  else
307  {
308  // Ensemble averaged
309  // - same as gAverage, but already know number of faces
310 
311  areaAverage = sum(data);
312  reduce(areaAverage, sumOp<scalar>());
313 
314  areaAverage /= (scalar(nFaces_) + ROOTVSMALL);
315  }
316 
317  return areaAverage;
318 }
319 
320 
322 (
323  const fileName& outDirBase,
324  const word& fName,
325  const word& title,
326  const scalar freq,
327  const scalarField& data,
328  const globalIndex& procFaceAddr,
329  const bool writeSurface
330 ) const
331 {
332  Info<< " processing " << title << " for frequency " << freq << endl;
333 
334  const instant freqInst(freq, Foam::name(freq));
335 
336  if (!writeSurface)
337  {
338  return surfaceAverage(data, procFaceAddr);
339  }
340 
341  scalar areaAverage = 0;
342 
343  if (Pstream::parRun())
344  {
345  // Collect the surface data so that we can output the surfaces
346  scalarField allData;
347 
348  procFaceAddr.gather
349  (
350  data,
351  allData,
353  commType_,
355  );
356 
357  if (Pstream::master())
358  {
359  // Note: hard-coded to read mesh from first time index
360  const meshedSurface& surf = readerPtr_->geometry(0);
361 
362  if (areaAverage_)
363  {
364  areaAverage = sum(allData*surf.magSf())/sum(surf.magSf());
365  }
366  else
367  {
368  areaAverage = sum(allData)/(allData.size() + ROOTVSMALL);
369  }
370 
371  // (writeSurface == true)
372  {
373  // Time-aware, with time spliced into the output path
374  writerPtr_->beginTime(freqInst);
375 
376  writerPtr_->open
377  (
378  surf.points(),
379  surf.surfFaces(),
380  (outDirBase / fName),
381  false // serial - already merged
382  );
383 
384  writerPtr_->nFields(1); // Legacy VTK
385  writerPtr_->write(title, allData);
386 
387  writerPtr_->endTime();
388  writerPtr_->clear();
389  }
390  }
391  }
392  else
393  {
394  // Note: hard-coded to read mesh from first time index
395  const meshedSurface& surf = readerPtr_->geometry(0);
396 
397  if (areaAverage_)
398  {
399  areaAverage = sum(data*surf.magSf())/sum(surf.magSf());
400  }
401  else
402  {
403  areaAverage = sum(data)/(data.size() + ROOTVSMALL);
404  }
405 
406  // (writeSurface == true)
407  {
408  // Time-aware, with time spliced into the output path
409  writerPtr_->beginTime(freqInst);
410 
411  writerPtr_->open
412  (
413  surf.points(),
414  surf.surfFaces(),
415  (outDirBase / fName),
416  false // serial - already merged
417  );
418 
419  writerPtr_->nFields(1); // Legacy VTK
420  writerPtr_->write(title, data);
421 
422  writerPtr_->endTime();
423  writerPtr_->clear();
424  }
425  }
426 
427  Pstream::broadcast(areaAverage);
428  return areaAverage;
429 }
430 
431 
432 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
433 
435 (
436  const dictionary& dict,
437  const objectRegistry& obr,
438  const word& name,
439  const bool readFields
440 )
441 :
442  noiseModel(dict, obr, name, false),
443  inputFileNames_(),
444  pName_("p"),
445  pIndex_(0),
446  times_(),
447  deltaT_(0),
448  startTimeIndex_(0),
449  nFaces_(0),
450  fftWriteInterval_(1),
451  areaAverage_(false),
452  useBroadcast_(false),
453  commType_(UPstream::commsTypes::scheduled),
454  readerType_(),
455  readerPtr_(nullptr),
456  writerPtr_(nullptr)
457 {
458  if (readFields)
459  {
461  }
462 }
463 
464 
465 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
466 
468 {
469  if (noiseModel::read(dict))
470  {
471  if (!dict.readIfPresent("files", inputFileNames_))
472  {
474  dict.readEntry("file", inputFileNames_.first());
475  }
476 
477  dict.readIfPresent("p", pName_);
478  dict.readIfPresent("fftWriteInterval", fftWriteInterval_);
479 
480  Info<< this->type() << nl
481  << " Pressure field name: " << pName_ << nl
482  << " FFT write interval: " << fftWriteInterval_ << nl;
483 
484  dict.readIfPresent("areaAverage", areaAverage_);
485 
486  if (areaAverage_)
487  {
488  Info<< " Averaging: area weighted" << endl;
489  }
490  else
491  {
492  Info<< " Averaging: ensemble" << endl;
493  }
494 
495  useBroadcast_ = false;
496  dict.readIfPresent("broadcast", useBroadcast_);
498 
499  if (Pstream::parRun())
500  {
501  Info<< " Distribute fields: "
503 
504  if (useBroadcast_)
505  {
506  Info<< " (broadcast all)";
507  }
508  Info<< endl;
509  }
510 
511  readerType_ = dict.get<word>("reader");
512 
513  // Surface writer (keywords: writer, writeOptions)
514 
515  const word writerType = dict.get<word>("writer");
516 
518  (
519  writerType,
520  surfaceWriter::formatOptions(dict, writerType, "writeOptions")
521  );
522 
523  // Use outputDir/TIME/surface-name
524  writerPtr_->useTimeDir(true);
525 
526  Info<< endl;
527 
528  return true;
529  }
530 
531  return false;
532 }
533 
534 
536 {
537  forAll(inputFileNames_, filei)
538  {
539  fileName fName = inputFileNames_[filei];
540  fName.expand();
541 
542  if (!fName.isAbsolute())
543  {
544  fName = argList::envGlobalPath()/fName;
545  }
546 
547  initialise(fName);
548 
549  // Processor face addressing
550  globalIndex procFaceAddr;
551 
552  if (Pstream::parRun())
553  {
554  // Calculate face/proc offsets manually
555  labelList procFaceOffsets(Pstream::nProcs() + 1);
556  const label nFacePerProc = floor(nFaces_/Pstream::nProcs()) + 1;
557 
558  procFaceOffsets[0] = 0;
559  for (label proci = 1; proci < procFaceOffsets.size(); ++proci)
560  {
561  procFaceOffsets[proci] = min(proci*nFacePerProc, nFaces_);
562  }
563 
564  procFaceAddr.offsets() = std::move(procFaceOffsets);
565 
566  // Don't need to broadcast. Already identical on all ranks
567  }
568  else
569  {
570  // Local data only
571  procFaceAddr.reset(globalIndex::gatherNone{}, nFaces_);
572  }
573 
574  // Pressure time history data per face
575  List<scalarField> pData;
576 
577  // Read pressure data from file
578  readSurfaceData(procFaceAddr, pData);
579 
580  // Process the pressure data, and store results as surface values per
581  // frequency so that it can be output using the surface writer
582 
583  Info<< "Creating noise FFTs" << endl;
584 
585  const scalarField freq1(uniformFrequencies(deltaT_, true));
586 
587  const scalar maxFreq1 = max(freq1);
588 
589  // Reset desired frequency range if outside actual frequency range
590  fLower_ = min(fLower_, maxFreq1);
591  fUpper_ = min(fUpper_, maxFreq1);
592 
593  // Storage for FFT data
594  const label nLocalFace = pData.size();
595  const label nFFT = ceil(freq1.size()/scalar(fftWriteInterval_));
596 
597  List<scalarField> surfPrmsf(nFFT);
598  List<scalarField> surfPSDf(nFFT);
599  forAll(surfPrmsf, freqI)
600  {
601  surfPrmsf[freqI].setSize(nLocalFace);
602  surfPSDf[freqI].setSize(nLocalFace);
603  }
604 
605  // Storage for 1/3 octave data
606  labelList octave13BandIDs;
607  scalarField octave13FreqCentre;
609  (
610  freq1,
611  fLower_,
612  fUpper_,
613  3,
614  octave13BandIDs,
615  octave13FreqCentre
616  );
617 
618  label bandSize = 0;
619  if (octave13BandIDs.empty())
620  {
622  << "Octave band calculation failed (zero sized). "
623  << "Please check your input data"
624  << endl;
625  }
626  else
627  {
628  bandSize = octave13BandIDs.size() - 1;
629  }
630 
631  List<scalarField> surfPrms13f(bandSize);
632  forAll(surfPrms13f, freqI)
633  {
634  surfPrms13f[freqI].setSize(nLocalFace);
635  }
636 
637  const windowModel& win = windowModelPtr_();
638 
639  {
640  forAll(pData, faceI)
641  {
642  const scalarField& p = pData[faceI];
643 
644  // Generate the FFT-based data
645  const scalarField Prmsf(RMSmeanPf(p));
646  const scalarField PSDf(this->PSDf(p, deltaT_));
647 
648  // Store the frequency results in slot for face of surface
649  forAll(surfPrmsf, i)
650  {
651  label freqI = i*fftWriteInterval_;
652  surfPrmsf[i][faceI] = Prmsf[freqI];
653  surfPSDf[i][faceI] = PSDf[freqI];
654  }
655 
656  // Integrated PSD = P(rms)^2 [Pa^2]
657  const scalarField Prms13f
658  (
659  octaves
660  (
661  PSDf,
662  freq1,
663  octave13BandIDs
664  )
665  );
666 
667  // Store the 1/3 octave results in slot for face of surface
668  forAll(surfPrms13f, freqI)
669  {
670  surfPrms13f[freqI][faceI] = Prms13f[freqI];
671  }
672  }
673  }
674 
675  const word fNameBase = fName.stem();
676 
677  // Output directory
678  fileName outDirBase(baseFileDir(filei)/fNameBase);
679 
680  const scalar deltaf = 1.0/(deltaT_*win.nSamples());
681  Info<< "Writing fft surface data";
682  if (fftWriteInterval_ == 1)
683  {
684  Info<< endl;
685  }
686  else
687  {
688  Info<< " at every " << fftWriteInterval_ << " frequency points"
689  << endl;
690  }
691 
692  // Common output information
693  // Note: hard-coded to read mesh from first time index
694  scalar surfArea = 0;
695  label surfSize = 0;
696  if (Pstream::master())
697  {
698  const meshedSurface& surf = readerPtr_->geometry(0);
699  surfArea = sum(surf.magSf());
700  surfSize = surf.size();
701  }
703  (
705  surfArea,
706  surfSize
707  );
708 
709  List<Tuple2<string, token>> commonInfo
710  ({
711  {"Area average", token(word(Switch::name(areaAverage_)))},
712  {"Area sum", token(surfArea)},
713  {"Number of faces", token(surfSize)}
714  });
715 
716  {
717  fileName outDir(outDirBase/"fft");
718  fileName outSurfDir(filePath(outDir));
719 
720  // Determine frequency range of interest
721  // Note: frequencies have fixed interval, and are in the range
722  // 0 to fftWriteInterval_*(n-1)*deltaf
723  label f0 = ceil(fLower_/deltaf/scalar(fftWriteInterval_));
724  label f1 = floor(fUpper_/deltaf/scalar(fftWriteInterval_));
725  label nFreq = f1 - f0;
726 
727  scalarField PrmsfAve(nFreq, Zero);
728  scalarField PSDfAve(nFreq, Zero);
729  scalarField fOut(nFreq, Zero);
730 
731  if (nFreq == 0)
732  {
734  << "No surface data available using a fftWriteInterval of "
735  << fftWriteInterval_ << endl;
736  }
737  else
738  {
739  forAll(fOut, i)
740  {
741  label freqI = (i + f0)*fftWriteInterval_;
742  fOut[i] = freq1[freqI];
743 
744 
745  PrmsfAve[i] = writeSurfaceData
746  (
747  outSurfDir,
748  fNameBase,
749  "Prmsf",
750  freq1[freqI],
751  surfPrmsf[i + f0],
752  procFaceAddr,
754  );
755 
756  PSDfAve[i] = writeSurfaceData
757  (
758  outSurfDir,
759  fNameBase,
760  "PSDf",
761  freq1[freqI],
762  surfPSDf[i + f0],
763  procFaceAddr,
764  writePSDf_
765  );
767  (
768  outSurfDir,
769  fNameBase,
770  "PSD",
771  freq1[freqI],
772  PSD(surfPSDf[i + f0]),
773  procFaceAddr,
774  writePSD_
775  );
777  (
778  outSurfDir,
779  fNameBase,
780  "SPL",
781  freq1[freqI],
782  SPL(surfPSDf[i + f0]*deltaf, freq1[freqI]),
783  procFaceAddr,
784  writeSPL_
785  );
786  }
787  }
788 
789  if (Pstream::master())
790  {
791  {
792  auto filePtr = newFile(outDir/"Average_Prms_f");
793  auto& os = filePtr();
794 
795  Info<< " Writing " << os.relativeName() << endl;
796 
797  writeFileHeader(os, "f [Hz]", "P(f) [Pa]", commonInfo);
798  writeFreqDataToFile(os, fOut, PrmsfAve);
799  }
800  {
801  auto filePtr = newFile(outDir/"Average_PSD_f_f");
802  auto& os = filePtr();
803 
804  Info<< " Writing " << os.relativeName() << endl;
805 
807  (
808  os,
809  "f [Hz]",
810  "PSD(f) [PaPa_Hz]",
811  commonInfo
812  );
813  writeFreqDataToFile(os, fOut, PSDfAve);
814  }
815  {
816  auto filePtr = newFile(outDir/"Average_PSD_dB_Hz_f");
817  auto& os = filePtr();
818 
819  Info<< " Writing " << os.relativeName() << endl;
820 
822  (
823  os,
824  "f [Hz]",
825  "PSD(f) [dB_Hz]",
826  commonInfo
827  );
828  writeFreqDataToFile(os, fOut, PSD(PSDfAve));
829  }
830  {
831  auto filePtr = newFile(outDir/"Average_SPL_dB_f");
832  auto& os = filePtr();
833 
834  Info<< " Writing " << os.relativeName() << endl;
835 
837  (
838  os,
839  "f [Hz]",
840  "SPL(f) [dB]",
841  commonInfo
842  );
843  writeFreqDataToFile(os, fOut, SPL(PSDfAve*deltaf, fOut));
844  }
845  }
846  }
847 
848 
849  Info<< "Writing one-third octave surface data" << endl;
850  {
851  fileName outDir(outDirBase/"oneThirdOctave");
852  fileName outSurfDir(filePath(outDir));
853 
854  scalarField PSDfAve(surfPrms13f.size(), Zero);
855  scalarField Prms13fAve(surfPrms13f.size(), Zero);
856 
857  forAll(surfPrms13f, i)
858  {
860  (
861  outSurfDir,
862  fNameBase,
863  "SPL13",
864  octave13FreqCentre[i],
865  SPL(surfPrms13f[i], octave13FreqCentre[i]),
866  procFaceAddr,
868  );
869 
870  Prms13fAve[i] =
871  surfaceAverage(surfPrms13f[i], procFaceAddr);
872  }
873 
874  if (Pstream::master())
875  {
876  auto filePtr = newFile(outDir/"Average_SPL13_dB_fm");
877  auto& os = filePtr();
878 
879  Info<< " Writing " << os.relativeName() << endl;
880 
882  (
883  os,
884  "fm [Hz]",
885  "SPL(fm) [dB]",
886  commonInfo
887  );
889  (
890  os,
891  octave13FreqCentre,
892  SPL(Prms13fAve, octave13FreqCentre)
893  );
894  }
895  }
896  }
897 }
898 
899 
900 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
901 
902 } // End namespace noiseModels
903 } // End namespace Foam
904 
905 // ************************************************************************* //
label nFaces_
Global number of surface faces.
Definition: surfaceNoise.H:192
virtual void calculate()
Calculate.
Definition: surfaceNoise.C:528
labelRange range(const label proci) const
Return start/size range of proci data.
Definition: globalIndexI.H:282
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &f1)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1)
A class for handling file names.
Definition: fileName.H:72
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:82
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
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
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
autoPtr< windowModel > windowModelPtr_
Window model.
Definition: noiseModel.H:263
bool readIfPresent(const word &key, const dictionary &dict, EnumType &val, const bool warnOnly=false) const
Find an entry if present, and assign to T val.
Definition: EnumI.H:111
bool writeOctaves_
Write writeOctaves; default = yes.
Definition: noiseModel.H:319
label startTimeIndex_
Start time index.
Definition: surfaceNoise.H:187
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
void initialise(const fileName &fName)
Initialise.
Definition: surfaceNoise.C:42
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
scalar surfaceAverage(const scalarField &data, const globalIndex &procFaceAddr) const
Calculate the area average value.
Definition: surfaceNoise.C:252
surfaceNoise(const dictionary &dict, const objectRegistry &obr, const word &name=typeName, const bool readFields=true)
Constructor.
Definition: surfaceNoise.C:428
T & first()
Access first element of the list, position [0].
Definition: UList.H:853
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
autoPtr< surfaceWriter > writerPtr_
Pointer to the surface writer.
Definition: surfaceNoise.H:231
fileName relativePath(const fileName &input, const bool caseTag=false) const
Return the input relative to the globalPath by stripping off a leading value of the globalPath...
Definition: TimePathsI.H:103
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:175
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
static bool isAbsolute(const std::string &str)
Return true if filename starts with a &#39;/&#39; or &#39;\&#39; or (windows-only) with a filesystem-root.
Definition: fileNameI.H:129
virtual autoPtr< OFstream > newFile(const fileName &fName) const
Return autoPtr to a new file using file name.
Definition: writeFile.C:82
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:409
static dictionary formatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Same as fileFormats::getFormatOptions.
Definition: surfaceWriter.C:57
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
defineTypeNameAndDebug(pointNoise, 0)
static label findStart(const UList< instant > &times, const scalar timeVal)
Find and return index of given start time (linear search)
Definition: instant.C:37
bool writePrmsf_
Write Prmsf; default = yes.
Definition: noiseModel.H:299
static std::string stem(const std::string &str)
Return the basename, without extension.
Definition: fileName.C:391
Macros for easy insertion into run-time selection tables.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
word pName_
Name of pressure field.
Definition: surfaceNoise.H:167
scalar startTime_
Start time, default = 0s.
Definition: noiseModel.H:258
scalar rhoRef_
Reference density (to convert from kinematic to static pressure)
Definition: noiseModel.H:233
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
scalar fUpper_
Upper frequency limit, default = 10kHz.
Definition: noiseModel.H:248
scalar checkUniformTimeStep(const scalarList &times) const
Check and return uniform time step.
Definition: noiseModel.C:177
autoPtr< OFstream > filePtr
Definition: createFields.H:37
fileName filePath(const fileName &fName) const
Return the full path for the supplied file name.
Definition: writeFile.C:73
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
static const char * name(const bool b) noexcept
A string representation of bool as "false" / "true".
Definition: Switch.C:141
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
scalarList times_
Sample times.
Definition: surfaceNoise.H:177
scalar writeSurfaceData(const fileName &outDirBase, const word &fName, const word &title, const scalar freq, const scalarField &data, const globalIndex &procFaceAddr, const bool writeSurface) const
Write surface data to file.
Definition: surfaceNoise.C:315
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: noiseModel.C:649
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
tmp< scalarField > octaves(const scalarField &data, const scalarField &f, const labelUList &freqBandIDs) const
Generate octave data.
Definition: noiseModel.C:332
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const NameMatchPredicate &selectedFields, DynamicList< regIOobject *> &storedObjects)
Read the selected GeometricFields of the templated type and store on the objectRegistry.
void writeFileHeader(Ostream &os, const string &x, const string &y, const UList< Tuple2< string, token >> &headerValues=UList< Tuple2< string, token >>::null()) const
Write output file header.
Definition: noiseModel.C:250
A class for handling words, derived from Foam::string.
Definition: word.H:63
const scalarField & magSf() const
Face area magnitudes.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const Time & time() const noexcept
Return time registry.
MeshedSurface< face > meshedSurface
tmp< scalarField > PSDf(const scalarField &p, const scalar deltaT) const
Return the multi-window Power Spectral Density (PSD) of the complete pressure data [Pa^2/Hz]...
Definition: noiseModel.C:466
label localSize(const label proci) const
Size of proci data.
Definition: globalIndexI.H:257
List< fileName > inputFileNames_
Input file names.
Definition: surfaceNoise.H:162
bool useBroadcast_
Use broadcast to send entire field to sub-ranks.
Definition: surfaceNoise.H:211
SubField< Type > slice(const label pos, label len=-1)
Return SubField slice (non-const access) - no range checking.
Definition: SubField.H:219
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
void writeFreqDataToFile(Ostream &os, const scalarField &f, const scalarField &fx) const
Definition: noiseModel.C:278
tmp< Foam::scalarField > PSD(const scalarField &PSDf) const
PSD [dB/Hz].
Definition: noiseModel.C:758
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: surfaceNoise.C:460
bool writeSPL_
Write SPL; default = yes.
Definition: noiseModel.H:304
autoPtr< surfaceReader > readerPtr_
Pointer to the surface reader.
Definition: surfaceNoise.H:226
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
OBJstream os(runTime.globalPath()/outputName)
bool areaAverage_
Apply area average; default = no (ensemble average) for backwards compatibility.
Definition: surfaceNoise.H:206
scalar deltaT_
Time step (constant)
Definition: surfaceNoise.H:182
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
UPstream::commsTypes commType_
Communication type (for sending/receiving fields)
Definition: surfaceNoise.H:216
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
fileName baseFileDir() const
Return the base directory for output.
Definition: writeFile.C:43
static autoPtr< surfaceReader > New(const word &readType, const fileName &fName, const dictionary &options=dictionary())
Return a reference to the selected surfaceReader.
Definition: surfaceReader.C:71
static fileName envGlobalPath()
Global case (directory) from environment variable.
Definition: argList.C:651
label fftWriteInterval_
Frequency data output interval, default = 1.
Definition: surfaceNoise.H:200
#define WarningInFunction
Report a warning using Foam::Warning.
string & expand(const bool allowEmpty=false)
Inplace expand initial tags, tildes, and all occurrences of environment variables as per stringOps::e...
Definition: string.C:166
Perform noise analysis on surface-based pressure data.
Definition: surfaceNoise.H:151
static void setOctaveBands(const scalarField &f, const scalar fLower, const scalar fUpper, const scalar octave, labelList &fBandIDs, scalarField &fCentre)
Return a list of the frequency indices wrt f field that correspond to the bands limits for a given oc...
Definition: noiseModel.C:48
bool writePSDf_
Write PSDf; default = yes.
Definition: noiseModel.H:314
void readSurfaceData(const globalIndex &procFaceAddr, List< scalarField > &pData)
Read surface data.
Definition: surfaceNoise.C:126
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
addToRunTimeSelectionTable(noiseModel, pointNoise, dictionary)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
label pIndex_
Index of pressure field in reader field list.
Definition: surfaceNoise.H:172
const objectRegistry & fileObr_
Reference to the region objectRegistry.
Definition: writeFile.H:121
tmp< scalarField > SPL(const scalarField &Prms2, const scalar f) const
SPL [dB].
Definition: noiseModel.C:767
messageStream Info
Information stream (stdout output on master, null elsewhere)
bool writePSD_
Write PSD; default = yes.
Definition: noiseModel.H:309
SubField< scalar > subField
Declare type of subField.
Definition: Field.H:128
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const UPstream::commsTypes=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
Registry of regIOobjects.
tmp< scalarField > uniformFrequencies(const scalar deltaT, const bool check) const
Create a field of equally spaced frequencies for the current set of data - assumes a constant time st...
Definition: noiseModel.C:295
scalar sampleFreq_
Prescribed sample frequency.
Definition: noiseModel.H:253
Inter-processor communications stream.
Definition: UPstream.H:60
static autoPtr< surfaceWriter > New(const word &writeType)
Return a reference to the selected surfaceWriter.
Definition: surfaceWriter.C:80
tmp< scalarField > RMSmeanPf(const scalarField &p) const
Return the multi-window RMS mean fft of the complete pressure data [Pa].
Definition: noiseModel.C:447
Namespace for OpenFOAM.
scalar fLower_
Lower frequency limit, default = 25Hz.
Definition: noiseModel.H:243
static void scatter(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &allFld, UList< Type > &fld, const int tag=UPstream::msgType(), const UPstream::commsTypes=UPstream::commsTypes::nonBlocking)
Distribute data in processor order.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
Base class for noise models.
Definition: noiseModel.H:175