Skip to content

Commit 01eb182

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feature_StreamPer_massflow_PlzWörkDisTime
2 parents d510f0e + 1be5ed2 commit 01eb182

6 files changed

Lines changed: 157 additions & 78 deletions

File tree

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Brian Munguía
6161
Carsten Othmer
6262
Catarina Garbacz
6363
Charanya Venkatesan-Crome
64+
Christian Bauer
6465
Clark Pederson
6566
Daumantas Kavolis
6667
Dave Taflin

SU2_CFD/include/output/tools/CWindowingTools.hpp

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,22 @@ class CWindowingTools{
6868
class CWindowedAverage:CWindowingTools{
6969
private:
7070
su2double val = 0.0; /*!< \brief Value of the windowed-time average (of the instantaneous output) from starting time to the current time iteration. */
71+
su2double cachedSum = 0.0; /*!< \brief Cached sum of windowWeight*value over all previous iterations. */
7172
std::vector<su2double> values; /*!< \brief Vector of instantatneous output values from starting time to the current time iteration.*/
7273
unsigned long lastTimeIter = std::numeric_limits<unsigned long>::max();
74+
const WINDOW_FUNCTION windowingFunctionId; /*!< \brief ID of the windowing function to use.*/
75+
76+
public:
77+
78+
/*!
79+
* \brief Creates a new CWindowedAverage with the specified windowing function
80+
*/
81+
inline explicit CWindowedAverage(WINDOW_FUNCTION windowId) : windowingFunctionId(windowId) {
82+
if (windowId==WINDOW_FUNCTION::SQUARE) {
83+
values.push_back(0.);
84+
}
85+
}
7386

74-
public:
7587
/*!
7688
* \brief Returns the value of windowed-time average (of the instantaneous output) from starting time to the current time iteration
7789
*/
@@ -83,6 +95,7 @@ class CWindowedAverage:CWindowingTools{
8395
inline void Reset() {
8496
val = 0.0;
8597
values.clear();
98+
cachedSum = 0.0;
8699
lastTimeIter = std::numeric_limits<unsigned long>::max();
87100
}
88101

@@ -94,32 +107,10 @@ class CWindowedAverage:CWindowingTools{
94107
*/
95108
void addValue(su2double valIn, unsigned long curTimeIter,unsigned long startIter = 0);
96109

97-
/*!
98-
* \brief Computes a windowed-time average of the values stored in the vector "values" using the windowing-function specified in enum windowId
99-
* and stores it in "val".
100-
* \param windowId - specified windowing-function
101-
* \return windowed-time average of the values stored in the vector "values"
102-
*/
103-
su2double WindowedUpdate(WINDOW_FUNCTION windowId);
104-
105110
private:
106-
/*! \brief Computes a Square-windowed-time average of the values stored in the vector "values" with the Midpoint-integration rule (for consistency with the adjoint solver).
107-
* \return Squarewindowed-time average of the values stored in the vector "values"
108-
*/
109-
su2double NoWindowing() const;
110-
111-
/*! \brief Computes a Hann-windowed-time average of the values stored in the vector "values" with the Midpoint-integration rule (for consistency with the adjoint solver).
112-
* \return Squarewindowed-time average of the values stored in the vector "values"
113-
*/
114-
su2double HannWindowing() const;
115-
116-
/*! \brief Computes a Hann-Square-windowed-time average of the values stored in the vector "values" with the Midpoint-integration rule (for consistency with the adjoint solver).
117-
* \return Squarewindowed-time average of the values stored in the vector "values"
118-
*/
119-
su2double HannSquaredWindowing() const;
120-
121-
/*! \brief Computes a Bump-windowed-time average of the values stored in the vector "values" with the Midpoint-integration rule (for consistency with the adjoint solver).
122-
* \return Squarewindowed-time average of the values stored in the vector "values"
111+
/*!
112+
* \brief Caches the weighted sums from a previous time-step for later re-use
113+
* \param windowWidth - Total width of the window, over which the samples were weighted during the previous timestep
123114
*/
124-
su2double BumpWindowing() const;
115+
su2double UpdateCachedSum(unsigned long windowWidth) const;
125116
};

SU2_CFD/src/output/COutput.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,10 +1915,15 @@ void COutput::Postprocess_HistoryData(CConfig *config){
19151915

19161916
if (currentField.fieldType == HistoryFieldType::COEFFICIENT){
19171917
if (config->GetTime_Domain()){
1918-
windowedTimeAverages[historyOutput_List[iField]].addValue(currentField.value,config->GetTimeIter(), config->GetStartWindowIteration()); //Collecting Values for Windowing
1919-
SetHistoryOutputValue("TAVG_" + fieldIdentifier, windowedTimeAverages[fieldIdentifier].WindowedUpdate(config->GetKindWindow()));
1918+
auto it = windowedTimeAverages.find(fieldIdentifier);
1919+
if (it == windowedTimeAverages.end()) {
1920+
it = windowedTimeAverages.insert({fieldIdentifier, CWindowedAverage(config->GetKindWindow())}).first;
1921+
}
1922+
auto& timeAverage = it->second;
1923+
timeAverage.addValue(currentField.value,config->GetTimeIter(), config->GetStartWindowIteration()); //Collecting Values for Windowing
1924+
SetHistoryOutputValue("TAVG_" + fieldIdentifier, timeAverage.GetVal());
19201925
if (config->GetDirectDiff() != NO_DERIVATIVE) {
1921-
SetHistoryOutputValue("D_TAVG_" + fieldIdentifier, SU2_TYPE::GetDerivative(windowedTimeAverages[fieldIdentifier].GetVal()));
1926+
SetHistoryOutputValue("D_TAVG_" + fieldIdentifier, SU2_TYPE::GetDerivative(timeAverage.GetVal()));
19221927
}
19231928
}
19241929
if (config->GetDirectDiff() != NO_DERIVATIVE){

SU2_CFD/src/output/tools/CWindowingTools.cpp

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -67,59 +67,37 @@ su2double CWindowingTools::BumpWindow(unsigned long curTimeIter, unsigned long e
6767
}
6868

6969
void CWindowedAverage::addValue(su2double valIn, unsigned long curTimeIter,unsigned long startIter){
70-
if (curTimeIter < startIter) return;
71-
if (curTimeIter != lastTimeIter) {
72-
lastTimeIter = curTimeIter;
73-
values.push_back(valIn);
74-
}
75-
else values.back() = valIn;
76-
}
77-
78-
su2double CWindowedAverage::WindowedUpdate(WINDOW_FUNCTION windowId){
79-
if(values.size()>0){
80-
switch (windowId){
81-
case WINDOW_FUNCTION::HANN: val= HannWindowing(); return val;
82-
case WINDOW_FUNCTION::HANN_SQUARE: val= HannSquaredWindowing(); return val;
83-
case WINDOW_FUNCTION::BUMP: val= BumpWindowing(); return val;
84-
case WINDOW_FUNCTION::SQUARE: val= NoWindowing(); return val;
70+
if (curTimeIter < startIter) return; // Averaging not yet started.
71+
const unsigned long windowWidth = curTimeIter - startIter + 1; // Calculate total width of window for this iteration
72+
if (curTimeIter != lastTimeIter) { // Handle new timestep
73+
if (curTimeIter > startIter) { // Only update sum over previous timesteps, if there are any
74+
cachedSum = UpdateCachedSum(windowWidth-1); // Save weighted sum up to last time step for later use
75+
}
76+
lastTimeIter = curTimeIter; // New time iteration step, update iteration number.
77+
// Add new sample
78+
if (windowingFunctionId != WINDOW_FUNCTION::SQUARE) {
79+
values.push_back(valIn); // Add new sample to list for non-trivial windows
8580
}
8681
}
87-
return 0.0;
88-
}
89-
90-
/* Definitions below are according to the window definitions in the paper of
91-
* Krakos et al. : "Sensitivity analysis of limit cycle oscillations"
92-
* by Krakos, J. A. and Wang, Q. and Hall, S. R. and Darmfoal, D. L..
93-
*/
94-
su2double CWindowedAverage::NoWindowing() const {
95-
su2double wnd_timeAvg = 0.0;
96-
for(unsigned long curTimeIter=0; curTimeIter<values.size(); curTimeIter++){
97-
wnd_timeAvg+=values[curTimeIter];
82+
else { // We are within the same timestep. Update the last sample
83+
values.back() = valIn;
9884
}
99-
return wnd_timeAvg/static_cast<su2double>(values.size());
85+
// Update the windowed-average from the weighted sum of previous samples and the latest sample
86+
const su2double totalSum = cachedSum + valIn*GetWndWeight(windowingFunctionId, windowWidth-1, windowWidth-1);
87+
val = totalSum / static_cast<su2double>(windowWidth);
10088
}
10189

102-
su2double CWindowedAverage::HannWindowing() const {
103-
su2double wnd_timeAvg = 0.0;
104-
for(unsigned long curTimeIter=0; curTimeIter<values.size(); curTimeIter++){
105-
wnd_timeAvg+=values[curTimeIter]*HannWindow(curTimeIter,values.size()-1);
90+
su2double CWindowedAverage::UpdateCachedSum(unsigned long windowWidth) const {
91+
// Handle square window
92+
if (windowingFunctionId == WINDOW_FUNCTION::SQUARE) return val * static_cast<su2double>(windowWidth);
93+
// Handle non-trivial windows
94+
// At this point new samples are not yet added. Therefore: values.size()=windowWidth-1
95+
su2double weightedSum = 0.0;
96+
for (unsigned long curTimeIter = 0; curTimeIter < values.size(); curTimeIter++) {
97+
// integrate over all but the last timestep-bin
98+
weightedSum += values[curTimeIter] * GetWndWeight(windowingFunctionId, curTimeIter, windowWidth);
10699
}
107-
return wnd_timeAvg/static_cast<su2double>(values.size());
100+
return weightedSum;
108101
}
109102

110-
su2double CWindowedAverage::HannSquaredWindowing() const {
111-
su2double wnd_timeAvg = 0.0;
112-
for(unsigned long curTimeIter=0; curTimeIter<values.size(); curTimeIter++){
113-
wnd_timeAvg+=values[curTimeIter]*HannSquaredWindow(curTimeIter,values.size()-1);
114-
}
115-
return wnd_timeAvg/static_cast<su2double>(values.size());
116-
}
117-
118-
su2double CWindowedAverage::BumpWindowing() const {
119-
su2double wnd_timeAvg = 0.0;
120-
for(unsigned long curTimeIter=0; curTimeIter<values.size(); curTimeIter++){
121-
wnd_timeAvg+=values[curTimeIter]*BumpWindow(curTimeIter,values.size()-1);
122-
}
123-
return wnd_timeAvg/static_cast<su2double>(values.size());
124-
}
125103

UnitTests/SU2_CFD/windowing.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*!
2+
* \file windowing.cpp
3+
* \brief Unit tests for windowed time-averaging.
4+
* \author C. Bauer
5+
* \version 7.3.0 "Blackbird"
6+
*
7+
* SU2 Project Website: https://su2code.github.io
8+
*
9+
* The SU2 Project is maintained by the SU2 Foundation
10+
* (http://su2foundation.org)
11+
*
12+
* Copyright 2012-2022, SU2 Contributors (cf. AUTHORS.md)
13+
*
14+
* SU2 is free software; you can redistribute it and/or
15+
* modify it under the terms of the GNU Lesser General Public
16+
* License as published by the Free Software Foundation; either
17+
* version 2.1 of the License, or (at your option) any later version.
18+
*
19+
* SU2 is distributed in the hope that it will be useful,
20+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22+
* Lesser General Public License for more details.
23+
*
24+
* You should have received a copy of the GNU Lesser General Public
25+
* License along with SU2. If not, see <http://www.gnu.org/licenses/>.
26+
*/
27+
28+
#include "catch.hpp"
29+
#include "../../SU2_CFD/include/output/COutput.hpp"
30+
#include "../../SU2_CFD/include/output/tools/CWindowingTools.hpp"
31+
32+
/*!
33+
* \brief Wrapper class that provides reference values and methods for
34+
* averaging these over different windows.
35+
*/
36+
struct CWindowingTest {
37+
static constexpr size_t MAX_INNER_ITERATIONS = 5;
38+
39+
/*!
40+
* \brief Calculates sample value at the specified time-step. Simple SIN function.
41+
*/
42+
static su2double GetSampleAtIteration(unsigned long currentTimeStep) {
43+
return 0.5 * sin(0.1 * currentTimeStep + 2) + 1.;
44+
}
45+
46+
/*!
47+
* \brief Perform averaging over simulated inner and outer solver iterations.
48+
*/
49+
static su2double calcAverage(WINDOW_FUNCTION win, unsigned long nIterations, unsigned long startIteration) {
50+
CWindowedAverage avg{win}; // Create averaging object with the specified window.
51+
su2double previousSample = 0.;
52+
su2double currentSample = 0.;
53+
su2double input = 0.; // Value that is specified as actual input to the addValue function.
54+
su2double weightPrevious = 0.;
55+
su2double weightCurrent = 0.;
56+
// Simulate solver time-steps
57+
for (size_t outerIteration = 0; outerIteration < nIterations; outerIteration++) {
58+
previousSample = currentSample;
59+
currentSample = GetSampleAtIteration(outerIteration);
60+
// Simulate inner iterations
61+
for (size_t innerIteration = 0; innerIteration < MAX_INNER_ITERATIONS; innerIteration++) {
62+
weightPrevious = static_cast<su2double>(MAX_INNER_ITERATIONS - innerIteration - 1);
63+
weightCurrent = innerIteration;
64+
// Simulate gradual change of sample during inner iterations.
65+
input = (weightPrevious * previousSample + weightCurrent * currentSample) / (weightCurrent + weightPrevious);
66+
avg.addValue(input, outerIteration, startIteration);
67+
}
68+
}
69+
return avg.GetVal();
70+
}
71+
};
72+
73+
TEST_CASE("BUMP", "[Windowing]") {
74+
su2double avg = 0;
75+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::BUMP, 10, 0);
76+
CHECK(avg == Approx(1.1851).epsilon(0.001));
77+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::BUMP, 100, 10);
78+
CHECK(avg == Approx(1.1883).epsilon(0.001));
79+
}
80+
81+
TEST_CASE("HANN", "[Windowing]") {
82+
su2double avg = 0;
83+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::HANN, 10, 0);
84+
CHECK(avg == Approx(1.1832).epsilon(0.001));
85+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::HANN, 100, 10);
86+
CHECK(avg == Approx(1.0869).epsilon(0.001));
87+
}
88+
89+
TEST_CASE("HANN_SQUARE", "[Windowing]") {
90+
su2double avg = 0;
91+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::HANN_SQUARE, 10, 0);
92+
CHECK(avg == Approx(1.1847).epsilon(0.001));
93+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::HANN_SQUARE, 100, 10);
94+
CHECK(avg == Approx(1.1856).epsilon(0.001));
95+
}
96+
97+
TEST_CASE("SQUARE", "[Windowing]") {
98+
su2double avg = 0;
99+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::SQUARE, 10, 0);
100+
CHECK(avg == Approx(1.3059).epsilon(0.001));
101+
avg = CWindowingTest::calcAverage(WINDOW_FUNCTION::SQUARE, 100, 10);
102+
CHECK(avg == Approx(0.9001).epsilon(0.001));
103+
}

UnitTests/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ su2_cfd_tests = files(['Common/geometry/primal_grid/CPrimalGrid_tests.cpp',
1212
'Common/vectorization.cpp',
1313
'Common/toolboxes/ndflattener_tests.cpp',
1414
'SU2_CFD/numerics/CNumerics_tests.cpp',
15-
'SU2_CFD/gradients.cpp'])
15+
'SU2_CFD/gradients.cpp',
16+
'SU2_CFD/windowing.cpp'])
1617

1718
# Reverse-mode (algorithmic differentiation) tests:
1819
su2_cfd_tests_ad = files(['Common/simple_ad_test.cpp'])

0 commit comments

Comments
 (0)