Nektar++
ProcessVortexInducedVelocity.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: ProcessVortexInducedVelocity.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: Computes velocity induced by vortex filaments.
32//
33////////////////////////////////////////////////////////////////////////////////
34
35#include <iostream>
36#include <string>
37using namespace std;
38
42#include <boost/core/ignore_unused.hpp>
43
44namespace Nektar::FieldUtils
45{
46
49 ModuleKey(eProcessModule, "vortexinducedvelocity"),
51 "Computes velocity induced by vortex filaments.");
52
54 : ProcessModule(f)
55{
56 m_config["vortex"] = ConfigOption(false, "vortexfilament.dat",
57 "vortex filaments infomation");
58 // format of vortexfilament.dat
59 // uniform background flow [3]: u, v, w
60 // vortex filament format [10] :
61 // start point (x, y, z, infinity 1/finite 0);
62 // end point (x, y, z, infinity 1/finite 0); sigma, circulation
63 // 0., 0.4,1.,1; 3., 0.4,1.,0; 0.1, 1.
64 // 3., 0.4,1.,0; 3.,-0.4,1.,0; 0.1, 1.
65 // 0.,-0.4,1.,1; 3.,-0.4,1.,0; 0.1, -1.
66 // 0, 0, 0
67}
68
70{
71}
72
73void ProcessVortexInducedVelocity::ParserDouble(const char *cstr, int n,
74 std::vector<NekDouble> &value)
75{
76 value.clear();
77 std::vector<int> digs;
78 std::vector<int> dige;
79 int i = 0;
80 int flag = 0; // digit chunk
81 while (i < n)
82 {
83 if ((cstr[i] >= '0' && cstr[i] <= '9') || cstr[i] == '.' ||
84 cstr[i] == 'e' || cstr[i] == 'E' || cstr[i] == '+' ||
85 cstr[i] == '-')
86 {
87 if (flag == 0)
88 {
89 digs.push_back(i);
90 }
91 flag = 1;
92 }
93 else
94 {
95 if (flag == 1)
96 {
97 dige.push_back(i);
98 }
99 flag = 0;
100 }
101 if (cstr[i] == 0)
102 {
103 break;
104 }
105 ++i;
106 }
107 for (int j = 0; j < digs.size(); ++j)
108 {
109 std::string cuts(cstr + digs[j], dige[j] - digs[j]);
110 value.push_back(std::stod(cuts));
111 }
112}
113
115{
117 {
118 return 0.;
119 }
120 else if (sigma < NekConstants::kNekZeroTol)
121 {
122 return 1. / (s * s);
123 }
124 else if (s < 1E-3 * sigma)
125 {
126 return 1. / (2. * sigma * sigma);
127 }
128 else
129 {
130 s = s * s;
131 return (1. - exp(-s / (2. * sigma * sigma))) / s;
132 }
133}
134
136{
137 m_f->SetUpExp(vm);
138
139 // Skip in case of empty partition
140 if (m_f->m_exp[0]->GetNumElmts() == 0)
141 {
142 return;
143 }
144 // read vortex filaments
145 string vorfile = m_config["vortex"].as<string>();
146 ifstream filament(vorfile.c_str());
147 ASSERTL0(filament.is_open(), "Unable to open file " + vorfile);
148 std::vector<NekDouble> Uniformflow(3, 0.);
149 char buffer[1000];
150 int count = 0;
151 int Nparam = 10;
152 while (!filament.eof())
153 {
154 filament.getline(buffer, sizeof(buffer));
155 std::vector<double> value;
156 ParserDouble(buffer, sizeof(buffer), value);
157 if (value.size() >= Nparam)
158 {
159 m_vortex.resize(count + 1);
160 m_vortex[count].resize(Nparam);
161 for (int i = 0; i < Nparam; ++i)
162 {
163 m_vortex[count][i] = value[i];
164 }
165 ++count;
166 }
167 else if (value.size() == 3)
168 {
169 Uniformflow = value;
170 }
171 }
172 filament.close();
173 // get coordinates
174 int Np = m_f->m_exp[0]->GetTotPoints();
177 for (int i = 0; i < 3; ++i)
178 {
179 coord[i] = Array<OneD, NekDouble>(Np);
180 vel[i] = Array<OneD, NekDouble>(Np, Uniformflow[i]);
181 }
182 m_f->m_exp[0]->GetCoords(coord[0], coord[1], coord[2]);
183 for (int v = 0; v < m_vortex.size(); ++v)
184 {
185 SpatialDomains::PointGeom pstart(3, 0, m_vortex[v][0], m_vortex[v][1],
186 m_vortex[v][2]);
187 SpatialDomains::PointGeom pend(3, 0, m_vortex[v][4], m_vortex[v][5],
188 m_vortex[v][6]);
190 e.Sub(pend, pstart);
191 NekDouble dist = sqrt(e.dot(e));
193 {
194 continue;
195 }
196 for (int i = 0; i < 3; ++i)
197 {
198 e[i] /= dist;
199 }
200 NekDouble sigma = std::fabs(m_vortex[v][8]);
201 NekDouble coeff = m_vortex[v][9] / (4. * M_PI);
202 for (int p = 0; p < Np; ++p)
203 {
204 SpatialDomains::PointGeom r(3, 0, coord[0][p], coord[1][p],
205 coord[2][p]);
206 SpatialDomains::PointGeom e_r, s_r, cross;
207 e_r.Sub(pend, r);
208 s_r.Sub(pstart, r);
209 cross.Mult(s_r, e);
210 NekDouble s = sqrt(cross.dot(cross));
212 {
213 continue;
214 }
215 NekDouble ls = -1., le = 1.;
216 if (m_vortex[v][3] < 0.5)
217 {
218 ls = e.dot(s_r) / s;
219 ls = ls / sqrt(ls * ls + 1.);
220 }
221 if (m_vortex[v][7] < 0.5)
222 {
223 le = e.dot(e_r) / s;
224 le = le / sqrt(le * le + 1.);
225 }
226 NekDouble velcoeff = coeff * Smooths(s, sigma) * (le - ls);
227 for (int i = 0; i < 3; ++i)
228 {
229 vel[i][p] += velcoeff * cross[i];
230 }
231 }
232 }
233 // add field
234 m_f->m_variables.resize(3);
235 vector<string> varsname = {"u", "v", "w"};
237 for (int n = 0; n < 3; ++n)
238 {
239 m_f->m_variables[n] = varsname[n];
240 if (n < m_f->m_exp.size())
241 {
242 Vmath::Vcopy(Np, vel[n], 1, m_f->m_exp[n]->UpdatePhys(), 1);
243 }
244 else
245 {
246 Exp = m_f->AppendExpList(m_f->m_numHomogeneousDir);
247 Vmath::Vcopy(Np, vel[n], 1, Exp->UpdatePhys(), 1);
248 m_f->m_exp.insert(m_f->m_exp.begin() + n, Exp);
249 }
250 m_f->m_exp[n]->FwdTransLocalElmt(vel[n], m_f->m_exp[n]->UpdateCoeffs());
251 }
252}
253} // namespace Nektar::FieldUtils
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
FieldSharedPtr m_f
Field object.
Definition: Module.h:239
std::map< std::string, ConfigOption > m_config
List of configuration values.
Definition: Module.h:272
Abstract base class for processing modules.
Definition: Module.h:301
static NekDouble Smooths(NekDouble s, NekDouble sigma)
void v_Process(po::variables_map &vm) override
Write mesh to output file.
static std::shared_ptr< Module > create(FieldSharedPtr f)
Creates an instance of this class.
static void ParserDouble(const char *cstr, int n, std::vector< NekDouble > &value)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
void Sub(PointGeom &a, PointGeom &b)
Definition: PointGeom.cpp:122
void Mult(PointGeom &a, PointGeom &b)
_this = a x b
Definition: PointGeom.cpp:131
NekDouble dot(PointGeom &a)
retun the dot product between this and input a
Definition: PointGeom.cpp:185
array buffer
Definition: GsLib.hpp:81
std::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:1026
std::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:180
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:47
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
static const NekDouble kNekZeroTol
double NekDouble
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825
STL namespace.
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294
Represents a command-line configuration option.
Definition: Module.h:129