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
43namespace Nektar::FieldUtils
44{
45
48 ModuleKey(eProcessModule, "vortexinducedvelocity"),
50 "Computes velocity induced by vortex filaments.");
51
53 : ProcessModule(f)
54{
55 m_config["vortex"] = ConfigOption(false, "vortexfilament.dat",
56 "vortex filaments infomation");
57 // format of vortexfilament.dat
58 // uniform background flow [3]: u, v, w
59 // vortex filament format [10] :
60 // start point (x, y, z, infinity 1/finite 0);
61 // end point (x, y, z, infinity 1/finite 0); sigma, circulation
62 // 0., 0.4,1.,1; 3., 0.4,1.,0; 0.1, 1.
63 // 3., 0.4,1.,0; 3.,-0.4,1.,0; 0.1, 1.
64 // 0.,-0.4,1.,1; 3.,-0.4,1.,0; 0.1, -1.
65 // 0, 0, 0
66}
67
69{
70}
71
72void ProcessVortexInducedVelocity::ParserDouble(const char *cstr, int n,
73 std::vector<NekDouble> &value)
74{
75 value.clear();
76 std::vector<int> digs;
77 std::vector<int> dige;
78 int i = 0;
79 int flag = 0; // digit chunk
80 while (i < n)
81 {
82 if ((cstr[i] >= '0' && cstr[i] <= '9') || cstr[i] == '.' ||
83 cstr[i] == 'e' || cstr[i] == 'E' || cstr[i] == '+' ||
84 cstr[i] == '-')
85 {
86 if (flag == 0)
87 {
88 digs.push_back(i);
89 }
90 flag = 1;
91 }
92 else
93 {
94 if (flag == 1)
95 {
96 dige.push_back(i);
97 }
98 flag = 0;
99 }
100 if (cstr[i] == 0)
101 {
102 break;
103 }
104 ++i;
105 }
106 for (int j = 0; j < digs.size(); ++j)
107 {
108 std::string cuts(cstr + digs[j], dige[j] - digs[j]);
109 value.push_back(std::stod(cuts));
110 }
111}
112
114{
116 {
117 return 0.;
118 }
119 else if (sigma < NekConstants::kNekZeroTol)
120 {
121 return 1. / (s * s);
122 }
123 else if (s < 1E-3 * sigma)
124 {
125 return 1. / (2. * sigma * sigma);
126 }
127 else
128 {
129 s = s * s;
130 return (1. - exp(-s / (2. * sigma * sigma))) / s;
131 }
132}
133
135{
136 m_f->SetUpExp(vm);
137
138 // Skip in case of empty partition
139 if (m_f->m_exp[0]->GetNumElmts() == 0)
140 {
141 return;
142 }
143 // read vortex filaments
144 string vorfile = m_config["vortex"].as<string>();
145 ifstream filament(vorfile.c_str());
146 ASSERTL0(filament.is_open(), "Unable to open file " + vorfile);
147 std::vector<NekDouble> Uniformflow(3, 0.);
148 char buffer[1000];
149 int count = 0;
150 int Nparam = 10;
151 while (!filament.eof())
152 {
153 filament.getline(buffer, sizeof(buffer));
154 std::vector<double> value;
155 ParserDouble(buffer, sizeof(buffer), value);
156 if (value.size() >= Nparam)
157 {
158 m_vortex.resize(count + 1);
159 m_vortex[count].resize(Nparam);
160 for (int i = 0; i < Nparam; ++i)
161 {
162 m_vortex[count][i] = value[i];
163 }
164 ++count;
165 }
166 else if (value.size() == 3)
167 {
168 Uniformflow = value;
169 }
170 }
171 filament.close();
172 // get coordinates
173 int Np = m_f->m_exp[0]->GetTotPoints();
176 for (int i = 0; i < 3; ++i)
177 {
178 coord[i] = Array<OneD, NekDouble>(Np);
179 vel[i] = Array<OneD, NekDouble>(Np, Uniformflow[i]);
180 }
181 m_f->m_exp[0]->GetCoords(coord[0], coord[1], coord[2]);
182 for (int v = 0; v < m_vortex.size(); ++v)
183 {
184 SpatialDomains::PointGeom pstart(3, 0, m_vortex[v][0], m_vortex[v][1],
185 m_vortex[v][2]);
186 SpatialDomains::PointGeom pend(3, 0, m_vortex[v][4], m_vortex[v][5],
187 m_vortex[v][6]);
189 e.Sub(pend, pstart);
190 NekDouble dist = sqrt(e.dot(e));
192 {
193 continue;
194 }
195 for (int i = 0; i < 3; ++i)
196 {
197 e[i] /= dist;
198 }
199 NekDouble sigma = std::fabs(m_vortex[v][8]);
200 NekDouble coeff = m_vortex[v][9] / (4. * M_PI);
201 for (int p = 0; p < Np; ++p)
202 {
203 SpatialDomains::PointGeom r(3, 0, coord[0][p], coord[1][p],
204 coord[2][p]);
205 SpatialDomains::PointGeom e_r, s_r, cross;
206 e_r.Sub(pend, r);
207 s_r.Sub(pstart, r);
208 cross.Mult(s_r, e);
209 NekDouble s = sqrt(cross.dot(cross));
211 {
212 continue;
213 }
214 NekDouble ls = -1., le = 1.;
215 if (m_vortex[v][3] < 0.5)
216 {
217 ls = e.dot(s_r) / s;
218 ls = ls / sqrt(ls * ls + 1.);
219 }
220 if (m_vortex[v][7] < 0.5)
221 {
222 le = e.dot(e_r) / s;
223 le = le / sqrt(le * le + 1.);
224 }
225 NekDouble velcoeff = coeff * Smooths(s, sigma) * (le - ls);
226 for (int i = 0; i < 3; ++i)
227 {
228 vel[i][p] += velcoeff * cross[i];
229 }
230 }
231 }
232 // add field
233 m_f->m_variables.resize(3);
234 vector<string> varsname = {"u", "v", "w"};
236 for (int n = 0; n < 3; ++n)
237 {
238 m_f->m_variables[n] = varsname[n];
239 if (n < m_f->m_exp.size())
240 {
241 Vmath::Vcopy(Np, vel[n], 1, m_f->m_exp[n]->UpdatePhys(), 1);
242 }
243 else
244 {
245 Exp = m_f->AppendExpList(m_f->m_numHomogeneousDir);
246 Vmath::Vcopy(Np, vel[n], 1, Exp->UpdatePhys(), 1);
247 m_f->m_exp.insert(m_f->m_exp.begin() + n, Exp);
248 }
249 m_f->m_exp[n]->FwdTransLocalElmt(vel[n], m_f->m_exp[n]->UpdateCoeffs());
250 }
251}
252} // 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:119
void Mult(PointGeom &a, PointGeom &b)
_this = a x b
Definition: PointGeom.cpp:128
NekDouble dot(PointGeom &a)
retun the dot product between this and input a
Definition: PointGeom.cpp:182
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:285
Represents a command-line configuration option.
Definition: Module.h:129