Nektar++
ForcingCFSSyntheticEddy.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: ForcingCFSSyntheticEddy.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Derived base class - Synthetic turbulence forcing for the
32// Compressible solver.
33//
34///////////////////////////////////////////////////////////////////////////////
35
37
38namespace Nektar::SolverUtils
39{
40
43 "CFSSyntheticTurbulence", ForcingCFSSyntheticEddy::create,
44 "Compressible Synthetic Eddy Turbulence Forcing (Generation)");
45
48 const std::weak_ptr<EquationSystem> &pEquation)
49 : Forcing(pSession, pEquation), ForcingSyntheticEddy(pSession, pEquation)
50{
51}
52
53/**
54 * @brief Apply forcing term if an eddy left the box of eddies and
55 * update the eddies positions.
56 *
57 * @param pFields Pointer to fields.
58 * @param inarray Given fields. The fields are in in physical space.
59 * @param outarray Calculated solution after forcing term being applied
60 * in physical space.
61 * @param time time.
62 */
65 [[maybe_unused]] const Array<OneD, Array<OneD, NekDouble>> &inarray,
67 [[maybe_unused]] const NekDouble &time)
68{
69 // Number of Variables
70 int nVars = pFields.size();
71 // Total number of coefficients
72 unsigned int nqTot = pFields[0]->GetTotPoints();
73
74 // Only calculates the forcing in the first time step and when an eddy
75 // leaves the synthetic eddy region (box).
76 if (m_calcForcing)
77 {
78 CalculateForcing(pFields);
79 m_calcForcing = false;
80 }
81
82 for (size_t i = 0; i < nVars; ++i)
83 {
84 Vmath::Vadd(nqTot, m_Forcing[i], 1, outarray[i], 1, outarray[i], 1);
85 }
86
87 // Update eddies position inside the box.
89}
90
91/**
92 * @brief Apply forcing term if an eddy left the box of eddies and
93 * update the eddies positions.
94 *
95 * @param pFields Pointer to fields.
96 * @param inarray Given fields. The fields are in in physical space.
97 * @param outarray Calculated solution after forcing term being applied
98 * in coeficient space.
99 * @param time time.
100 */
103 [[maybe_unused]] const Array<OneD, Array<OneD, NekDouble>> &inarray,
104 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble &time)
105{
106 // Number of Variables
107 int nVars = fields.size();
108 // Total number of coefficients
109 unsigned int nCoeff = fields[0]->GetNcoeffs();
110
111 // Only calculates the forcing in the first time step and when an eddy
112 // leaves the box
113 if (m_calcForcing)
114 {
115 CalculateForcing(fields);
116 m_calcForcing = false;
117 }
118
119 Array<OneD, NekDouble> forcingCoeff(nCoeff);
120 for (size_t i = 0; i < nVars; ++i)
121 {
122 fields[i]->FwdTrans(m_Forcing[i], forcingCoeff);
123 Vmath::Vadd(nCoeff, forcingCoeff, 1, outarray[i], 1, outarray[i], 1);
124 }
125
126 // Check for update: implicit solver
127 if (m_currTime != time)
128 {
130 m_currTime = time;
131 }
132}
133
134/**
135 * @brief Calculate forcing term.
136 *
137 * @param pFfields Pointer to fields.
138 */
141{
142 // Total number of quadrature points
143 int nqTot = pFields[0]->GetTotPoints();
144 // Number of Variables
145 int nVars = pFields.size();
146 // Define parameters
147 Array<OneD, NekDouble> rho(nqTot), temperature(nqTot), pressure(nqTot);
148 // Velocity fluctuation module
149 NekDouble velFlucMod;
150 // Variable converter
152 m_spacedim);
153
154 // Compute Stochastic Signal
155 Array<OneD, Array<OneD, NekDouble>> stochasticSignal;
156 stochasticSignal = ComputeStochasticSignal(pFields);
157
158 // Compute rho and mach mean inside the box of eddies
159 std::pair<NekDouble, NekDouble> rhoMachMean;
160 rhoMachMean = ComputeRhoMachMean(pFields);
161
162 // Compute velocity fluctuation
164 velFluc = ComputeVelocityFluctuation(pFields, stochasticSignal);
165
166 // Compute density fluctuation
168 rhoFluc = ComputeDensityFluctuation(pFields, velFluc, rhoMachMean);
169
170 // Compute characteristic convective turbulent time
172 convTurbTime = ComputeCharConvTurbTime(pFields);
173
174 // Compute smoothing factor
176 smoothFac = ComputeSmoothingFactor(pFields, convTurbTime);
177
178 // Get physical data
179 Array<OneD, Array<OneD, NekDouble>> physFields(nVars);
180 for (size_t i = 0; i < nVars; ++i)
181 {
182 physFields[i] = pFields[i]->GetPhys();
183 }
184
185 // Calculate parameters
186 m_varConv->GetTemperature(physFields, temperature);
187 m_varConv->GetPressure(physFields, pressure);
188 m_varConv->GetRhoFromPT(pressure, temperature, rho);
189
190 // Check if eddies left the box (reinjected). Note that the member
191 // m_eddiesIDForcing is populate with the eddies that left the box.
192 // If any left it is going to be empty.
193 if (!m_eddiesIDForcing.empty())
194 {
195 // Forcing must stop applying for eddies that left the box
197
198 // Update Forcing term which are going to be applied until
199 // the eddy leave the leave the domain
200 // Select the eddies to apply the forcing. Superposition.
201 for (auto &n : m_eddiesIDForcing)
202 {
203 for (size_t i = 0; i < nqTot; ++i)
204 {
205 if (m_mask[i])
206 {
207 // density term
208 m_ForcingEddy[n][0][i] =
209 (rhoFluc[n][i] * smoothFac[0][i]) / convTurbTime[0][i];
210 // Update forcing
211 m_Forcing[0][i] += m_ForcingEddy[n][0][i];
212 // velocity term
213 for (size_t j = 0; j < m_spacedim; ++j)
214 {
215 m_ForcingEddy[n][j + 1][i] =
216 (rho[i] * velFluc[n][j * nqTot + i] *
217 smoothFac[j][i]) /
218 convTurbTime[j][i];
219 // Update forcing
220 m_Forcing[j + 1][i] += m_ForcingEddy[n][j + 1][i];
221 }
222 // energy term
223 velFlucMod =
224 velFluc[n][i] * velFluc[n][i] +
225 velFluc[n][nqTot + i] * velFluc[n][nqTot + i] +
226 velFluc[n][2 * nqTot + i] * velFluc[n][2 * nqTot + i];
227
228 m_ForcingEddy[n][nVars - 1][i] =
229 (0.5 * rho[i] * velFlucMod * smoothFac[0][i]) /
230 convTurbTime[0][i];
231 // Update forcing
232 m_Forcing[nVars - 1][i] += m_ForcingEddy[n][nVars - 1][i];
233 }
234 }
235 }
236 // delete eddies
238 m_eddiesIDForcing.end());
239 }
240 else
241 {
242 NEKERROR(ErrorUtil::efatal, "Failed: Eddies ID vector is empty.");
243 }
244}
245
246/**
247 * @brief Compute density fluctuation for the source term
248 *
249 * @param pFfields Pointer to fields.
250 */
254 const Array<OneD, Array<OneD, NekDouble>> &velFluc,
255 std::pair<NekDouble, NekDouble> rhoMachMean)
256{
257 // Total number of quadrature points
258 int nqTot = pFields[0]->GetTotPoints();
259 // Density fluctuation
261
262 for (auto &n : m_eddiesIDForcing)
263 {
264 rhoFluc[n] = Array<OneD, NekDouble>(nqTot, 0.0);
265
266 for (size_t i = 0; i < nqTot; ++i)
267 {
268 if (m_mask[i])
269 {
270 // only need velocity fluctation in the x-direction
271 rhoFluc[n][i] = rhoMachMean.first * (m_gamma - 1) *
272 rhoMachMean.second * rhoMachMean.second *
273 (velFluc[n][i] / m_Ub);
274 }
275 }
276 }
277
278 return rhoFluc;
279}
280
281/**
282 * @brief Calculate the density and mach number mean
283 * inside the box of eddies.
284 *
285 * @param pFfields Pointer to fields.
286 * @return Pair with density and mach nember means.
287 */
288std::pair<NekDouble, NekDouble> ForcingCFSSyntheticEddy::ComputeRhoMachMean(
290{
291 // Total number of quadrature points
292 int nqTot = pFields[0]->GetTotPoints();
293 // Number of Variables
294 int nVars = pFields.size();
295 // <rho> and <mach>^{2}
296 NekDouble rhoMean = 0.0, machMean = 0.0;
297 // Counter for the mean
298 int count = 0;
299
300 // Get physical field
301 Array<OneD, Array<OneD, NekDouble>> physFields(nVars);
302 for (size_t i = 0; i < nVars; ++i)
303 {
304 physFields[i] = pFields[i]->GetPhys();
305 }
306
307 // Define parameters
308 Array<OneD, NekDouble> soundSpeed(nqTot), mach(nqTot), rho(nqTot),
309 temperature(nqTot), pressure(nqTot);
310 // Calculate parameters
311
312 m_varConv->GetTemperature(physFields, temperature);
313 m_varConv->GetPressure(physFields, pressure);
314 m_varConv->GetRhoFromPT(pressure, temperature, rho);
315 m_varConv->GetSoundSpeed(physFields, soundSpeed);
316 m_varConv->GetMach(physFields, soundSpeed, mach);
317
318 // Sum
319 for (size_t i = 0; i < nqTot; ++i)
320 {
321 if (m_mask[i])
322 {
323 rhoMean += rho[i];
324 machMean += mach[i];
325 count += 1;
326 }
327 }
328
329 // Density mean
330 rhoMean = rhoMean / count;
331 // Mach number mean
332 machMean = machMean / count;
333
334 return std::make_pair(rhoMean, machMean);
335}
336
337} // namespace Nektar::SolverUtils
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:202
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void v_ApplyCoeff(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble &time) override
Apply forcing term if an eddy left the box of eddies and update the eddies positions.
void CalculateForcing(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Calculate Forcing.
std::pair< NekDouble, NekDouble > ComputeRhoMachMean(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Compute rho and mach mean.
VariableConverterSharedPtr m_varConv
Auxiliary object to convert variables.
void v_Apply(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble &time) override
Apply forcing term if an eddy left the box of eddies and update the eddies positions.
ForcingCFSSyntheticEddy(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation)
Array< OneD, Array< OneD, NekDouble > > ComputeDensityFluctuation(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const Array< OneD, Array< OneD, NekDouble > > &velFLuc, std::pair< NekDouble, NekDouble > rhoMachMean)
Compute Velocity Fluctuation.
static ForcingSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields, const TiXmlElement *pForce)
Creates an instance of this class.
static std::string className
Name of the class.
Defines a forcing term to be explicitly applied.
Definition: Forcing.h:71
Array< OneD, Array< OneD, NekDouble > > m_Forcing
Evaluated forcing function.
Definition: Forcing.h:119
LibUtilities::SessionReaderSharedPtr m_session
Session reader.
Definition: Forcing.h:115
SOLVER_UTILS_EXPORT Array< OneD, Array< OneD, NekDouble > > ComputeSmoothingFactor(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, Array< OneD, NekDouble > > convTurb)
Compute Smoothing Factor.
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_ForcingEddy
Forcing for each eddy.
SOLVER_UTILS_EXPORT Array< OneD, Array< OneD, NekDouble > > ComputeStochasticSignal(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Compute Stochastic Signal.
SOLVER_UTILS_EXPORT Array< OneD, Array< OneD, NekDouble > > ComputeVelocityFluctuation(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, Array< OneD, NekDouble > > stochasticSignal)
Compute Velocity Fluctuation.
SOLVER_UTILS_EXPORT void UpdateEddiesPositions()
Update positions of the eddies inside the box.
std::vector< unsigned int > m_eddiesIDForcing
Eddies that add to the domain.
bool m_calcForcing
Check when the forcing should be applied.
SOLVER_UTILS_EXPORT void RemoveEddiesFromForcing(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Remove eddy from forcing term.
SOLVER_UTILS_EXPORT Array< OneD, Array< OneD, NekDouble > > ComputeCharConvTurbTime(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Compute Characteristic Convective Turbulent Time.
Array< OneD, int > m_mask
Box of eddies mask.
NekDouble m_gamma
Ration of specific heats.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
ForcingFactory & GetForcingFactory()
Declaration of the forcing factory singleton.
Definition: Forcing.cpp:42
double NekDouble
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.hpp:180