Nektar++
Loading...
Searching...
No Matches
ProcessForceDecompose.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: ProcessForceDecompose.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: Perform force decomposition.
32//
33////////////////////////////////////////////////////////////////////////////////
34
35#include <iostream>
36#include <string>
37using namespace std;
38
40
42
43namespace Nektar::FieldUtils
44{
45
50
52{
53 return m_f->m_session->GetParameter("Kinvis");
54}
55
59{
60 int method = m_config["Q"].as<int>();
61 if (method == 1)
62 {
63 QFromPressure(exp, Q);
64 }
65 else
66 {
67 QFromField(exp, Q);
68 }
69}
70
74{
75 int npoints = m_f->m_exp[0]->GetNpoints();
76 int IQ = FindVariable("Q");
77 if (Q.size() < npoints)
78 {
79 Q = Array<OneD, NekDouble>(npoints);
80 }
81 Vmath::Vcopy(npoints, exp[IQ]->GetPhys(), 1, Q, 1);
82}
83
84int ProcessForceDecompose::FindVariable(const std::string &var)
85{
86 auto index = find(m_f->m_variables.begin(), m_f->m_variables.end(), var);
87 if (index == m_f->m_variables.end())
88 {
89 NEKERROR(ErrorUtil::efatal, var + " field not found.");
90 }
91 return index - m_f->m_variables.begin();
92}
93
97{
98 int npoints = exp[0]->GetNpoints();
99 int ip = FindVariable("p");
100 if (Q.size() < npoints)
101 {
102 Q = Array<OneD, NekDouble>(npoints);
103 }
104
106 Array<OneD, NekDouble> tmp(npoints, 0.);
107
108 for (int i = 0; i < m_spacedim; ++i)
109 {
110 grad[i] = Array<OneD, NekDouble>(npoints);
111 }
112 Vmath::Zero(npoints, Q, 1);
113
114 for (int i = 0; i < m_spacedim; ++i)
115 {
116 exp[ip]->PhysDeriv(i, m_f->m_exp[ip]->GetPhys(), grad[i]);
117 exp[ip]->PhysDeriv(i, grad[i], tmp);
118 Vmath::Vadd(npoints, tmp, 1, Q, 1, Q, 1);
119 }
120 Vmath::Smul(npoints, 0.5, Q, 1, Q, 1);
121}
122
125 Array<OneD, Array<OneD, NekDouble>> &phi, std::map<int, std::string> &Iphi)
126{
127 Iphi.clear();
128 int npoints = exp[0]->GetNpoints();
129 for (size_t i = 0; i < m_f->m_variables.size(); ++i)
130 {
131 if (std::string::npos != m_f->m_variables[i].find("phi"))
132 {
133 Iphi[i] = m_f->m_variables[i];
134 }
135 }
136 if (phi.size() != Iphi.size())
137 {
138 phi = Array<OneD, Array<OneD, NekDouble>>(Iphi.size());
139 }
140 int i = 0;
141 for (const auto &p : Iphi)
142 {
143 if (phi[i].size() < npoints)
144 {
145 phi[i] = Array<OneD, NekDouble>(npoints, 0.);
146 }
147 Vmath::Vcopy(npoints, exp[p.first]->GetPhys(), 1, phi[i], 1);
148 ++i;
149 }
150}
151
152void ProcessForceDecompose::GetInfoPhi(std::map<int, std::string> &Iphi)
153{
154 Iphi.clear();
155 for (size_t i = 0; i < m_f->m_variables.size(); ++i)
156 {
157 if (std::string::npos != m_f->m_variables[i].find("phi"))
158 {
159 Iphi[i] = m_f->m_variables[i];
160 }
161 }
162}
163
167{
168 int npoints = exp[0]->GetNpoints();
169 if (gradp.size() < m_spacedim)
170 {
172 }
173 for (size_t i = 0; i < gradp.size(); ++i)
174 {
175 if (gradp[i].size() < npoints)
176 {
177 gradp[i] = Array<OneD, NekDouble>(npoints, 0.);
178 }
179 }
180 int iv;
181 try
182 {
183 iv = FindVariable("p");
184 }
185 catch (...)
186 {
187 return;
188 }
189 Array<OneD, NekDouble> pressure(npoints, 0.);
190 Vmath::Vcopy(npoints, exp[iv]->GetPhys(), 1, pressure, 1);
191 for (int i = 0; i < m_spacedim; ++i)
192 {
193 exp[0]->PhysDeriv(i, pressure, gradp[i]);
194 }
195}
196
200{
201 int npoints = exp[0]->GetNpoints();
202 if (vel.size() < m_spacedim)
203 {
205 }
206 std::vector<std::string> vars = {"u", "v", "w"};
207 for (size_t i = 0; i < m_spacedim; ++i)
208 {
209 int iv = FindVariable(vars[i]);
210 if (vel[i].size() < npoints)
211 {
212 vel[i] = Array<OneD, NekDouble>(npoints);
213 }
214 Vmath::Vcopy(npoints, exp[iv]->GetPhys(), 1, vel[i], 1);
215 }
216}
217
221{
222 int npoints = exp[0]->GetNpoints();
224 GetVelocity(exp, vel);
226 Array<OneD, NekDouble> tmp(npoints);
227 for (size_t i = 0; i < grad.size(); ++i)
228 {
229 grad[i] = Array<OneD, NekDouble>(npoints);
230 }
231
232 if (stress.size() < m_spacedim * m_spacedim)
233 {
235 }
236
237 for (size_t i = 0; i < stress.size(); ++i)
238 {
239 if (stress[i].size() < npoints)
240 {
241 stress[i] = Array<OneD, NekDouble>(npoints);
242 }
243 }
244
245 for (int i = 0; i < m_spacedim; ++i)
246 {
247 for (int j = 0; j < m_spacedim; ++j)
248 {
249 exp[i]->PhysDeriv(j, vel[i], grad[i * m_spacedim + j]);
250 }
251 }
252
253 // Compute stress component terms
254 // tau_ij = mu*(u_i,j + u_j,i) + mu*lambda*delta_ij*div(u)
255 for (int i = 0; i < m_spacedim; ++i)
256 {
257 for (int j = i; j < m_spacedim; ++j)
258 {
259 Vmath::Vadd(npoints, grad[i * m_spacedim + j], 1,
260 grad[j * m_spacedim + i], 1, stress[i * m_spacedim + j],
261 1);
262
263 Vmath::Smul(npoints, GetViscosity(), stress[i * m_spacedim + j], 1,
264 stress[i * m_spacedim + j], 1);
265 }
266 }
267 for (int i = 0; i < m_spacedim; ++i)
268 {
269 for (int j = 0; j < i; ++j)
270 {
271 Vmath::Vcopy(npoints, stress[j * m_spacedim + i], 1,
272 stress[i * m_spacedim + j], 1);
273 }
274 }
275}
276
280{
281 int npoints = exp[0]->GetNpoints();
283 GetVelocity(exp, vel);
284 if (lapvel.size() != vel.size())
285 {
286 lapvel = Array<OneD, Array<OneD, NekDouble>>(vel.size());
287 }
288 for (size_t i = 0; i < lapvel.size(); ++i)
289 {
290 if (lapvel[i].size() < npoints)
291 {
292 lapvel[i] = Array<OneD, NekDouble>(npoints);
293 }
294 }
296 Array<OneD, NekDouble> tmp(npoints);
297 for (int i = 0; i < m_spacedim; ++i)
298 {
299 grad[i] = Array<OneD, NekDouble>(npoints);
300 }
301 for (size_t i = 0; i < lapvel.size(); ++i)
302 {
303 Vmath::Zero(npoints, lapvel[i], 1);
304 for (int j = 0; j < m_spacedim; ++j)
305 {
306 exp[i]->PhysDeriv(j, vel[i], grad[j]);
307 exp[i]->PhysDeriv(j, grad[j], tmp);
308 Vmath::Vadd(npoints, tmp, 1, lapvel[i], 1, lapvel[i], 1);
309 }
310 }
311}
312
315{
316 NekDouble sum = 0.;
317 for (int i = 0; i < exp->GetExpSize(); ++i)
318 {
319 sum += exp->GetExp(i)->Integral(value + exp->GetPhys_Offset(i));
320 }
321 return sum;
322}
323
326 const Array<OneD, Array<OneD, NekDouble>> &data,
327 const LibUtilities::CommSharedPtr &comm, std::map<int, std::string> &Iphi,
328 Array<OneD, NekDouble> &BoundBox, int dir)
329{
330 int Nslots = 100;
331 int ndata = data.size();
332 NekDouble dh = (BoundBox[dir * 2 + 1] - BoundBox[dir * 2]) / Nslots;
334 for (int i = 0; i < ndata; ++i)
335 {
336 slots[i] = Array<OneD, NekDouble>(Nslots, 0.);
337 }
338
339 for (size_t e = 0; e < field->GetExpSize(); ++e)
340 {
341 LocalRegions::ExpansionSharedPtr exp = field->GetExp(e);
342 SpatialDomains::Geometry *geom = exp->GetGeom();
343 int nv = geom->GetNumVerts();
344 NekDouble gc[3] = {0., 0., 0.};
345 NekDouble gct[3] = {0., 0., 0.};
346 bool inside = false;
347 for (size_t j = 0; j < nv; ++j)
348 {
349 SpatialDomains::PointGeom *vertex = geom->GetVertex(j);
350 vertex->GetCoords(gct[0], gct[1], gct[2]);
351 gc[0] += gct[0] / NekDouble(nv);
352 gc[1] += gct[1] / NekDouble(nv);
353 gc[2] += gct[2] / NekDouble(nv);
354 if (BoundBox[0] <= gct[0] && gct[0] <= BoundBox[1] &&
355 BoundBox[2] <= gct[1] && gct[1] <= BoundBox[3] &&
356 BoundBox[4] <= gct[2] && gct[2] <= BoundBox[5])
357 {
358 inside = true;
359 }
360 }
361 if (inside)
362 {
363 int index = floor((gc[dir] - BoundBox[2 * dir]) / dh);
364 index = std::max(std::min(index, Nslots - 1), 0);
365 for (int j = 0; j < ndata; ++j)
366 {
367 slots[j][index] +=
368 exp->Integral(data[j] + field->GetPhys_Offset(e));
369 }
370 }
371 }
372 for (int j = 0; j < ndata; ++j)
373 {
374 comm->AllReduce(slots[j], LibUtilities::ReduceSum);
375 }
376 if (comm->TreatAsRankZero())
377 {
378 Array<OneD, NekDouble> sum(ndata, 0.);
379 cout << "variables = x";
380 for (const auto &phi : Iphi)
381 {
382 cout << ", f" + phi.second;
383 }
384 cout << "\n";
385 for (int i = 0; i < Nslots; ++i)
386 {
387 cout << (BoundBox[2 * dir] + (i + 0.5) * dh) << " ";
388 for (int j = 0; j < ndata; ++j)
389 {
390 sum[j] += slots[j][i];
391 cout << sum[j] << " ";
392 }
393 cout << "\n";
394 }
395 cout << endl;
396 }
397}
398
399} // namespace Nektar::FieldUtils
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
FieldSharedPtr m_f
Field object.
Definition Module.h:239
std::map< std::string, ConfigOption > m_config
List of configuration values.
Definition Module.h:272
void QFromField(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, NekDouble > &Q)
void GetGradPressure(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, Array< OneD, NekDouble > > &gradp)
void GetLaplaceVelocity(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, Array< OneD, NekDouble > > &lapvel)
void GetQ(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, NekDouble > &Q)
void VolumeIntegrateForce(const MultiRegions::ExpListSharedPtr &field, const Array< OneD, Array< OneD, NekDouble > > &data, const LibUtilities::CommSharedPtr &comm, std::map< int, std::string > &Iphi, Array< OneD, NekDouble > &BoundBox, int dir)
NekDouble PhysIntegral(MultiRegions::ExpListSharedPtr exp, Array< OneD, NekDouble > value)
void GetInfoPhi(std::map< int, std::string > &Iphi)
void GetStressTensor(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, Array< OneD, NekDouble > > &shear)
void GetVelocity(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, Array< OneD, NekDouble > > &vel)
void QFromPressure(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, NekDouble > &Q)
void GetPhi(const Array< OneD, MultiRegions::ExpListSharedPtr > exp, Array< OneD, Array< OneD, NekDouble > > &phi, std::map< int, std::string > &Iphi)
Abstract base class for processing modules.
Definition Module.h:301
Base class for shape geometry information.
Definition Geometry.h:74
PointGeom * GetVertex(int i) const
Returns vertex i of this object.
Definition Geometry.h:361
int GetNumVerts() const
Get the number of vertices of this object.
Definition Geometry.h:403
void GetCoords(NekDouble &x, NekDouble &y, NekDouble &z)
Definition PointGeom.cpp:69
std::shared_ptr< Field > FieldSharedPtr
Definition Field.hpp:1026
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition Comm.h:55
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
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
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition Vmath.hpp:100
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
STL namespace.