Nektar++
ProcessCFL.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: ProcessCFL.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 CFL number over the entire domain for the
32// incompressible flow simulaiton. This is helpful in terms of debugging
33// and tracing the evolution of CFL in time over the domain.
34//
35////////////////////////////////////////////////////////////////////////////////
36
37#include <iostream>
38#include <string>
39using namespace std;
40
43
44#include "ProcessCFL.h"
45#include "ProcessMapping.h"
46
47namespace Nektar::FieldUtils
48{
49
52 "Computes CFL number for the entire domain for Incompressible flow.");
53
55{
56}
57
59{
60}
61
62void ProcessCFL::v_Process(po::variables_map &vm)
63{
64 m_f->SetUpExp(vm);
65
66 int expdim = m_f->m_graph->GetMeshDimension();
67 int nelmt = m_f->m_exp[0]->GetExpSize();
68 int nfields = m_f->m_variables.size();
69 m_spacedim = expdim;
70
71 NekDouble timeStep = m_f->m_session->GetParameter("TimeStep");
72 NekDouble cLambda = 0.2; // Spencer's book
73
74 if (m_f->m_numHomogeneousDir == 1)
75 {
76 m_spacedim = 3;
77 }
78 ASSERTL0(m_f->m_numHomogeneousDir != 2,
79 "CFL for 3DH2D simulations is not supported");
80 ASSERTL0(m_spacedim != 1, "Error: CFL for a 1D problem is not supported");
81
82 // Append field names
83 m_f->m_variables.push_back("CFL");
84
85 // Skip in case of empty partition
86 if (m_f->m_exp[0]->GetNumElmts() == 0)
87 {
88 return;
89 }
90 int npoints = m_f->m_exp[0]->GetNpoints();
91 Array<OneD, NekDouble> outfield(npoints);
92
93 int nstrips;
94 m_f->m_session->LoadParameter("Strip_Z", nstrips, 1);
95
97 // add in new fields
98 for (int s = 0; s < nstrips; ++s)
99 {
100 Exp = m_f->AppendExpList(m_f->m_numHomogeneousDir);
101 m_f->m_exp.insert(m_f->m_exp.begin() + s * (nfields + 1) + nfields,
102 Exp);
103 }
104
105 for (int s = 0; s < nstrips; ++s) // homogeneous strip varient
106 {
107 Array<OneD, Array<OneD, NekDouble>> velocityField(expdim);
108
109 // Get the velocity field
110 GetVelocity(velocityField, s);
111
112 // compute the max velocity in the std regions
113 Array<OneD, NekDouble> stdVel = GetMaxStdVelocity(velocityField);
114
115 // get the maximum expansion order in each element
116 Array<OneD, int> expOrder =
117 m_f->m_exp[s * nfields + 0]->EvalBasisNumModesMaxPerExp();
118
119 // compute the CFL number
120 Array<OneD, NekDouble> cfl(nelmt);
121 for (int el = 0; el < nelmt; ++el)
122 {
123 int order = std::max(expOrder[el] - 1, 1);
124 cfl[el] = timeStep * stdVel[el] * cLambda * order * order;
125 }
126
127 int cnt = 0;
128 for (int el = 0; el < nelmt; ++el)
129 {
130 // using the field[0]==m_exp[s*nfields + 0]
131 int nquad = m_f->m_exp[s * nfields + 0]->GetExp(el)->GetTotPoints();
132 Vmath::Fill(nquad, cfl[el], &outfield[cnt], 1);
133 cnt += nquad;
134 }
135
136 // temporary store the CFL number field for each strip
137 Vmath::Vcopy(npoints, outfield, 1,
138 m_f->m_exp[s * (nfields + 1) + nfields]->UpdatePhys(), 1);
139 m_f->m_exp[0]->FwdTransLocalElmt(
140 outfield, m_f->m_exp[s * (nfields + 1) + nfields]->UpdateCoeffs());
141 }
142}
143
145 int strip)
146{
147 int expdim = m_f->m_graph->GetMeshDimension();
148 int nfields = m_f->m_variables.size();
149 int npoints = m_f->m_exp[0]->GetNpoints();
150 if (boost::iequals(m_f->m_variables[0], "u"))
151 {
152 // IncNavierStokesSolver
153 // Using expdim instead of spacedim
154 // This is because for 3DH1D, only a 2D plane will be considered
155 for (int i = 0; i < expdim; ++i)
156 {
157 vel[i] = Array<OneD, NekDouble>(npoints);
158 Vmath::Vcopy(npoints, m_f->m_exp[strip * nfields + i]->GetPhys(), 1,
159 vel[i], 1);
160 }
161 }
162 else if (boost::iequals(m_f->m_variables[0], "rho") &&
163 boost::iequals(m_f->m_variables[1], "rhou"))
164 {
165 // CompressibleFlowSolver
166 ASSERTL0(false, "CFL calculation is not supported for the compressible "
167 "flow simulations at the moment");
168 }
169 else
170 {
171 // Unknown
172 ASSERTL0(false, "Could not identify velocity for ProcessCFL");
173 }
174}
175
176/**
177 *
178 */
180 const Array<OneD, Array<OneD, NekDouble>> &vel, int strip)
181{
182 int nfields = m_f->m_variables.size();
183 int n_points_0 = m_f->m_exp[0]->GetExp(0)->GetTotPoints();
184 int n_element = m_f->m_exp[0]->GetExpSize();
185 int nvel = vel.size();
186 int cnt;
187
188 NekDouble pntVelocity;
189
190 // Getting the standard velocity vector
191 Array<OneD, Array<OneD, NekDouble>> stdVelocity(nvel);
193 Array<OneD, NekDouble> maxV(n_element, 0.0);
195
196 for (int i = 0; i < nvel; ++i)
197 {
198 stdVelocity[i] = Array<OneD, NekDouble>(n_points_0);
199 }
200
201 cnt = 0.0;
202 for (int el = 0; el < n_element; ++el)
203 {
204 int n_points = m_f->m_exp[0]->GetExp(el)->GetTotPoints();
205 ptsKeys = m_f->m_exp[0]->GetExp(el)->GetPointsKeys();
206
207 // reset local space
208 if (n_points != n_points_0)
209 {
210 for (int j = 0; j < nvel; ++j)
211 {
212 stdVelocity[j] = Array<OneD, NekDouble>(n_points, 0.0);
213 }
214 n_points_0 = n_points;
215 }
216 else
217 {
218 for (int j = 0; j < nvel; ++j)
219 {
220 Vmath::Zero(n_points, stdVelocity[j], 1);
221 }
222 }
223
224 Array<TwoD, const NekDouble> gmat = m_f->m_exp[strip * nfields + 0]
225 ->GetExp(el)
226 ->GetGeom()
227 ->GetMetricInfo()
228 ->GetDerivFactors(ptsKeys);
229
230 if (m_f->m_exp[strip * nfields + 0]
231 ->GetExp(el)
232 ->GetGeom()
233 ->GetMetricInfo()
234 ->GetGtype() == SpatialDomains::eDeformed)
235 {
236 for (int j = 0; j < nvel; ++j)
237 {
238 for (int k = 0; k < nvel; ++k)
239 {
240 Vmath::Vvtvp(n_points, gmat[k * nvel + j], 1,
241 tmp = vel[k] + cnt, 1, stdVelocity[j], 1,
242 stdVelocity[j], 1);
243 }
244 }
245 }
246 else
247 {
248 for (int j = 0; j < nvel; ++j)
249 {
250 for (int k = 0; k < nvel; ++k)
251 {
252 Vmath::Svtvp(n_points, gmat[k * nvel + j][0],
253 tmp = vel[k] + cnt, 1, stdVelocity[j], 1,
254 stdVelocity[j], 1);
255 }
256 }
257 }
258 cnt += n_points;
259
260 // Calculate total velocity in stdVelocity[0]
261 Vmath::Vmul(n_points, stdVelocity[0], 1, stdVelocity[0], 1,
262 stdVelocity[0], 1);
263 for (int k = 1; k < nvel; ++k)
264 {
265 Vmath::Vvtvp(n_points, stdVelocity[k], 1, stdVelocity[k], 1,
266 stdVelocity[0], 1, stdVelocity[0], 1);
267 }
268 pntVelocity = Vmath::Vmax(n_points, stdVelocity[0], 1);
269 maxV[el] = sqrt(pntVelocity);
270 }
271
272 return maxV;
273}
274} // namespace Nektar::FieldUtils
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
FieldSharedPtr m_f
Field object.
Definition: Module.h:239
void GetVelocity(Array< OneD, Array< OneD, NekDouble > > &vel, int strip=0)
Definition: ProcessCFL.cpp:144
Array< OneD, NekDouble > GetMaxStdVelocity(const Array< OneD, Array< OneD, NekDouble > > &vel, int strip=0)
Definition: ProcessCFL.cpp:179
static std::shared_ptr< Module > create(FieldSharedPtr f)
Creates an instance of this class.
Definition: ProcessCFL.h:50
static ModuleKey className
Definition: ProcessCFL.h:54
void v_Process(po::variables_map &vm) override
Write mesh to output file.
Definition: ProcessCFL.cpp:62
ProcessCFL(FieldSharedPtr f)
Definition: ProcessCFL.cpp:54
Abstract base class for processing modules.
Definition: Module.h:301
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
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::vector< PointsKey > PointsKeyVector
Definition: Points.h:231
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
@ eDeformed
Geometry is curved or has non-constant factors.
double NekDouble
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.hpp:72
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
Definition: Vmath.hpp:396
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.hpp:366
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.hpp:273
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.hpp:54
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.hpp:644
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