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-2022 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 (Pstream::master())
100  {
101  // Restrict times
102  times_.setSize(nRequiredTimes);
103  forAll(times_, timeI)
104  {
105  times_[timeI] = allTimes[timeI + startTimeIndex_].value();
106  }
108 
109  // Read the surface geometry
110  // Note: hard-coded to read mesh from first time index
111  const meshedSurface& surf = readerPtr_->geometry(0);
112 
113  nFaces_ = surf.nFaces();
114  }
115 
117  (
119  times_,
121  nFaces_
122  );
123 }
124 
125 
127 (
128  const globalIndex& procFaceAddr,
129  List<scalarField>& pData
130 )
131 {
132  // Data is stored as pressure on surface at a given time. Now we need to
133  // pivot the data so that we have the complete pressure time history per
134  // surface face. In serial mode, this results in all pressure data being
135  // loaded into memory (!)
136 
137  const label nLocalFace = procFaceAddr.localSize();
138 
139  // Complete pressure time history data for subset of faces
140  pData.resize_nocopy(nLocalFace);
141  const label nTimes = times_.size();
142  for (scalarField& pf : pData)
143  {
144  pf.resize_nocopy(nTimes);
145  }
146 
147  Info<< "Reading pressure data" << endl;
148 
149  // Master only
150  scalarField allData;
151 
152  if (Pstream::parRun())
153  {
154  // Procedure:
155  // 1. Master processor reads pressure data for all faces for all times
156  // 2. Master sends each processor a subset of faces
157  // 3. Local processor reconstructs the full time history for the subset
158  // of faces
159  // Note: reading all data on master to avoid potential NFS problems...
160 
161  scalarField scratch;
162 
163  if (!useBroadcast_)
164  {
165  scratch.resize(nLocalFace);
166  }
167 
168  // Read data and send to sub-ranks
169  forAll(times_, timei)
170  {
171  const label fileTimeIndex = timei + startTimeIndex_;
172 
173  if (Pstream::master())
174  {
175  Info<< " time: " << times_[timei] << endl;
176 
177  // Read pressure at all faces for time timeI
178  allData = readerPtr_->field(fileTimeIndex, pIndex_, scalar(0));
179  }
180 
181  if (useBroadcast_)
182  {
183  Pstream::broadcast(allData);
184  }
185  else
186  {
187  procFaceAddr.scatter
188  (
189  allData,
190  scratch,
192  commType_,
194  );
195  }
196 
197  scalarField::subField procData =
198  (
200  ? allData.slice(procFaceAddr.range())
201  : scratch.slice(0, nLocalFace)
202  );
203 
204  // Apply conversions
205  procData *= rhoRef_;
206 
207  // Transcribe this time snapshot (transpose)
208  forAll(procData, facei)
209  {
210  pData[facei][timei] = procData[facei];
211  }
212  }
213  }
214  else
215  {
216  // Read data - no sub-ranks
217  forAll(times_, timei)
218  {
219  const label fileTimeIndex = timei + startTimeIndex_;
220 
221  Info<< " time: " << times_[timei] << endl;
222 
223  allData = readerPtr_->field(fileTimeIndex, pIndex_, scalar(0));
224 
225  auto& procData = allData;
226 
227  // Apply conversions
228  procData *= rhoRef_;
229 
230  // Transcribe this time snapshot (transpose)
231  forAll(procData, facei)
232  {
233  pData[facei][timei] = procData[facei];
234  }
235  }
236  }
237 
238  forAll(pData, facei)
239  {
240  pData[facei] -= average(pData[facei]);
241  }
242 
243 
244  Info<< "Read "
245  << returnReduce(pData.size(), sumOp<label>())
246  << " pressure traces with "
247  << times_.size()
248  << " time values" << nl << endl;
249 }
250 
251 
253 (
254  const scalarField& data,
255  const globalIndex& procFaceAddr
256 ) const
257 {
258  if (!nFaces_)
259  {
260  // Already reduced, can use as sanity check
261  return 0;
262  }
263 
264  scalar areaAverage = 0;
265 
266  if (areaAverage_)
267  {
268  if (Pstream::parRun())
269  {
270  // Collect the surface data so that we can output the surfaces
271  scalarField allData;
272 
273  procFaceAddr.gather
274  (
275  data,
276  allData,
278  commType_,
280  );
281 
282  if (Pstream::master())
283  {
284  // Note: hard-coded to read mesh from first time index
285  const meshedSurface& surf = readerPtr_->geometry(0);
286 
287  areaAverage = sum(allData*surf.magSf())/sum(surf.magSf());
288  }
289  }
290  else
291  {
292  // Note: hard-coded to read mesh from first time index
293  const meshedSurface& surf = readerPtr_->geometry(0);
294 
295  areaAverage = sum(data*surf.magSf())/sum(surf.magSf());
296  }
297 
298  Pstream::broadcast(areaAverage);
299  }
300  else
301  {
302  // Ensemble averaged
303  // - same as gAverage, but already know number of faces
304 
305  areaAverage = sum(data);
306  reduce(areaAverage, sumOp<scalar>());
307 
308  areaAverage /= (scalar(nFaces_) + ROOTVSMALL);
309  }
310 
311  return areaAverage;
312 }
313 
314 
316 (
317  const fileName& outDirBase,
318  const word& fName,
319  const word& title,
320  const scalar freq,
321  const scalarField& data,
322  const globalIndex& procFaceAddr,
323  const bool writeSurface
324 ) const
325 {
326  Info<< " processing " << title << " for frequency " << freq << endl;
327 
328  const instant freqInst(freq, Foam::name(freq));
329 
330  if (!writeSurface)
331  {
332  return surfaceAverage(data, procFaceAddr);
333  }
334 
335  scalar areaAverage = 0;
336 
337  if (Pstream::parRun())
338  {
339  // Collect the surface data so that we can output the surfaces
340  scalarField allData;
341 
342  procFaceAddr.gather
343  (
344  data,
345  allData,
347  commType_,
349  );
350 
351  if (Pstream::master())
352  {
353  // Note: hard-coded to read mesh from first time index
354  const meshedSurface& surf = readerPtr_->geometry(0);
355 
356  if (areaAverage_)
357  {
358  areaAverage = sum(allData*surf.magSf())/sum(surf.magSf());
359  }
360  else
361  {
362  areaAverage = sum(allData)/(allData.size() + ROOTVSMALL);
363  }
364 
365  // (writeSurface == true)
366  {
367  // Time-aware, with time spliced into the output path
368  writerPtr_->beginTime(freqInst);
369 
370  writerPtr_->open
371  (
372  surf.points(),
373  surf.surfFaces(),
374  (outDirBase / fName),
375  false // serial - already merged
376  );
377 
378  writerPtr_->nFields(1); // Legacy VTK
379  writerPtr_->write(title, allData);
380 
381  writerPtr_->endTime();
382  writerPtr_->clear();
383  }
384  }
385  }
386  else
387  {
388  // Note: hard-coded to read mesh from first time index
389  const meshedSurface& surf = readerPtr_->geometry(0);
390 
391  if (areaAverage_)
392  {
393  areaAverage = sum(data*surf.magSf())/sum(surf.magSf());
394  }
395  else
396  {
397  areaAverage = sum(data)/(data.size() + ROOTVSMALL);
398  }
399 
400  // (writeSurface == true)
401  {
402  // Time-aware, with time spliced into the output path
403  writerPtr_->beginTime(freqInst);
404 
405  writerPtr_->open
406  (
407  surf.points(),
408  surf.surfFaces(),
409  (outDirBase / fName),
410  false // serial - already merged
411  );
412 
413  writerPtr_->nFields(1); // Legacy VTK
414  writerPtr_->write(title, data);
415 
416  writerPtr_->endTime();
417  writerPtr_->clear();
418  }
419  }
420 
421  Pstream::broadcast(areaAverage);
422  return areaAverage;
423 }
424 
425 
426 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
427 
429 (
430  const dictionary& dict,
431  const objectRegistry& obr,
432  const word& name,
433  const bool readFields
434 )
435 :
436  noiseModel(dict, obr, name, false),
437  inputFileNames_(),
438  pName_("p"),
439  pIndex_(0),
440  times_(),
441  deltaT_(0),
442  startTimeIndex_(0),
443  nFaces_(0),
444  fftWriteInterval_(1),
445  areaAverage_(false),
446  useBroadcast_(false),
447  commType_(UPstream::commsTypes::scheduled),
448  readerType_(),
449  readerPtr_(nullptr),
450  writerPtr_(nullptr)
451 {
452  if (readFields)
453  {
455  }
456 }
457 
458 
459 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
460 
462 {
463  if (noiseModel::read(dict))
464  {
465  if (!dict.readIfPresent("files", inputFileNames_))
466  {
468  dict.readEntry("file", inputFileNames_.first());
469  }
470 
471  dict.readIfPresent("p", pName_);
472  dict.readIfPresent("fftWriteInterval", fftWriteInterval_);
473 
474  Info<< this->type() << nl
475  << " Pressure field name: " << pName_ << nl
476  << " FFT write interval: " << fftWriteInterval_ << nl;
477 
478  dict.readIfPresent("areaAverage", areaAverage_);
479 
480  if (areaAverage_)
481  {
482  Info<< " Averaging: area weighted" << endl;
483  }
484  else
485  {
486  Info<< " Averaging: ensemble" << endl;
487  }
488 
489  useBroadcast_ = false;
490  dict.readIfPresent("broadcast", useBroadcast_);
492 
493  if (Pstream::parRun())
494  {
495  Info<< " Distribute fields: "
497 
498  if (useBroadcast_)
499  {
500  Info<< " (broadcast all)";
501  }
502  Info<< endl;
503  }
504 
505  readerType_ = dict.get<word>("reader");
506 
507  // Surface writer (keywords: writer, writeOptions)
508 
509  const word writerType = dict.get<word>("writer");
510 
512  (
513  writerType,
514  surfaceWriter::formatOptions(dict, writerType, "writeOptions")
515  );
516 
517  // Use outputDir/TIME/surface-name
518  writerPtr_->useTimeDir(true);
519 
520  Info<< endl;
521 
522  return true;
523  }
524 
525  return false;
526 }
527 
528 
530 {
531  forAll(inputFileNames_, filei)
532  {
533  fileName fName = inputFileNames_[filei];
534  fName.expand();
535 
536  if (!fName.isAbsolute())
537  {
538  fName = argList::envGlobalPath()/fName;
539  }
540 
541  initialise(fName);
542 
543  // Processor face addressing
544  globalIndex procFaceAddr;
545 
546  if (Pstream::parRun())
547  {
548  // Calculate face/proc offsets manually
549  labelList procFaceOffsets(Pstream::nProcs() + 1);
550  const label nFacePerProc = floor(nFaces_/Pstream::nProcs()) + 1;
551 
552  procFaceOffsets[0] = 0;
553  for (label proci = 1; proci < procFaceOffsets.size(); ++proci)
554  {
555  procFaceOffsets[proci] = min(proci*nFacePerProc, nFaces_);
556  }
557 
558  procFaceAddr.offsets() = std::move(procFaceOffsets);
559 
560  // Don't need to broadcast. Already identical on all ranks
561  }
562  else
563  {
564  // Local data only
565  procFaceAddr.reset(globalIndex::gatherNone{}, nFaces_);
566  }
567 
568  // Pressure time history data per face
569  List<scalarField> pData;
570 
571  // Read pressure data from file
572  readSurfaceData(procFaceAddr, pData);
573 
574  // Process the pressure data, and store results as surface values per
575  // frequency so that it can be output using the surface writer
576 
577  Info<< "Creating noise FFTs" << endl;
578 
579  const scalarField freq1(uniformFrequencies(deltaT_, true));
580 
581  const scalar maxFreq1 = max(freq1);
582 
583  // Reset desired frequency range if outside actual frequency range
584  fLower_ = min(fLower_, maxFreq1);
585  fUpper_ = min(fUpper_, maxFreq1);
586 
587  // Storage for FFT data
588  const label nLocalFace = pData.size();
589  const label nFFT = ceil(freq1.size()/scalar(fftWriteInterval_));
590 
591  List<scalarField> surfPrmsf(nFFT);
592  List<scalarField> surfPSDf(nFFT);
593  forAll(surfPrmsf, freqI)
594  {
595  surfPrmsf[freqI].setSize(nLocalFace);
596  surfPSDf[freqI].setSize(nLocalFace);
597  }
598 
599  // Storage for 1/3 octave data
600  labelList octave13BandIDs;
601  scalarField octave13FreqCentre;
603  (
604  freq1,
605  fLower_,
606  fUpper_,
607  3,
608  octave13BandIDs,
609  octave13FreqCentre
610  );
611 
612  label bandSize = 0;
613  if (octave13BandIDs.empty())
614  {
616  << "Octave band calculation failed (zero sized). "
617  << "Please check your input data"
618  << endl;
619  }
620  else
621  {
622  bandSize = octave13BandIDs.size() - 1;
623  }
624 
625  List<scalarField> surfPrms13f(bandSize);
626  forAll(surfPrms13f, freqI)
627  {
628  surfPrms13f[freqI].setSize(nLocalFace);
629  }
630 
631  const windowModel& win = windowModelPtr_();
632 
633  {
634  forAll(pData, faceI)
635  {
636  const scalarField& p = pData[faceI];
637 
638  // Generate the FFT-based data
639  const scalarField Prmsf(RMSmeanPf(p));
640  const scalarField PSDf(this->PSDf(p, deltaT_));
641 
642  // Store the frequency results in slot for face of surface
643  forAll(surfPrmsf, i)
644  {
645  label freqI = i*fftWriteInterval_;
646  surfPrmsf[i][faceI] = Prmsf[freqI];
647  surfPSDf[i][faceI] = PSDf[freqI];
648  }
649 
650  // Integrated PSD = P(rms)^2 [Pa^2]
651  const scalarField Prms13f
652  (
653  octaves
654  (
655  PSDf,
656  freq1,
657  octave13BandIDs
658  )
659  );
660 
661  // Store the 1/3 octave results in slot for face of surface
662  forAll(surfPrms13f, freqI)
663  {
664  surfPrms13f[freqI][faceI] = Prms13f[freqI];
665  }
666  }
667  }
668 
669  const word fNameBase = fName.stem();
670 
671  // Output directory
672  fileName outDirBase(baseFileDir(filei)/fNameBase);
673 
674  const scalar deltaf = 1.0/(deltaT_*win.nSamples());
675  Info<< "Writing fft surface data";
676  if (fftWriteInterval_ == 1)
677  {
678  Info<< endl;
679  }
680  else
681  {
682  Info<< " at every " << fftWriteInterval_ << " frequency points"
683  << endl;
684  }
685 
686  // Common output information
687  // Note: hard-coded to read mesh from first time index
688  scalar surfArea = 0;
689  label surfSize = 0;
690  if (Pstream::master())
691  {
692  const meshedSurface& surf = readerPtr_->geometry(0);
693  surfArea = sum(surf.magSf());
694  surfSize = surf.size();
695  }
697  (
699  surfArea,
700  surfSize
701  );
702 
703  List<Tuple2<string, token>> commonInfo
704  ({
705  {"Area average", token(word(Switch::name(areaAverage_)))},
706  {"Area sum", token(surfArea)},
707  {"Number of faces", token(surfSize)}
708  });
709 
710  {
711  fileName outDir(outDirBase/"fft");
712  fileName outSurfDir(filePath(outDir));
713 
714  // Determine frequency range of interest
715  // Note: frequencies have fixed interval, and are in the range
716  // 0 to fftWriteInterval_*(n-1)*deltaf
717  label f0 = ceil(fLower_/deltaf/scalar(fftWriteInterval_));
718  label f1 = floor(fUpper_/deltaf/scalar(fftWriteInterval_));
719  label nFreq = f1 - f0;
720 
721  scalarField PrmsfAve(nFreq, Zero);
722  scalarField PSDfAve(nFreq, Zero);
723  scalarField fOut(nFreq, Zero);
724 
725  if (nFreq == 0)
726  {
728  << "No surface data available using a fftWriteInterval of "
729  << fftWriteInterval_ << endl;
730  }
731  else
732  {
733  forAll(fOut, i)
734  {
735  label freqI = (i + f0)*fftWriteInterval_;
736  fOut[i] = freq1[freqI];
737 
738 
739  PrmsfAve[i] = writeSurfaceData
740  (
741  outSurfDir,
742  fNameBase,
743  "Prmsf",
744  freq1[freqI],
745  surfPrmsf[i + f0],
746  procFaceAddr,
748  );
749 
750  PSDfAve[i] = writeSurfaceData
751  (
752  outSurfDir,
753  fNameBase,
754  "PSDf",
755  freq1[freqI],
756  surfPSDf[i + f0],
757  procFaceAddr,
758  writePSDf_
759  );
761  (
762  outSurfDir,
763  fNameBase,
764  "PSD",
765  freq1[freqI],
766  PSD(surfPSDf[i + f0]),
767  procFaceAddr,
768  writePSD_
769  );
771  (
772  outSurfDir,
773  fNameBase,
774  "SPL",
775  freq1[freqI],
776  SPL(surfPSDf[i + f0]*deltaf, freq1[freqI]),
777  procFaceAddr,
778  writeSPL_
779  );
780  }
781  }
782 
783  if (Pstream::master())
784  {
785  {
786  auto filePtr = newFile(outDir/"Average_Prms_f");
787  auto& os = filePtr();
788 
789  Info<< " Writing " << os.relativeName() << endl;
790 
791  writeFileHeader(os, "f [Hz]", "P(f) [Pa]", commonInfo);
792  writeFreqDataToFile(os, fOut, PrmsfAve);
793  }
794  {
795  auto filePtr = newFile(outDir/"Average_PSD_f_f");
796  auto& os = filePtr();
797 
798  Info<< " Writing " << os.relativeName() << endl;
799 
801  (
802  os,
803  "f [Hz]",
804  "PSD(f) [PaPa_Hz]",
805  commonInfo
806  );
807  writeFreqDataToFile(os, fOut, PSDfAve);
808  }
809  {
810  auto filePtr = newFile(outDir/"Average_PSD_dB_Hz_f");
811  auto& os = filePtr();
812 
813  Info<< " Writing " << os.relativeName() << endl;
814 
816  (
817  os,
818  "f [Hz]",
819  "PSD(f) [dB_Hz]",
820  commonInfo
821  );
822  writeFreqDataToFile(os, fOut, PSD(PSDfAve));
823  }
824  {
825  auto filePtr = newFile(outDir/"Average_SPL_dB_f");
826  auto& os = filePtr();
827 
828  Info<< " Writing " << os.relativeName() << endl;
829 
831  (
832  os,
833  "f [Hz]",
834  "SPL(f) [dB]",
835  commonInfo
836  );
837  writeFreqDataToFile(os, fOut, SPL(PSDfAve*deltaf, fOut));
838  }
839  }
840  }
841 
842 
843  Info<< "Writing one-third octave surface data" << endl;
844  {
845  fileName outDir(outDirBase/"oneThirdOctave");
846  fileName outSurfDir(filePath(outDir));
847 
848  scalarField PSDfAve(surfPrms13f.size(), Zero);
849  scalarField Prms13fAve(surfPrms13f.size(), Zero);
850 
851  forAll(surfPrms13f, i)
852  {
854  (
855  outSurfDir,
856  fNameBase,
857  "SPL13",
858  octave13FreqCentre[i],
859  SPL(surfPrms13f[i], octave13FreqCentre[i]),
860  procFaceAddr,
862  );
863 
864  Prms13fAve[i] =
865  surfaceAverage(surfPrms13f[i], procFaceAddr);
866  }
867 
868  if (Pstream::master())
869  {
870  auto filePtr = newFile(outDir/"Average_SPL13_dB_fm");
871  auto& os = filePtr();
872 
873  Info<< " Writing " << os.relativeName() << endl;
874 
876  (
877  os,
878  "fm [Hz]",
879  "SPL(fm) [dB]",
880  commonInfo
881  );
883  (
884  os,
885  octave13FreqCentre,
886  SPL(Prms13fAve, octave13FreqCentre)
887  );
888  }
889  }
890  }
891 }
892 
893 
894 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
895 
896 } // End namespace noiseModels
897 } // End namespace Foam
898 
899 // ************************************************************************* //
label nFaces_
Global number of surface faces.
Definition: surfaceNoise.H:192
virtual void calculate()
Calculate.
Definition: surfaceNoise.C:522
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
A class for handling file names.
Definition: fileName.H:71
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:76
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:132
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:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
autoPtr< windowModel > windowModelPtr_
Window model.
Definition: noiseModel.H:249
bool writeOctaves_
Write writeOctaves; default = yes.
Definition: noiseModel.H:305
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:49
scalar surfaceAverage(const scalarField &data, const globalIndex &procFaceAddr) const
Calculate the area average value.
Definition: surfaceNoise.C:246
surfaceNoise(const dictionary &dict, const objectRegistry &obr, const word &name=typeName, const bool readFields=true)
Constructor.
Definition: surfaceNoise.C:422
T & first()
Access first element of the list, position [0].
Definition: UList.H:798
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
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:80
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:139
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:806
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
Default world communicator (all processors). May differ from globalComm if local worlds are in use...
Definition: UPstream.H:361
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:285
static std::string stem(const std::string &str)
Return the basename, without extension.
Definition: fileName.C:389
Macros for easy insertion into run-time selection tables.
labelRange range() const
Return start/size range of local processor data.
Definition: globalIndexI.H:250
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
word pName_
Name of pressure field.
Definition: surfaceNoise.H:167
scalar startTime_
Start time, default = 0s.
Definition: noiseModel.H:244
scalar rhoRef_
Reference density (to convert from kinematic to static pressure)
Definition: noiseModel.H:224
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
scalar fUpper_
Upper frequency limit, default = 10kHz.
Definition: noiseModel.H:239
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:752
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
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) is 1 for serial run.
Definition: UPstream.H:656
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:309
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: noiseModel.C:643
void setSize(const label n)
Alias for resize()
Definition: List.H:289
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
tmp< scalarField > octaves(const scalarField &data, const scalarField &f, const labelUList &freqBandIDs) const
Generate octave data.
Definition: noiseModel.C:327
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:245
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:461
List< fileName > inputFileNames_
Input file names.
Definition: surfaceNoise.H:162
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &df)
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:273
tmp< Foam::scalarField > PSD(const scalarField &PSDf) const
PSD [dB/Hz].
Definition: noiseModel.C:736
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: surfaceNoise.C:454
bool writeSPL_
Write SPL; default = yes.
Definition: noiseModel.H:290
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)
Database for solution data, solver performance and other reduced data.
Definition: data.H:51
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 processes in communicator.
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:590
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:300
void readSurfaceData(const globalIndex &procFaceAddr, List< scalarField > &pData)
Read surface data.
Definition: surfaceNoise.C:120
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
addToRunTimeSelectionTable(noiseModel, pointNoise, dictionary)
bool readIfPresent(const word &key, const dictionary &dict, EnumType &val) const
Find an entry if present, and assign to T val.
Definition: EnumI.H:125
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:745
messageStream Info
Information stream (stdout output on master, null elsewhere)
bool writePSD_
Write PSD; default = yes.
Definition: noiseModel.H:295
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]).
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const wordHashSet &selectedFields, LIFOStack< regIOobject *> &storedObjects)
Read the selected GeometricFields of the templated type.
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:290
Inter-processor communications stream.
Definition: UPstream.H:54
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:442
Namespace for OpenFOAM.
scalar fLower_
Lower frequency limit, default = 25Hz.
Definition: noiseModel.H:234
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.
label localSize() const
My local size.
Definition: globalIndexI.H:225
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157
Base class for noise models.
Definition: noiseModel.H:166