Nektar++
Loading...
Searching...
No Matches
UnsteadyAdvection.cpp
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2//
3// File: UnsteadyAdvection.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: Unsteady linear advection solve routines
32//
33///////////////////////////////////////////////////////////////////////////////
34
39#include <iostream>
40
41namespace Nektar
42{
43
46 "UnsteadyAdvection", UnsteadyAdvection::create,
47 "Unsteady Advection equation.");
48
52 : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph)
53{
54}
55
56/**
57 * @brief Initialisation object for the unsteady linear advection equation.
58 */
59void UnsteadyAdvection::v_InitObject(bool DeclareFields)
60{
61 // Call to the initialisation object of UnsteadySystem
62 AdvectionSystem::v_InitObject(DeclareFields);
63
64 // Read the advection velocities from session file
65 m_session->LoadParameter("wavefreq", m_waveFreq, 0.0);
66
67 // check to see if it is explicity turned off
68 m_session->MatchSolverInfo("GJPStabilisation", "False",
70
71 // if GJPStabilisation set to False bool will be true and
72 // if not false so negate/revese bool
74
75 m_session->LoadParameter("GJPJumpScale", m_GJPJumpScale, 1.0);
76
77 // Define Velocity fields
78 std::vector<std::string> vel;
79 vel.push_back("Vx");
80 vel.push_back("Vy");
81 vel.push_back("Vz");
82
83 // Resize the advection velocities vector to dimension of the problem
84 vel.resize(m_spacedim);
85
86 // Store in the global variable m_velocity the advection velocities
88 GetFunction("AdvectionVelocity")->Evaluate(vel, m_velocity);
89
90 // Set advection velocities
94 for (int i = 0; i < m_spacedim; i++)
95 {
96 m_varcoeffs[varcoefftypes[i]] = m_velocity[i];
97 }
98
99 // Type of advection class to be used
100 switch (m_projectionType)
101 {
102 // Discontinuous field
104 {
105 // Do not forwards transform initial condition
106 m_homoInitialFwd = false;
107
108 // Define the normal velocity fields
109 if (m_fields[0]->GetTrace())
110 {
112 }
113
114 std::string advName;
115 std::string riemName;
116 m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
118 advName, advName);
120 {
121 m_advObject->SetFluxVector(
123 }
124 else
125 {
127 this);
128 }
129 m_session->LoadSolverInfo("UpwindType", riemName, "Upwind");
132 riemName, m_session);
133 m_riemannSolver->SetScalar(
135 m_advObject->SetRiemannSolver(m_riemannSolver);
136 m_advObject->InitObject(m_session, m_fields);
137 break;
138 }
139 // Continuous field
142 {
143 std::string advName;
144 m_session->LoadSolverInfo("AdvectionType", advName,
145 "NonConservative");
147 advName, advName);
149 {
150 m_advObject->SetFluxVector(
152 }
153 else
154 {
156 this);
157 }
158 break;
159 }
160 default:
161 {
162 ASSERTL0(false, "Unsupported projection type.");
163 break;
164 }
165 }
166
167 // Forcing terms
168 m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
169 m_fields, m_fields.size());
170
171 // If explicit it computes RHS and PROJECTION for the time integration
173 {
176 }
177 // Otherwise it gives an error (no implicit integration)
178 else
179 {
182 "Implicit UnsteadyAdvection is not implemented for a "
183 "Discontinuous Galerkin discretisation.")
184 }
185}
186
187/**
188 * @brief Compute the right-hand side for the linear advection equation.
189 *
190 * @param inarray Given fields.
191 * @param outarray Calculated solution.
192 * @param time Time.
193 */
195 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
196 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
197{
198 // Number of fields (variables of the problem)
199 int nVariables = inarray.size();
200
202 if (m_meshDistorted)
203 {
204 timer.Start();
205 Array<OneD, Array<OneD, NekDouble>> tmpIn(nVariables);
206 // If ALE we must take Mu coefficient space to u physical space
208 auto advWeakDGObject =
209 std::dynamic_pointer_cast<SolverUtils::AdvectionWeakDG>(
211 advWeakDGObject->AdvectCoeffs(nVariables, m_fields, m_velocity, tmpIn,
212 outarray, time);
213 timer.Stop();
214 }
215 else
216 {
217 timer.Start();
218 m_advObject->Advect(nVariables, m_fields, m_velocity, inarray, outarray,
219 time);
220 timer.Stop();
221 }
222
223 // Elapsed time
224 timer.AccumulateRegion("Advect");
225
226 // Negate the RHS
227 for (int i = 0; i < nVariables; ++i)
228 {
229 Vmath::Neg(outarray[i].size(), outarray[i], 1);
230 }
231
232 // Add forcing terms
233 for (auto &x : m_forcing)
234 {
235 // set up non-linear terms
236 x->Apply(m_fields, inarray, outarray, time);
237 }
238}
239
240/**
241 * @brief Compute the projection for the linear advection equation.
242 *
243 * @param inarray Given fields.
244 * @param outarray Calculated solution.
245 * @param time Time.
246 */
248 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
249 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
250{
251 // Number of fields (variables of the problem)
252 int nVariables = inarray.size();
253
254 // Perform ALE movement
255 if (m_ALESolver)
256 {
258 }
259
260 // Set the boundary conditions
262
263 // Switch on the projection type (Discontinuous or Continuous)
264 switch (m_projectionType)
265 {
266 // Discontinuous projection
268 {
269 // Just copy over array
270 if (inarray != outarray)
271 {
272 int npoints = GetNpoints();
273
274 for (int i = 0; i < nVariables; ++i)
275 {
276 Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
277 }
278 }
279 break;
280 }
281 // Continuous projection
284 {
285 int ncoeffs = m_fields[0]->GetNcoeffs();
286 Array<OneD, NekDouble> coeffs(ncoeffs, 0.0);
288 {
291
292 Array<OneD, NekDouble> wsp(ncoeffs);
293
294 for (int i = 0; i < nVariables; ++i)
295 {
297 std::dynamic_pointer_cast<MultiRegions::ContField>(
298 m_fields[i]);
299
300 m_fields[i]->IProductWRTBase(inarray[i], wsp);
301
302 cfield->InitGJPData();
303
305 cfield->GetGJPData();
306
307 factors[StdRegions::eFactorGJP] =
309
310 StdRegions::VarCoeffMap varcoeffs;
311 StdRegions::VarFactorsMap varfactors;
312
313 if (GJPData->IsSemiImplicit())
314 {
315 mtype = StdRegions::eMassGJP;
316
318 GJPData->GetTraceWeightVarFactors();
319 }
320
321 if (GJPData->IsSemiImplicit() || GJPData->IsExplicit())
322 {
323 // to set up forcing need initial guess in
324 // physical space
325 NekDouble scale = -factors[StdRegions::eFactorGJP];
326
327 GJPData->Apply(inarray[i], wsp, NullNekDouble1DArray,
328 scale);
329 }
330
331 if (GJPData->IsImplicit())
332 {
334 GJPData->GetTraceWeightVarFactors();
335 }
336
337 // Solve the system
339 mtype, cfield->GetLocalToGlobalMap(), factors,
340 varcoeffs, varfactors);
341
342 cfield->GlobalSolve(key, wsp, coeffs, NullNekDouble1DArray);
343
344 m_fields[i]->BwdTrans(coeffs, outarray[i]);
345 }
346 }
347 else
348 {
349 for (int i = 0; i < nVariables; ++i)
350 {
351 m_fields[i]->FwdTrans(inarray[i], coeffs);
352 m_fields[i]->BwdTrans(coeffs, outarray[i]);
353 }
354 }
355 break;
356 }
357 default:
358 ASSERTL0(false, "Unknown projection scheme");
359 break;
360 }
361}
362
363/**
364 * @brief Implicit solution of the unsteady advection problem.
365 */
367 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
369 [[maybe_unused]] const NekDouble time, const NekDouble lambda)
370{
372
373 int nvariables = inarray.size();
374 int npoints = m_fields[0]->GetNpoints();
375 factors[StdRegions::eFactorLambda] = -1.0 / lambda;
376
377 for (int i = 0; i < nvariables; ++i)
378 {
379 // Multiply 1.0/timestep/lambda
380 Vmath::Smul(npoints, factors[StdRegions::eFactorLambda], inarray[i], 1,
381 outarray[i], 1);
382
383 // Solve a system of equations
384 m_fields[i]->LinearAdvectionReactionSolve(
385 outarray[i], m_fields[i]->UpdateCoeffs(), factors, m_varcoeffs);
386
387 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
388
389 m_fields[i]->SetPhysState(false);
390 }
391}
392
393/**
394 * @brief Get the normal velocity for the linear advection equation.
395 */
401
403 const Array<OneD, const Array<OneD, NekDouble>> &velfield)
404{
405 // Number of trace (interface) points
406 int nTracePts = GetTraceNpoints();
407 int nPts = m_velocity[0].size();
408
409 // Auxiliary variable to compute the normal velocity
410 Array<OneD, NekDouble> tmp(nPts), tmp2(nTracePts);
411
412 // Reset the normal velocity
413 Vmath::Zero(nTracePts, m_traceVn, 1);
414
415 for (int i = 0; i < velfield.size(); ++i)
416 {
417 // velocity - grid velocity for ALE before getting trace velocity
418 Vmath::Vsub(nPts, velfield[i], 1, m_gridVelocity[i], 1, tmp, 1);
419
420 m_fields[0]->ExtractTracePhys(tmp, tmp2);
421
422 Vmath::Vvtvp(nTracePts, m_traceNormals[i], 1, tmp2, 1, m_traceVn, 1,
423 m_traceVn, 1);
424 }
425
426 return m_traceVn;
427}
428
429/**
430 * @brief Return the flux vector for the linear advection equation.
431 *
432 * @param physfield Fields.
433 * @param flux Resulting flux.
434 */
436 const Array<OneD, Array<OneD, NekDouble>> &physfield,
438{
439 ASSERTL1(flux[0].size() == m_velocity.size(),
440 "Dimension of flux array and velocity array do not match");
441
442 const int nq = m_fields[0]->GetNpoints();
443
444 for (int i = 0; i < flux.size(); ++i)
445 {
446 for (int j = 0; j < flux[0].size(); ++j)
447 {
448 for (int k = 0; k < nq; ++k)
449 {
450 // If ALE we need to take off the grid velocity
451 flux[i][j][k] =
452 physfield[i][k] * (m_velocity[j][k] - m_gridVelocity[j][k]);
453 }
454 }
455 }
456}
457
458/**
459 * @brief Return the flux vector for the linear advection equation using
460 * the dealiasing technique.
461 *
462 * @param physfield Fields.
463 * @param flux Resulting flux.
464 */
466 const Array<OneD, Array<OneD, NekDouble>> &physfield,
468{
469 ASSERTL1(flux[0].size() == m_velocity.size(),
470 "Dimension of flux array and velocity array do not match");
471
472 int nq = physfield[0].size();
473 int nVariables = physfield.size();
474
475 // Factor to rescale 1d points in dealiasing
476 NekDouble OneDptscale = 2;
477
479
480 // Get number of points to dealias a cubic non-linearity
481 nq = m_fields[0]->Get1DScaledTotPoints(OneDptscale);
482
483 // Initialisation of higher-space variables
484 Array<OneD, Array<OneD, NekDouble>> physfieldInterp(nVariables);
486 Array<OneD, Array<OneD, Array<OneD, NekDouble>>> fluxInterp(nVariables);
487
488 // Interpolation to higher space of physfield
489 for (int i = 0; i < nVariables; ++i)
490 {
491 physfieldInterp[i] = Array<OneD, NekDouble>(nq);
493 for (int j = 0; j < m_expdim; ++j)
494 {
495 fluxInterp[i][j] = Array<OneD, NekDouble>(nq);
496 }
497
498 m_fields[0]->PhysInterp1DScaled(OneDptscale, physfield[i],
499 physfieldInterp[i]);
500 }
501
502 // Interpolation to higher space of velocity
503 for (int j = 0; j < m_expdim; ++j)
504 {
505 velocityInterp[j] = Array<OneD, NekDouble>(nq);
506
507 m_fields[0]->PhysInterp1DScaled(OneDptscale, m_velocity[j],
508 velocityInterp[j]);
509 }
510
511 // Evaluation of flux vector in the higher space
512 for (int i = 0; i < flux.size(); ++i)
513 {
514 for (int j = 0; j < flux[0].size(); ++j)
515 {
516 Vmath::Vmul(nq, physfieldInterp[i], 1, velocityInterp[j], 1,
517 fluxInterp[i][j], 1);
518 }
519 }
520
521 // Galerkin project solution back to original space
522 for (int i = 0; i < nVariables; ++i)
523 {
524 for (int j = 0; j < m_spacedim; ++j)
525 {
526 m_fields[0]->PhysGalerkinProjection1DScaled(
527 OneDptscale, fluxInterp[i][j], flux[i][j]);
528 }
529 }
530}
531
533{
534 AdvectionSystem::v_GenerateSummary(s);
536 {
538 s, "GJP Stab. Impl. ",
539 m_session->GetSolverInfo("GJPStabilisation"));
540 SolverUtils::AddSummaryItem(s, "GJP Stab. JumpScale", m_GJPJumpScale);
541 }
542}
543
544bool UnsteadyAdvection::v_PreIntegrate([[maybe_unused]] int step)
545{
546 return false;
547}
548
550 std::vector<Array<OneD, NekDouble>> &fieldcoeffs,
551 std::vector<std::string> &variables)
552{
553 bool extraFields;
554 m_session->MatchSolverInfo("OutputExtraFields", "True", extraFields, true);
555
556 if (extraFields && m_ALESolver)
557 {
558 ExtraFldOutputGridVelocity(fieldcoeffs, variables);
559 }
560}
561
564{
566 {
567 m_spaceDim = spaceDim;
568 m_fieldsALE = fields;
569
570 // Initialise grid velocities as 0s
573 for (int i = 0; i < spaceDim; ++i)
574 {
575 m_gridVelocity[i] =
576 Array<OneD, NekDouble>(fields[0]->GetTotPoints(), 0.0);
578 fields[0]->GetTrace()->GetTotPoints(), 0.0);
579 }
580 }
581 ALEHelper::InitObject(spaceDim, fields);
582}
583
584} // namespace Nektar
#define ASSERTL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
void DefineImplicitSolve(FuncPointerT func, ObjectPointerT obj)
void AccumulateRegion(std::string, int iolevel=0)
Accumulate elapsed time for a region.
Definition Timer.cpp:70
Array< OneD, MultiRegions::ExpListSharedPtr > m_fieldsALE
Definition ALEHelper.h:140
SOLVER_UTILS_EXPORT void InitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields)
Definition ALEHelper.cpp:48
Array< OneD, Array< OneD, NekDouble > > m_gridVelocityTrace
Definition ALEHelper.h:142
SOLVER_UTILS_EXPORT void ALEDoElmtInvMassBwdTrans(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
SOLVER_UTILS_EXPORT void ExtraFldOutputGridVelocity(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables)
SOLVER_UTILS_EXPORT void MoveMesh(const NekDouble &time, Array< OneD, Array< OneD, NekDouble > > &traceNormals)
Array< OneD, Array< OneD, NekDouble > > m_gridVelocity
Definition ALEHelper.h:141
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Initialisation object for EquationSystem.
int m_spacedim
Spatial dimension (>= expansion dim).
NekDouble m_timestep
Time step size.
SOLVER_UTILS_EXPORT int GetTraceNpoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
SOLVER_UTILS_EXPORT int GetNpoints()
bool m_specHP_dealiasing
Flag to determine if dealisising is usde for the Spectral/hp element discretisation.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
Array< OneD, Array< OneD, NekDouble > > m_traceNormals
Array holding trace normals for DG simulations in the forwards direction.
SOLVER_UTILS_EXPORT int GetTotPoints()
enum MultiRegions::ProjectionType m_projectionType
Type of projection; e.g continuous or discontinuous.
SOLVER_UTILS_EXPORT void SetBoundaryConditions(NekDouble time)
Evaluates the boundary conditions at the given time.
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(std::string name, const MultiRegions::ExpListSharedPtr &field=MultiRegions::NullExpListSharedPtr, bool cache=false)
Get a SessionFunction by name.
static SOLVER_UTILS_EXPORT std::vector< ForcingSharedPtr > Load(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields=0)
Definition Forcing.cpp:76
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
bool m_explicitAdvection
Indicates if explicit or implicit treatment of advection is used.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
void v_ALEInitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields) override
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void v_ExtraFldOutput(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables) override
Array< OneD, NekDouble > m_traceVn
Array< OneD, NekDouble > & GetNormalVel(const Array< OneD, const Array< OneD, NekDouble > > &velfield)
Get the normal velocity based on input velfield.
void DoImplicitSolve(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time, const NekDouble lambda)
Implicit solution of the unsteady advection problem.
StdRegions::VarCoeffMap m_varcoeffs
static std::string className
Name of class.
Array< OneD, NekDouble > & GetNormalVelocity()
Get the normal velocity.
void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print Summary.
Array< OneD, Array< OneD, NekDouble > > m_velocity
Advection velocity.
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the RHS.
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the projection.
void GetFluxVectorDeAlias(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Evaluate the flux at each solution point using dealiasing.
UnsteadyAdvection(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
void v_InitObject(bool DeclareFields=true) override
Initialise the object.
void GetFluxVector(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Evaluate the flux at each solution point.
SolverUtils::RiemannSolverSharedPtr m_riemannSolver
bool v_PreIntegrate(int step) override
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< GJPStabilisation > GJPStabilisationSharedPtr
std::shared_ptr< ContField > ContFieldSharedPtr
Definition ContField.h:295
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition Advection.cpp:43
std::vector< std::pair< std::string, std::string > > SummaryList
Definition Misc.h:46
EquationSystemFactory & GetEquationSystemFactory()
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition Misc.cpp:47
RiemannSolverFactory & GetRiemannSolverFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition MeshGraph.h:224
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
std::map< ConstFactorType, NekDouble > ConstFactorMap
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
static Array< OneD, NekDouble > NullNekDouble1DArray
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 Neg(int n, T *x, const int incx)
Negate x = -x.
Definition Vmath.hpp:292
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 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
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.hpp:220