Nektar++
VCSMapping.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: VCSMapping.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: Velocity Correction Scheme w/ coordinate transformation
32// for the Incompressible Navier Stokes equations
33///////////////////////////////////////////////////////////////////////////////
34
38
39#include <boost/algorithm/string.hpp>
40
41using namespace std;
42
43namespace Nektar
44{
47 "VCSMapping", VCSMapping::create);
48
50 LibUtilities::SessionReader::RegisterEnumValue("SolverType", "VCSMapping",
52
53/**
54 * Constructor. Creates ...
55 *
56 * \param
57 * \param
58 */
61 : UnsteadySystem(pSession, pGraph),
62 VelocityCorrectionScheme(pSession, pGraph)
63{
64}
65
66void VCSMapping::v_InitObject(bool DeclareField)
67{
69
71 ASSERTL0(m_mapping, "Could not create mapping in VCSMapping.");
72
73 std::string vExtrapolation = "Mapping";
75 vExtrapolation, m_session, m_fields, m_pressure, m_velocity,
77 m_extrapolation->SubSteppingTimeIntegration(m_intScheme);
78 m_extrapolation->GenerateHOPBCMap(m_session);
79
80 // Storage to extrapolate pressure forcing
81 size_t physTot = m_fields[0]->GetTotPoints();
82 size_t intSteps = 1;
83
84 if (m_intScheme->GetName() == "IMEX" ||
85 m_intScheme->GetName() == "IMEXGear")
86 {
87 m_intSteps = m_intScheme->GetOrder();
88 }
89 else
90 {
92 "Integration method not suitable: "
93 "Options include IMEXGear or IMEXOrder{1,2,3,4}");
94 }
95
97 for (size_t i = 0; i < m_presForcingCorrection.size(); i++)
98 {
100 }
101 m_verbose = (m_session->DefinesCmdLineArgument("verbose")) ? true : false;
102
103 // Load solve parameters related to the mapping
104 // Flags determining if pressure/viscous terms should be treated implicitly
105 m_session->MatchSolverInfo("MappingImplicitPressure", "True",
106 m_implicitPressure, false);
107 m_session->MatchSolverInfo("MappingImplicitViscous", "True",
108 m_implicitViscous, false);
109 m_session->MatchSolverInfo("MappingNeglectViscous", "True",
110 m_neglectViscous, false);
111
113 {
114 m_implicitViscous = false;
115 }
116
117 // Tolerances and relaxation parameters for implicit terms
118 m_session->LoadParameter("MappingPressureTolerance", m_pressureTolerance,
119 1e-12);
120 m_session->LoadParameter("MappingViscousTolerance", m_viscousTolerance,
121 1e-12);
122 m_session->LoadParameter("MappingPressureRelaxation", m_pressureRelaxation,
123 1.0);
124 m_session->LoadParameter("MappingViscousRelaxation", m_viscousRelaxation,
125 1.0);
126}
127
128/**
129 * Destructor
130 */
132{
133}
134
135void VCSMapping::v_DoInitialise(bool dumpInitialConditions)
136{
137 UnsteadySystem::v_DoInitialise(dumpInitialConditions);
138
139 // Set up Field Meta Data for output files
140 m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
141 m_fieldMetaDataMap["TimeStep"] =
142 boost::lexical_cast<std::string>(m_timestep);
143
144 // Correct Dirichlet boundary conditions to account for mapping
145 m_mapping->UpdateBCs(0.0);
146 //
148 for (int i = 0; i < m_nConvectiveFields; ++i)
149 {
150 m_fields[i]->ImposeDirichletConditions(m_fields[i]->UpdateCoeffs());
151 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
152 m_fields[i]->UpdatePhys());
154 }
155
156 // Initialise m_gradP
157 size_t physTot = m_fields[0]->GetTotPoints();
159 for (int i = 0; i < m_nConvectiveFields; ++i)
160 {
161 m_gradP[i] = Array<OneD, NekDouble>(physTot, 0.0);
163 m_pressure->GetPhys(), m_gradP[i]);
164 if (m_pressure->GetWaveSpace())
165 {
166 m_pressure->HomogeneousBwdTrans(physTot, m_gradP[i], m_gradP[i]);
167 }
168 }
169}
170
171/**
172 * Explicit part of the method - Advection, Forcing + HOPBCs
173 */
175 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
176 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
177{
178 EvaluateAdvectionTerms(inarray, outarray, time);
179
180 // Smooth advection
182 {
183 for (int i = 0; i < m_nConvectiveFields; ++i)
184 {
185 m_pressure->SmoothField(outarray[i]);
186 }
187 }
188
189 // Add forcing terms
190 for (auto &x : m_forcing)
191 {
192 x->Apply(m_fields, inarray, outarray, time);
193 }
194
195 // Add mapping terms
196 ApplyIncNSMappingForcing(inarray, outarray);
197
198 // Calculate High-Order pressure boundary conditions
199 m_extrapolation->EvaluatePressureBCs(inarray, outarray, m_kinvis);
200
201 // Update mapping and deal with Dirichlet boundary conditions
202 if (m_mapping->IsTimeDependent())
203 {
204 if (m_mapping->IsFromFunction())
205 {
206 // If the transformation is explicitly defined, update it here
207 // Otherwise, it will be done somewhere else (ForcingMovingBody)
208 m_mapping->UpdateMapping(time + m_timestep);
209 }
210 m_mapping->UpdateBCs(time + m_timestep);
211 }
212}
213
214/**
215 * Forcing term for Poisson solver solver
216 */
218 const Array<OneD, const Array<OneD, NekDouble>> &fields,
220{
221 if (m_mapping->HasConstantJacobian())
222 {
224 aii_Dt);
225 }
226 else
227 {
228 size_t physTot = m_fields[0]->GetTotPoints();
229 size_t nvel = m_nConvectiveFields;
230 Array<OneD, NekDouble> wk(physTot, 0.0);
231
232 Array<OneD, NekDouble> Jac(physTot, 0.0);
233 m_mapping->GetJacobian(Jac);
234
235 // Calculate div(J*u/Dt)
236 Vmath::Zero(physTot, Forcing[0], 1);
237 for (size_t i = 0; i < nvel; ++i)
238 {
239 if (m_fields[i]->GetWaveSpace())
240 {
241 m_fields[i]->HomogeneousBwdTrans(physTot, fields[i], wk);
242 }
243 else
244 {
245 Vmath::Vcopy(physTot, fields[i], 1, wk, 1);
246 }
247 Vmath::Vmul(physTot, wk, 1, Jac, 1, wk, 1);
248 if (m_fields[i]->GetWaveSpace())
249 {
250 m_fields[i]->HomogeneousFwdTrans(physTot, wk, wk);
251 }
252 m_fields[i]->PhysDeriv(MultiRegions::DirCartesianMap[i], wk, wk);
253 Vmath::Vadd(physTot, wk, 1, Forcing[0], 1, Forcing[0], 1);
254 }
255 Vmath::Smul(physTot, 1.0 / aii_Dt, Forcing[0], 1, Forcing[0], 1);
256
257 //
258 // If the mapping viscous terms are being treated explicitly
259 // we need to apply a correction to the forcing
261 {
262 bool wavespace = m_fields[0]->GetWaveSpace();
263 m_fields[0]->SetWaveSpace(false);
264
265 //
266 // Part 1: div(J*grad(U/J . grad(J)))
269 for (size_t i = 0; i < tmp.size(); i++)
270 {
271 tmp[i] = Array<OneD, NekDouble>(physTot, 0.0);
272 velocity[i] = Array<OneD, NekDouble>(physTot, 0.0);
273 if (wavespace)
274 {
275 m_fields[0]->HomogeneousBwdTrans(
276 physTot, m_fields[i]->GetPhys(), velocity[i]);
277 }
278 else
279 {
280 Vmath::Vcopy(physTot, m_fields[i]->GetPhys(), 1,
281 velocity[i], 1);
282 }
283 }
284 // Calculate wk = U.grad(J)
285 m_mapping->DotGradJacobian(velocity, wk);
286 // Calculate wk = (U.grad(J))/J
287 Vmath::Vdiv(physTot, wk, 1, Jac, 1, wk, 1);
288 // J*grad[(U.grad(J))/J]
289 for (size_t i = 0; i < nvel; ++i)
290 {
291 m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i], wk,
292 tmp[i]);
293 Vmath::Vmul(physTot, Jac, 1, tmp[i], 1, tmp[i], 1);
294 }
295 // div(J*grad[(U.grad(J))/J])
296 Vmath::Zero(physTot, wk, 1);
297 for (size_t i = 0; i < nvel; ++i)
298 {
299 m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i], tmp[i],
300 tmp[i]);
301 Vmath::Vadd(physTot, wk, 1, tmp[i], 1, wk, 1);
302 }
303
304 // Part 2: grad(J) . curl(curl(U))
305 m_mapping->CurlCurlField(velocity, tmp, m_implicitViscous);
306 // dont need velocity any more, so reuse it
307 m_mapping->DotGradJacobian(tmp, velocity[0]);
308
309 // Add two parts
310 Vmath::Vadd(physTot, velocity[0], 1, wk, 1, wk, 1);
311
312 // Multiply by kinvis and prepare to extrapolate
313 size_t nlevels = m_presForcingCorrection.size();
314 Vmath::Smul(physTot, m_kinvis, wk, 1,
315 m_presForcingCorrection[nlevels - 1], 1);
316
317 // Extrapolate correction
318 m_extrapolation->ExtrapolateArray(m_presForcingCorrection);
319
320 // Put in wavespace
321 if (wavespace)
322 {
323 m_fields[0]->HomogeneousFwdTrans(
324 physTot, m_presForcingCorrection[nlevels - 1], wk);
325 }
326 else
327 {
328 Vmath::Vcopy(physTot, m_presForcingCorrection[nlevels - 1], 1,
329 wk, 1);
330 }
331 // Apply correction: Forcing = Forcing - correction
332 Vmath::Vsub(physTot, Forcing[0], 1, wk, 1, Forcing[0], 1);
333
334 m_fields[0]->SetWaveSpace(wavespace);
335 }
336 }
337}
338
339/**
340 * Forcing term for Helmholtz solver
341 */
343 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
345{
346 NekDouble aii_dtinv = 1.0 / aii_Dt;
347 size_t physTot = m_fields[0]->GetTotPoints();
348
349 // Grad p
350 m_pressure->BwdTrans(m_pressure->GetCoeffs(), m_pressure->UpdatePhys());
351
352 size_t nvel = m_velocity.size();
353 if (nvel == 2)
354 {
355 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[0], Forcing[1]);
356 }
357 else
358 {
359 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[0], Forcing[1],
360 Forcing[2]);
361 }
362
363 // Copy grad p in physical space to m_gradP to reuse later
364 if (m_pressure->GetWaveSpace())
365 {
366 for (size_t i = 0; i < nvel; i++)
367 {
368 m_pressure->HomogeneousBwdTrans(physTot, Forcing[i], m_gradP[i]);
369 }
370 }
371 else
372 {
373 for (size_t i = 0; i < nvel; i++)
374 {
375 Vmath::Vcopy(physTot, Forcing[i], 1, m_gradP[i], 1);
376 }
377 }
378
379 if ((!m_mapping->HasConstantJacobian()) || m_implicitPressure)
380 {
381 // If pressure terms are treated explicitly, we need to divide by J
382 // if they are implicit, we need to calculate G(p)
384 {
385 m_mapping->RaiseIndex(m_gradP, Forcing);
386 }
387 else
388 {
389 Array<OneD, NekDouble> Jac(physTot, 0.0);
390 m_mapping->GetJacobian(Jac);
391 for (size_t i = 0; i < nvel; i++)
392 {
393 Vmath::Vdiv(physTot, m_gradP[i], 1, Jac, 1, Forcing[i], 1);
394 }
395 }
396 // Transform back to wavespace
397 if (m_pressure->GetWaveSpace())
398 {
399 for (size_t i = 0; i < nvel; i++)
400 {
401 m_pressure->HomogeneousFwdTrans(physTot, Forcing[i],
402 Forcing[i]);
403 }
404 }
405 }
406
407 // Subtract inarray/(aii_dt) and divide by kinvis. Kinvis will
408 // need to be updated for the convected fields.
409 for (size_t i = 0; i < nvel; ++i)
410 {
411 Blas::Daxpy(physTot, -aii_dtinv, inarray[i], 1, Forcing[i], 1);
412 Blas::Dscal(physTot, 1.0 / m_kinvis, &(Forcing[i])[0], 1);
413 }
414}
415
416/**
417 * Solve pressure system
418 */
420{
422 {
424 }
425 else
426 {
427 size_t physTot = m_fields[0]->GetTotPoints();
428 size_t nvel = m_nConvectiveFields;
429 bool converged = false; // flag to mark if system converged
430 size_t s = 0; // iteration counter
431 NekDouble error; // L2 error at current iteration
432 NekDouble forcing_L2 = 0.0; // L2 norm of F
433
434 size_t maxIter;
435 m_session->LoadParameter("MappingMaxIter", maxIter, 5000);
436
437 // rhs of the equation at current iteration
438 Array<OneD, NekDouble> F_corrected(physTot, 0.0);
439 // Pressure field at previous iteration
440 Array<OneD, NekDouble> previous_iter(physTot, 0.0);
441 // Temporary variables
445 for (size_t i = 0; i < nvel; ++i)
446 {
447 wk1[i] = Array<OneD, NekDouble>(physTot, 0.0);
448 wk2[i] = Array<OneD, NekDouble>(physTot, 0.0);
449 gradP[i] = Array<OneD, NekDouble>(physTot, 0.0);
450 }
451
452 // Jacobian
453 Array<OneD, NekDouble> Jac(physTot, 0.0);
454 m_mapping->GetJacobian(Jac);
455
456 // Factors for Laplacian system
459
460 m_pressure->BwdTrans(m_pressure->GetCoeffs(), m_pressure->UpdatePhys());
461 forcing_L2 = m_pressure->L2(Forcing, wk1[0]);
462 while (!converged)
463 {
464 // Update iteration counter and set previous iteration field
465 // (use previous timestep solution for first iteration)
466 s++;
467 ASSERTL0(s < maxIter,
468 "VCSMapping exceeded maximum number of iterations.");
469
470 Vmath::Vcopy(physTot, m_pressure->GetPhys(), 1, previous_iter, 1);
471
472 // Correct pressure bc to account for iteration
473 m_extrapolation->CorrectPressureBCs(previous_iter);
474
475 //
476 // Calculate forcing term for this iteration
477 //
478 for (size_t i = 0; i < nvel; ++i)
479 {
481 previous_iter, gradP[i]);
482 if (m_pressure->GetWaveSpace())
483 {
484 m_pressure->HomogeneousBwdTrans(physTot, gradP[i], wk1[i]);
485 }
486 else
487 {
488 Vmath::Vcopy(physTot, gradP[i], 1, wk1[i], 1);
489 }
490 }
491 m_mapping->RaiseIndex(wk1, wk2); // G(p)
492
493 m_mapping->Divergence(wk2, F_corrected); // div(G(p))
494 if (!m_mapping->HasConstantJacobian())
495 {
496 Vmath::Vmul(physTot, F_corrected, 1, Jac, 1, F_corrected, 1);
497 }
498 // alpha*J*div(G(p))
499 Vmath::Smul(physTot, m_pressureRelaxation, F_corrected, 1,
500 F_corrected, 1);
501 if (m_pressure->GetWaveSpace())
502 {
503 m_pressure->HomogeneousFwdTrans(physTot, F_corrected,
504 F_corrected);
505 }
506 // alpha*J*div(G(p)) - p_ii
507 for (int i = 0; i < m_nConvectiveFields; ++i)
508 {
510 gradP[i], wk1[0]);
511 Vmath::Vsub(physTot, F_corrected, 1, wk1[0], 1, F_corrected, 1);
512 }
513 // p_i,i - J*div(G(p))
514 Vmath::Neg(physTot, F_corrected, 1);
515 // alpha*F - alpha*J*div(G(p)) + p_i,i
516 Vmath::Smul(physTot, m_pressureRelaxation, Forcing, 1, wk1[0], 1);
517 Vmath::Vadd(physTot, wk1[0], 1, F_corrected, 1, F_corrected, 1);
518
519 //
520 // Solve system
521 //
522 m_pressure->HelmSolve(F_corrected, m_pressure->UpdateCoeffs(),
523 factors);
524 m_pressure->BwdTrans(m_pressure->GetCoeffs(),
525 m_pressure->UpdatePhys());
526
527 //
528 // Test convergence
529 //
530 error = m_pressure->L2(m_pressure->GetPhys(), previous_iter);
531 if (forcing_L2 != 0)
532 {
533 if ((error / forcing_L2 < m_pressureTolerance))
534 {
535 converged = true;
536 }
537 }
538 else
539 {
540 if (error < m_pressureTolerance)
541 {
542 converged = true;
543 }
544 }
545 }
546 if (m_verbose && m_session->GetComm()->GetRank() == 0)
547 {
548 std::cout << " Pressure system (mapping) converged in " << s
549 << " iterations with error = " << error << std::endl;
550 }
551 }
552}
553
554/**
555 * Solve velocity system
556 */
559 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
560 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble aii_Dt)
561{
562 boost::ignore_unused(inarray);
563
565 {
567 aii_Dt);
568 }
569 else
570 {
571 size_t physTot = m_fields[0]->GetTotPoints();
572 size_t nvel = m_nConvectiveFields;
573 bool converged = false; // flag to mark if system converged
574 size_t s = 0; // iteration counter
575 NekDouble error, max_error; // L2 error at current iteration
576
577 size_t maxIter;
578 m_session->LoadParameter("MappingMaxIter", maxIter, 5000);
579
580 // L2 norm of F
582
583 // rhs of the equation at current iteration
584 Array<OneD, Array<OneD, NekDouble>> F_corrected(nvel);
585 // Solution at previous iteration
586 Array<OneD, Array<OneD, NekDouble>> previous_iter(nvel);
587 // Working space
589 for (size_t i = 0; i < nvel; ++i)
590 {
591 F_corrected[i] = Array<OneD, NekDouble>(physTot, 0.0);
592 previous_iter[i] = Array<OneD, NekDouble>(physTot, 0.0);
593 wk[i] = Array<OneD, NekDouble>(physTot, 0.0);
594 }
595
596 // Factors for Helmholtz system
599 1.0 * m_viscousRelaxation / aii_Dt / m_kinvis;
601 {
605 }
606
607 // Calculate L2-norm of F and set initial solution for iteration
608 for (size_t i = 0; i < nvel; ++i)
609 {
610 forcing_L2[i] = m_fields[0]->L2(Forcing[i], wk[0]);
611 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), previous_iter[i]);
612 }
613
614 while (!converged)
615 {
616 converged = true;
617 // Iteration counter
618 s++;
619 ASSERTL0(s < maxIter,
620 "VCSMapping exceeded maximum number of iterations.");
621
622 max_error = 0.0;
623
624 //
625 // Calculate forcing term for next iteration
626 //
627
628 // Calculate L(U)- in this parts all components might be coupled
629 if (m_fields[0]->GetWaveSpace())
630 {
631 for (size_t i = 0; i < nvel; ++i)
632 {
633 m_fields[0]->HomogeneousBwdTrans(physTot, previous_iter[i],
634 wk[i]);
635 }
636 }
637 else
638 {
639 for (size_t i = 0; i < nvel; ++i)
640 {
641 Vmath::Vcopy(physTot, previous_iter[i], 1, wk[i], 1);
642 }
643 }
644
645 // (L(U^i) - 1/alpha*U^i_jj)
646 m_mapping->VelocityLaplacian(wk, F_corrected,
647 1.0 / m_viscousRelaxation);
648
649 if (m_fields[0]->GetWaveSpace())
650 {
651 for (size_t i = 0; i < nvel; ++i)
652 {
653 m_fields[0]->HomogeneousFwdTrans(physTot, F_corrected[i],
654 F_corrected[i]);
655 }
656 }
657 else
658 {
659 for (size_t i = 0; i < nvel; ++i)
660 {
661 Vmath::Vcopy(physTot, F_corrected[i], 1, F_corrected[i], 1);
662 }
663 }
664
665 // Loop velocity components
666 for (size_t i = 0; i < nvel; ++i)
667 {
668 // (-alpha*L(U^i) + U^i_jj)
669 Vmath::Smul(physTot, -1.0 * m_viscousRelaxation, F_corrected[i],
670 1, F_corrected[i], 1);
671 // F_corrected = alpha*F + (-alpha*L(U^i) + U^i_jj)
672 Vmath::Smul(physTot, m_viscousRelaxation, Forcing[i], 1, wk[0],
673 1);
674 Vmath::Vadd(physTot, wk[0], 1, F_corrected[i], 1,
675 F_corrected[i], 1);
676
677 //
678 // Solve System
679 //
680 m_fields[i]->HelmSolve(F_corrected[i],
681 m_fields[i]->UpdateCoeffs(), factors);
682 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
683
684 //
685 // Test convergence
686 //
687 error = m_fields[i]->L2(outarray[i], previous_iter[i]);
688
689 if (forcing_L2[i] != 0)
690 {
691 if ((error / forcing_L2[i] >= m_viscousTolerance))
692 {
693 converged = false;
694 }
695 }
696 else
697 {
698 if (error >= m_viscousTolerance)
699 {
700 converged = false;
701 }
702 }
703 if (error > max_error)
704 {
705 max_error = error;
706 }
707
708 // Copy field to previous_iter
709 Vmath::Vcopy(physTot, outarray[i], 1, previous_iter[i], 1);
710 }
711 }
712 if (m_verbose && m_session->GetComm()->GetRank() == 0)
713 {
714 std::cout << " Velocity system (mapping) converged in " << s
715 << " iterations with error = " << max_error << std::endl;
716 }
717 }
718}
719
720/**
721 * Explicit terms of the mapping
722 */
724 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
726{
727 size_t physTot = m_fields[0]->GetTotPoints();
732 for (int i = 0; i < m_nConvectiveFields; ++i)
733 {
734 velPhys[i] = Array<OneD, NekDouble>(physTot, 0.0);
735 Forcing[i] = Array<OneD, NekDouble>(physTot, 0.0);
736 tmp[i] = Array<OneD, NekDouble>(physTot, 0.0);
737 }
738
739 // Get fields and store velocity in wavespace and physical space
740 if (m_fields[0]->GetWaveSpace())
741 {
742 for (int i = 0; i < m_nConvectiveFields; ++i)
743 {
744 vel[i] = inarray[i];
745 m_fields[0]->HomogeneousBwdTrans(physTot, vel[i], velPhys[i]);
746 }
747 }
748 else
749 {
750 for (int i = 0; i < m_nConvectiveFields; ++i)
751 {
752 vel[i] = inarray[i];
753 Vmath::Vcopy(physTot, inarray[i], 1, velPhys[i], 1);
754 }
755 }
756
757 // Advection contribution
759
760 // Time-derivative contribution
761 if (m_mapping->IsTimeDependent())
762 {
763 MappingAccelerationCorrection(vel, velPhys, tmp);
764 for (int i = 0; i < m_nConvectiveFields; ++i)
765 {
766 Vmath::Vadd(physTot, tmp[i], 1, Forcing[i], 1, Forcing[i], 1);
767 }
768 }
769
770 // Pressure contribution
772 {
774 for (int i = 0; i < m_nConvectiveFields; ++i)
775 {
776 Vmath::Vadd(physTot, tmp[i], 1, Forcing[i], 1, Forcing[i], 1);
777 }
778 }
779 // Viscous contribution
781 {
782 MappingViscousCorrection(velPhys, tmp);
783 for (int i = 0; i < m_nConvectiveFields; ++i)
784 {
785 Vmath::Smul(physTot, m_kinvis, tmp[i], 1, tmp[i], 1);
786 Vmath::Vadd(physTot, tmp[i], 1, Forcing[i], 1, Forcing[i], 1);
787 }
788 }
789
790 // If necessary, transform to wavespace
791 if (m_fields[0]->GetWaveSpace())
792 {
793 for (int i = 0; i < m_nConvectiveFields; ++i)
794 {
795 m_fields[0]->HomogeneousFwdTrans(physTot, Forcing[i], Forcing[i]);
796 }
797 }
798
799 // Add to outarray
800 for (int i = 0; i < m_nConvectiveFields; ++i)
801 {
802 Vmath::Vadd(physTot, outarray[i], 1, Forcing[i], 1, outarray[i], 1);
803 }
804}
805
807 const Array<OneD, const Array<OneD, NekDouble>> &velPhys,
809{
810 size_t physTot = m_fields[0]->GetTotPoints();
811 size_t nvel = m_nConvectiveFields;
812
813 Array<OneD, Array<OneD, NekDouble>> wk(nvel * nvel);
814
815 // Apply Christoffel symbols to obtain {i,kj}vel(k)
816 m_mapping->ApplyChristoffelContravar(velPhys, wk);
817
818 // Calculate correction -U^j*{i,kj}vel(k)
819 for (size_t i = 0; i < nvel; i++)
820 {
821 Vmath::Zero(physTot, outarray[i], 1);
822 for (size_t j = 0; j < nvel; j++)
823 {
824 Vmath::Vvtvp(physTot, wk[i * nvel + j], 1, velPhys[j], 1,
825 outarray[i], 1, outarray[i], 1);
826 }
827 Vmath::Neg(physTot, outarray[i], 1);
828 }
829}
830
832 const Array<OneD, const Array<OneD, NekDouble>> &vel,
833 const Array<OneD, const Array<OneD, NekDouble>> &velPhys,
835{
836 size_t physTot = m_fields[0]->GetTotPoints();
837 size_t nvel = m_nConvectiveFields;
838
839 Array<OneD, Array<OneD, NekDouble>> wk(nvel * nvel);
842 for (size_t i = 0; i < nvel; i++)
843 {
844 tmp[i] = Array<OneD, NekDouble>(physTot, 0.0);
845 coordVel[i] = Array<OneD, NekDouble>(physTot, 0.0);
846 }
847 // Get coordinates velocity in transformed system
848 m_mapping->GetCoordVelocity(tmp);
849 m_mapping->ContravarFromCartesian(tmp, coordVel);
850
851 // Calculate first term: U^j u^i,j = U^j (du^i/dx^j + {i,kj}u^k)
852 m_mapping->ApplyChristoffelContravar(velPhys, wk);
853 for (size_t i = 0; i < nvel; i++)
854 {
855 Vmath::Zero(physTot, outarray[i], 1);
856
857 m_fields[0]->PhysDeriv(velPhys[i], tmp[0], tmp[1]);
858 for (size_t j = 0; j < nvel; j++)
859 {
860 if (j == 2)
861 {
862 m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[j], vel[i],
863 tmp[2]);
864 if (m_fields[0]->GetWaveSpace())
865 {
866 m_fields[0]->HomogeneousBwdTrans(physTot, tmp[2], tmp[2]);
867 }
868 }
869
870 Vmath::Vadd(physTot, wk[i * nvel + j], 1, tmp[j], 1,
871 wk[i * nvel + j], 1);
872
873 Vmath::Vvtvp(physTot, coordVel[j], 1, wk[i * nvel + j], 1,
874 outarray[i], 1, outarray[i], 1);
875 }
876 }
877
878 // Set wavespace to false and store current value
879 bool wavespace = m_fields[0]->GetWaveSpace();
880 m_fields[0]->SetWaveSpace(false);
881
882 // Add -u^j U^i,j
883 m_mapping->ApplyChristoffelContravar(coordVel, wk);
884 for (size_t i = 0; i < nvel; i++)
885 {
886 if (nvel == 2)
887 {
888 m_fields[0]->PhysDeriv(coordVel[i], tmp[0], tmp[1]);
889 }
890 else
891 {
892 m_fields[0]->PhysDeriv(coordVel[i], tmp[0], tmp[1], tmp[2]);
893 }
894
895 for (size_t j = 0; j < nvel; j++)
896 {
897 Vmath::Vadd(physTot, wk[i * nvel + j], 1, tmp[j], 1,
898 wk[i * nvel + j], 1);
899 Vmath::Neg(physTot, wk[i * nvel + j], 1);
900
901 Vmath::Vvtvp(physTot, velPhys[j], 1, wk[i * nvel + j], 1,
902 outarray[i], 1, outarray[i], 1);
903 }
904 }
905
906 // Restore value of wavespace
907 m_fields[0]->SetWaveSpace(wavespace);
908}
909
912{
913 size_t physTot = m_fields[0]->GetTotPoints();
914 size_t nvel = m_nConvectiveFields;
915
916 // Calculate g^(ij)p_(,j)
917 m_mapping->RaiseIndex(m_gradP, outarray);
918
919 // Calculate correction = (nabla p)/J - g^(ij)p_,j
920 // (Jac is not required if it is constant)
921 if (!m_mapping->HasConstantJacobian())
922 {
923 Array<OneD, NekDouble> Jac(physTot, 0.0);
924 m_mapping->GetJacobian(Jac);
925 for (size_t i = 0; i < nvel; ++i)
926 {
927 Vmath::Vdiv(physTot, m_gradP[i], 1, Jac, 1, m_gradP[i], 1);
928 }
929 }
930 for (size_t i = 0; i < nvel; ++i)
931 {
932 Vmath::Vsub(physTot, m_gradP[i], 1, outarray[i], 1, outarray[i], 1);
933 }
934}
935
937 const Array<OneD, const Array<OneD, NekDouble>> &velPhys,
939{
940 // L(U) - 1.0*d^2(u^i)/dx^jdx^j
941 m_mapping->VelocityLaplacian(velPhys, outarray, 1.0);
942}
943
944} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
static GLOBAL_MAPPING_EXPORT MappingSharedPtr Load(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Return a pointer to the mapping, creating it on first call.
Definition: Mapping.cpp:272
MultiRegions::ExpListSharedPtr m_pressure
Pointer to field holding pressure field.
NekDouble m_kinvis
Kinematic viscosity.
bool m_SmoothAdvection
bool to identify if advection term smoothing is requested
ExtrapolateSharedPtr m_extrapolation
Array< OneD, int > m_velocity
int which identifies which components of m_fields contains the velocity (u,v,w);
int m_intSteps
Number of time integration steps AND Order of extrapolation for pressure boundary conditions.
int m_nConvectiveFields
Number of fields to be convected;.
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void EvaluateAdvectionTerms(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
static std::string RegisterEnumValue(std::string pEnum, std::string pString, int pEnumValue)
Registers an enumeration value.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
NekDouble m_timestep
Time step size.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
SOLVER_UTILS_EXPORT int GetTotPoints()
Defines a forcing term to be explicitly applied.
Definition: Forcing.h:73
Base class for unsteady solvers.
virtual SOLVER_UTILS_EXPORT void v_DoInitialise(bool dumpInitialConditions=true) override
Sets up initial conditions.
LibUtilities::TimeIntegrationSchemeSharedPtr m_intScheme
Wrapper to the time integration scheme.
virtual void v_SolvePressure(const Array< OneD, NekDouble > &Forcing) override
Definition: VCSMapping.cpp:419
virtual void v_SetUpPressureForcing(const Array< OneD, const Array< OneD, NekDouble > > &fields, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt) override
Definition: VCSMapping.cpp:217
void MappingViscousCorrection(const Array< OneD, const Array< OneD, NekDouble > > &velPhys, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:936
virtual ~VCSMapping()
Definition: VCSMapping.cpp:131
virtual void v_DoInitialise(bool dumpInitialConditions=true) override
Sets up initial conditions.
Definition: VCSMapping.cpp:135
virtual void v_SetUpViscousForcing(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt) override
Definition: VCSMapping.cpp:342
NekDouble m_pressureTolerance
Definition: VCSMapping.h:88
NekDouble m_viscousRelaxation
Definition: VCSMapping.h:91
static std::string className
Name of class.
Definition: VCSMapping.h:58
NekDouble m_pressureRelaxation
Definition: VCSMapping.h:90
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
Definition: VCSMapping.h:47
NekDouble m_viscousTolerance
Definition: VCSMapping.h:89
virtual void v_EvaluateAdvection_SetPressureBCs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time) override
Definition: VCSMapping.cpp:174
virtual void v_SolveViscous(const Array< OneD, const Array< OneD, NekDouble > > &Forcing, const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble aii_Dt) override
Definition: VCSMapping.cpp:557
static std::string solverTypeLookupId
Definition: VCSMapping.h:77
GlobalMapping::MappingSharedPtr m_mapping
Definition: VCSMapping.h:75
void MappingPressureCorrection(Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:910
void ApplyIncNSMappingForcing(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:723
Array< OneD, Array< OneD, NekDouble > > m_presForcingCorrection
Definition: VCSMapping.h:124
VCSMapping(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Constructor.
Definition: VCSMapping.cpp:59
virtual void v_InitObject(bool DeclareField=true) override
Init object for UnsteadySystem class.
Definition: VCSMapping.cpp:66
void MappingAccelerationCorrection(const Array< OneD, const Array< OneD, NekDouble > > &vel, const Array< OneD, const Array< OneD, NekDouble > > &velPhys, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:831
Array< OneD, Array< OneD, NekDouble > > m_gradP
Definition: VCSMapping.h:94
void MappingAdvectionCorrection(const Array< OneD, const Array< OneD, NekDouble > > &velPhys, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:806
NekDouble m_sVVCutoffRatio
cutt off ratio from which to start decayhing modes
NekDouble m_sVVDiffCoeff
Diffusion coefficient of SVV modes.
virtual void v_SolvePressure(const Array< OneD, NekDouble > &Forcing)
Array< OneD, Array< OneD, NekDouble > > m_F
virtual void v_SetUpPressureForcing(const Array< OneD, const Array< OneD, NekDouble > > &fields, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
bool m_useSpecVanVisc
bool to identify if spectral vanishing viscosity is active.
virtual void v_SolveViscous(const Array< OneD, const Array< OneD, NekDouble > > &Forcing, const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble aii_Dt)
virtual void v_InitObject(bool DeclareField=true) override
Init object for UnsteadySystem class.
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:151
static void Daxpy(const int &n, const double &alpha, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: y = alpha x plus y.
Definition: Blas.hpp:137
std::shared_ptr< SessionReader > SessionReaderSharedPtr
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:90
EquationSystemFactory & GetEquationSystemFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:408
StdRegions::ConstFactorMap factors
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
ExtrapolateFactory & GetExtrapolateFactory()
Definition: Extrapolate.cpp:48
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.cpp:207
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:513
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.cpp:569
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.cpp:354
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.cpp:245
void Vdiv(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.cpp:280
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:487
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:414