Nektar++
ContField.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: ContField.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: Field definition for a continuous domain with boundary
32// conditions
33//
34///////////////////////////////////////////////////////////////////////////////
35
38#include <tuple>
39
40using namespace std;
41
42namespace Nektar
43{
44namespace MultiRegions
45{
46/**
47 * @class ContField
48 * The class #ContField is
49 * able to incorporate the boundary conditions imposed to the problem
50 * to be solved. Therefore, the class is equipped with three additional
51 * data members:
52 * - #m_bndCondExpansions
53 * - #m_bndTypes
54 * - #m_bndCondEquations
55 *
56 * The first data structure, #m_bndCondExpansions, contains the
57 * one-dimensional spectral/hp expansion on the boundary, #m_bndTypes
58 * stores information about the type of boundary condition on the
59 * different parts of the boundary while #m_bndCondEquations holds the
60 * equation of the imposed boundary conditions.
61 *
62 * Furthermore, in case of Dirichlet boundary conditions, this class is
63 * capable of lifting a known solution satisfying these boundary
64 * conditions. If we denote the unknown solution by
65 * \f$u^{\mathcal{H}}(\boldsymbol{x})\f$ and the known Dirichlet
66 * boundary conditions by \f$u^{\mathcal{D}}(\boldsymbol{x})\f$, the
67 * expansion then can be decomposed as
68 * \f[ u^{\delta}(\boldsymbol{x}_i)=u^{\mathcal{D}}(\boldsymbol{x}_i)+
69 * u^{\mathcal{H}}(\boldsymbol{x}_i)=\sum_{n=0}^{N^{\mathcal{D}}-1}
70 * \hat{u}_n^{\mathcal{D}}\Phi_n(\boldsymbol{x}_i)+
71 * \sum_{n={N^{\mathcal{D}}}}^{N_{\mathrm{dof}}-1}
72 * \hat{u}_n^{\mathcal{H}} \Phi_n(\boldsymbol{x}_i).\f]
73 * This lifting is accomplished by ordering the known global degrees of
74 * freedom, prescribed by the Dirichlet boundary conditions, first in
75 * the global array
76 * \f$\boldsymbol{\hat{u}}\f$, that is,
77 * \f[\boldsymbol{\hat{u}}=\left[ \begin{array}{c}
78 * \boldsymbol{\hat{u}}^{\mathcal{D}}\\
79 * \boldsymbol{\hat{u}}^{\mathcal{H}}
80 * \end{array} \right].\f]
81 * Such kind of expansions are also referred to as continuous fields.
82 * This class should be used when solving 2D problems using a standard
83 * Galerkin approach.
84 */
85
86/**
87 *
88 */
90 : DisContField(), m_locToGloMap(), m_globalMat(),
91 m_globalLinSysManager(
92 std::bind(&ContField::GenGlobalLinSys, this, std::placeholders::_1),
93 std::string("GlobalLinSys"))
94{
95}
96
97/**
98 * Given a mesh \a graph, containing information about the domain and
99 * the spectral/hp element expansion, this constructor fills the list
100 * of local expansions #m_exp with the proper expansions, calculates
101 * the total number of quadrature points \f$\boldsymbol{x}_i\f$ and
102 * local expansion coefficients \f$\hat{u}^e_n\f$ and allocates memory
103 * for the arrays #m_coeffs and #m_phys. Furthermore, it constructs the
104 * mapping array (contained in #m_locToGloMap) for the transformation
105 * between local elemental level and global level, it calculates the
106 * total number global expansion coefficients \f$\hat{u}_n\f$ and
107 * allocates memory for the array #m_contCoeffs. The constructor also
108 * discretises the boundary conditions, specified by the argument \a
109 * bcs, by expressing them in terms of the coefficient of the expansion
110 * on the boundary.
111 *
112 * @param graph A mesh, containing information about the domain
113 * and the spectral/hp element expansion.
114 * @param bcs The boundary conditions.
115 * @param variable An optional parameter to indicate for which
116 * variable the field should be constructed.
117 */
120 const std::string &variable,
121 const bool DeclareCoeffPhysArrays,
122 const bool CheckIfSingularSystem,
124 : DisContField(pSession, graph, variable, false, DeclareCoeffPhysArrays,
125 ImpType),
126 m_globalMat(MemoryManager<GlobalMatrixMap>::AllocateSharedPtr()),
127 m_globalLinSysManager(
128 std::bind(&ContField::GenGlobalLinSys, this, std::placeholders::_1),
129 std::string("GlobalLinSys"))
130{
133 CheckIfSingularSystem, variable, m_periodicVerts, m_periodicEdges,
135
136 if (m_session->DefinesCmdLineArgument("verbose"))
137 {
138 m_locToGloMap->PrintStats(std::cout, variable);
139 }
140}
141
142/**
143 * Given a mesh \a graph, containing information about the domain and
144 * the spectral/hp element expansion, this constructor fills the list
145 * of local expansions #m_exp with the proper expansions, calculates
146 * the total number of quadrature points \f$\boldsymbol{x}_i\f$ and
147 * local expansion coefficients \f$\hat{u}^e_n\f$ and allocates memory
148 * for the arrays #m_coeffs and #m_phys. Furthermore, it constructs the
149 * mapping array (contained in #m_locToGloMap) for the transformation
150 * between local elemental level and global level, it calculates the
151 * total number global expansion coefficients \f$\hat{u}_n\f$ and
152 * allocates memory for the array #m_coeffs. The constructor also
153 * discretises the boundary conditions, specified by the argument \a
154 * bcs, by expressing them in terms of the coefficient of the expansion
155 * on the boundary.
156 *
157 * @param In Existing ContField object used to provide the
158 * local to global mapping information and
159 * global solution type.
160 * @param graph A mesh, containing information about the domain
161 * and the spectral/hp element expansion.
162 * @param bcs The boundary conditions.
163 * @param bc_loc
164 */
167 const std::string &variable, bool DeclareCoeffPhysArrays,
168 const bool CheckIfSingularSystem)
169 : DisContField(In, graph, variable, false, DeclareCoeffPhysArrays),
170 m_globalMat(MemoryManager<GlobalMatrixMap>::AllocateSharedPtr()),
171 m_globalLinSysManager(
172 std::bind(&ContField::GenGlobalLinSys, this, std::placeholders::_1),
173 std::string("GlobalLinSys")),
174 m_GJPData(In.m_GJPData)
175{
176 if (!SameTypeOfBoundaryConditions(In) || CheckIfSingularSystem)
177 {
180 CheckIfSingularSystem, variable, m_periodicVerts, m_periodicEdges,
182
183 if (m_session->DefinesCmdLineArgument("verbose"))
184 {
185 m_locToGloMap->PrintStats(std::cout, variable);
186 }
187 }
188 else
189 {
191 }
192}
193
194/**
195 * Initialises the object as a copy of an existing ContField object.
196 * @param In Existing ContField object.
197 * @param DeclareCoeffPhysArrays bool to declare if \a m_phys
198 * and \a m_coeffs should be declared. Default is true
199 */
200ContField::ContField(const ContField &In, bool DeclareCoeffPhysArrays)
201 : DisContField(In, DeclareCoeffPhysArrays), m_locToGloMap(In.m_locToGloMap),
202 m_globalMat(In.m_globalMat),
203 m_globalLinSysManager(In.m_globalLinSysManager), m_GJPData(In.m_GJPData)
204{
205}
206
207/**
208 * Constructs a continuous field as a copy of an existing
209 * explist field and adding all the boundary conditions.
210 *
211 * @param In Existing explist1D field .
212 */
214 const ExpList &In)
215 : DisContField(In), m_locToGloMap(),
216 m_globalLinSysManager(
217 std::bind(&ContField::GenGlobalLinSys, this, std::placeholders::_1),
218 std::string("GlobalLinSys"))
219{
221 pSession, m_ncoeffs, In);
222}
223
224/**
225 *
226 */
228{
229}
230
231/**
232 * Given a function \f$f(\boldsymbol{x})\f$ defined at the quadrature
233 * points, this function determines the unknown global coefficients
234 * \f$\boldsymbol{\hat{u}}^{\mathcal{H}}\f$ employing a discrete
235 * Galerkin projection from physical space to coefficient
236 * space. The operation is evaluated by the function #GlobalSolve using
237 * the global mass matrix.
238 *
239 * The values of the function \f$f(\boldsymbol{x})\f$ evaluated at the
240 * quadrature points \f$\boldsymbol{x}_i\f$ should be contained in the
241 * variable #inarray of the ExpList object \a Sin. The resulting global
242 * coefficients \f$\hat{u}_g\f$ are stored in the array #outarray.
243 */
245 Array<OneD, NekDouble> &outarray)
246
247{
248 // Inner product of forcing
250 IProductWRTBase(inarray, wsp);
251
252 // Solve the system
254
255 GlobalSolve(key, wsp, outarray);
256}
257
258/**
259 *
260 */
262{
263 int Ncoeffs = m_locToGloMap->GetNumLocalCoeffs();
264 Array<OneD, NekDouble> tmp1(Ncoeffs);
265 Array<OneD, NekDouble> tmp2(Ncoeffs);
266
267 IProductWRTBase(field, tmp1);
268 MultiplyByInvMassMatrix(tmp1, tmp2);
269 BwdTrans(tmp2, field);
270}
271
272/**
273 * Computes the matrix vector product
274 * @f$ \mathbf{y} = \mathbf{M}^{-1}\mathbf{x} @f$.
275 *
276 * @param inarray Input vector @f$\mathbf{x}@f$.
277 * @param outarray Output vector @f$\mathbf{y}@f$.
278 */
280 const Array<OneD, const NekDouble> &inarray,
281 Array<OneD, NekDouble> &outarray)
282
283{
285 GlobalSolve(key, inarray, outarray);
286}
287
288/**
289 * Consider the two dimensional Laplace equation,
290 * \f[\nabla\cdot\left(\boldsymbol{\sigma}\nabla
291 * u(\boldsymbol{x})\right) = f(\boldsymbol{x}),\f] supplemented with
292 * appropriate boundary conditions (which are contained in the data
293 * member #m_bndCondExpansions). In the equation above
294 * \f$\boldsymbol{\sigma}\f$ is the (symmetric positive definite)
295 * diffusion tensor:
296 * \f[ \sigma = \left[ \begin{array}{cc}
297 * \sigma_{00}(\boldsymbol{x},t) & \sigma_{01}(\boldsymbol{x},t) \\
298 * \sigma_{01}(\boldsymbol{x},t) & \sigma_{11}(\boldsymbol{x},t)
299 * \end{array} \right]. \f]
300 * Applying a \f$C^0\f$ continuous Galerkin discretisation, this
301 * equation leads to the following linear system:
302 * \f[\boldsymbol{L}
303 * \boldsymbol{\hat{u}}_g=\boldsymbol{\hat{f}}\f]
304 * where \f$\boldsymbol{L}\f$ is the Laplacian matrix. This function
305 * solves the system above for the global coefficients
306 * \f$\boldsymbol{\hat{u}}\f$ by a call to the function #GlobalSolve.
307 *
308 * The values of the function \f$f(\boldsymbol{x})\f$ evaluated at the
309 * quadrature points \f$\boldsymbol{x}_i\f$ should be contained in the
310 * variable #inarray
311 *
312 * @param inarray An Array<OneD, NekDouble> containing the discrete
313 * evaluation of the forcing function
314 * \f$f(\boldsymbol{x})\f$ at the quadrature
315 * points.
316 *
317 * @param outarray An Array<OneD, NekDouble> containing the
318 * coefficients of the solution
319 *
320 * @param variablecoeffs The (optional) parameter containing the
321 * coefficients evaluated at the quadrature
322 * points. It is an Array of (three) arrays which
323 * stores the laplacian coefficients in the
324 * following way
325 * \f[\mathrm{variablecoeffs} = \left[ \begin{array}{c}
326 * \left[\sigma_{00}(\boldsymbol{x_i},t)\right]_i \\
327 * \left[\sigma_{01}(\boldsymbol{x_i},t)\right]_i \\
328 * \left[\sigma_{11}(\boldsymbol{x_i},t)\right]_i
329 * \end{array}\right]
330 * \f]
331 * If this argument is not passed to the function, the following
332 * equation will be solved:
333 * \f[\nabla^2u(\boldsymbol{x}) = f(\boldsymbol{x}),\f]
334 *
335 * @param time The time-level at which the coefficients are
336 * evaluated
337 */
339 const Array<OneD, const NekDouble> &inarray,
340 Array<OneD, NekDouble> &outarray,
341 const Array<OneD, const NekDouble> &dirForcing,
342 const Array<OneD, Array<OneD, NekDouble>> &variablecoeffs, NekDouble time)
343{
344 // Inner product of forcing
346 IProductWRTBase(inarray, wsp);
347
348 // Note -1.0 term necessary to invert forcing function to
349 // be consistent with matrix definition
350 Vmath::Neg(m_ncoeffs, wsp, 1);
351
352 // Forcing function with weak boundary conditions
353 int i, j;
354 int bndcnt = 0;
356 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsSign();
357 const Array<OneD, const int> map =
358 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsMap();
359
360 // Add weak boundary conditions to forcing
361 for (i = 0; i < m_bndCondExpansions.size(); ++i)
362 {
363 if (m_bndConditions[i]->GetBoundaryConditionType() ==
365 m_bndConditions[i]->GetBoundaryConditionType() ==
367 {
368
369 const Array<OneD, const NekDouble> bndcoeff =
371
372 if (m_locToGloMap->GetSignChange())
373 {
374 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
375 {
376 wsp[map[bndcnt + j]] += sign[bndcnt + j] * bndcoeff[j];
377 }
378 }
379 else
380 {
381 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
382 {
383 wsp[map[bndcnt + j]] += bndcoeff[bndcnt + j];
384 }
385 }
386 }
387
388 bndcnt += m_bndCondExpansions[i]->GetNcoeffs();
389 }
390
391 StdRegions::VarCoeffMap varcoeffs;
392 varcoeffs[StdRegions::eVarCoeffD00] = variablecoeffs[0];
393 varcoeffs[StdRegions::eVarCoeffD01] = variablecoeffs[1];
394 varcoeffs[StdRegions::eVarCoeffD11] = variablecoeffs[3];
395 varcoeffs[StdRegions::eVarCoeffD22] = variablecoeffs[5];
398
399 // Solve the system
401 varcoeffs);
402
403 GlobalSolve(key, wsp, outarray, dirForcing);
404}
405
406/**
407 * Constructs the GlobalLinearSysKey for the linear advection operator
408 * with the supplied parameters, and computes the eigenvectors and
409 * eigenvalues of the associated matrix.
410 * @param ax Advection parameter, x.
411 * @param ay Advection parameter, y.
412 * @param Real Computed eigenvalues, real component.
413 * @param Imag Computed eigenvalues, imag component.
414 * @param Evecs Computed eigenvectors.
415 */
420{
421 // Solve the system
425 vel[0] = vel_x;
426 vel[1] = vel_y;
427
428 StdRegions::VarCoeffMap varcoeffs;
429 varcoeffs[StdRegions::eVarCoeffVelX] =
431 varcoeffs[StdRegions::eVarCoeffVelY] =
436 factors, varcoeffs);
437
439 Gmat->EigenSolve(Real, Imag, Evecs);
440}
441
442/**
443 * Given a linear system specified by the key \a key,
444 * \f[\boldsymbol{M}\boldsymbol{\hat{u}}_g=\boldsymbol{\hat{f}},\f]
445 * this function solves this linear system taking into account the
446 * boundary conditions specified in the data member
447 * #m_bndCondExpansions. Therefore, it adds an array
448 * \f$\boldsymbol{\hat{g}}\f$ which represents the non-zero surface
449 * integral resulting from the weak boundary conditions (e.g. Neumann
450 * boundary conditions) to the right hand side, that is,
451 * \f[\boldsymbol{M}\boldsymbol{\hat{u}}_g=\boldsymbol{\hat{f}}+
452 * \boldsymbol{\hat{g}}.\f]
453 * Furthermore, it lifts the known degrees of freedom which are
454 * prescribed by the Dirichlet boundary conditions. As these known
455 * coefficients \f$\boldsymbol{\hat{u}}^{\mathcal{D}}\f$ are numbered
456 * first in the global coefficient array \f$\boldsymbol{\hat{u}}_g\f$,
457 * the linear system can be decomposed as,
458 * \f[\left[\begin{array}{cc}
459 * \boldsymbol{M}^{\mathcal{DD}}&\boldsymbol{M}^{\mathcal{DH}}\\
460 * \boldsymbol{M}^{\mathcal{HD}}&\boldsymbol{M}^{\mathcal{HH}}
461 * \end{array}\right]
462 * \left[\begin{array}{c}
463 * \boldsymbol{\hat{u}}^{\mathcal{D}}\\
464 * \boldsymbol{\hat{u}}^{\mathcal{H}}
465 * \end{array}\right]=
466 * \left[\begin{array}{c}
467 * \boldsymbol{\hat{f}}^{\mathcal{D}}\\
468 * \boldsymbol{\hat{f}}^{\mathcal{H}}
469 * \end{array}\right]+
470 * \left[\begin{array}{c}
471 * \boldsymbol{\hat{g}}^{\mathcal{D}}\\
472 * \boldsymbol{\hat{g}}^{\mathcal{H}}
473 * \end{array}\right]
474 * \f]
475 * which will then be solved for the unknown coefficients
476 * \f$\boldsymbol{\hat{u}}^{\mathcal{H}}\f$ as,
477 * \f[
478 * \boldsymbol{M}^{\mathcal{HH}}\boldsymbol{\hat{u}}^{\mathcal{H}}=
479 * \boldsymbol{\hat{f}}^{\mathcal{H}}+
480 * \boldsymbol{\hat{g}}^{\mathcal{H}}-
481 * \boldsymbol{M}^{\mathcal{HD}}\boldsymbol{\hat{u}}^{\mathcal{D}}\f]
482 *
483 * @param mkey This key uniquely defines the linear system to
484 * be solved.
485 * @param locrhs contains the forcing term in local coefficient space
486 * @note inout contains initial guess and final output in local coeffs.
487 */
489 const Array<OneD, const NekDouble> &locrhs,
491 const Array<OneD, const NekDouble> &dirForcing)
492{
493 int NumDirBcs = m_locToGloMap->GetNumGlobalDirBndCoeffs();
494 int contNcoeffs = m_locToGloMap->GetNumGlobalCoeffs();
495
496 // STEP 1: SET THE DIRICHLET DOFS TO THE RIGHT VALUE
497 // IN THE SOLUTION ARRAY
499
500 // STEP 2: CALCULATE THE HOMOGENEOUS COEFFICIENTS
501 if (contNcoeffs - NumDirBcs > 0)
502 {
504 LinSys->Solve(locrhs, inout, m_locToGloMap, dirForcing);
505 }
506}
507
508/**
509 * Returns the global matrix associated with the given GlobalMatrixKey.
510 * If the global matrix has not yet been constructed on this field,
511 * it is first constructed using GenGlobalMatrix().
512 * @param mkey Global matrix key.
513 * @returns Assocated global matrix.
514 */
516{
518 "To use method must have a AssemblyMap "
519 "attached to key");
520
521 GlobalMatrixSharedPtr glo_matrix;
522 auto matrixIter = m_globalMat->find(mkey);
523
524 if (matrixIter == m_globalMat->end())
525 {
526 glo_matrix = GenGlobalMatrix(mkey, m_locToGloMap);
527 (*m_globalMat)[mkey] = glo_matrix;
528 }
529 else
530 {
531 glo_matrix = matrixIter->second;
532 }
533
534 return glo_matrix;
535}
536
537/**
538 * The function searches the map #m_globalLinSys to see if the
539 * global matrix has been created before. If not, it calls the function
540 * #GenGlobalLinSys to generate the requested global system.
541 *
542 * @param mkey This key uniquely defines the requested
543 * linear system.
544 */
546{
547 return m_globalLinSysManager[mkey];
548}
549
551{
553 "To use method must have a AssemblyMap "
554 "attached to key");
556}
557
559{
560 int i, j;
561 int bndcnt = 0;
562
564 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsSign();
565 const Array<OneD, const int> map =
566 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsMap();
567
568 for (i = 0; i < m_bndCondExpansions.size(); ++i)
569 {
570 if (m_bndConditions[i]->GetBoundaryConditionType() ==
572 {
573
574 const Array<OneD, const NekDouble> bndcoeff =
576
577 if (m_locToGloMap->GetSignChange())
578 {
579 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
580 {
581 outarray[map[bndcnt + j]] = sign[bndcnt + j] * bndcoeff[j];
582 }
583 }
584 else
585 {
586 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
587 {
588 outarray[map[bndcnt + j]] = bndcoeff[j];
589 }
590 }
591 }
592 bndcnt += m_bndCondExpansions[i]->GetNcoeffs();
593 }
594
595 // communicate local Dirichlet coeffs that are just
596 // touching a dirichlet boundary on another partition
597 set<int> &ParallelDirBndSign = m_locToGloMap->GetParallelDirBndSign();
598
599 for (auto &it : ParallelDirBndSign)
600 {
601 outarray[it] *= -1;
602 }
603
604 m_locToGloMap->UniversalAbsMaxBnd(outarray);
605
606 for (auto &it : ParallelDirBndSign)
607 {
608 outarray[it] *= -1;
609 }
610
611 set<ExtraDirDof> &copyLocalDirDofs = m_locToGloMap->GetCopyLocalDirDofs();
612 for (auto &it : copyLocalDirDofs)
613 {
614 outarray[std::get<0>(it)] = outarray[std::get<1>(it)] * std::get<2>(it);
615 }
616}
617
619{
620 int bndcnt = 0;
621
623 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsSign();
624 const Array<OneD, const int> bndmap =
625 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsMap();
626
627 for (int i = 0; i < m_bndCondExpansions.size(); ++i)
628 {
629 Array<OneD, NekDouble> &bcoeffs =
630 m_bndCondExpansions[i]->UpdateCoeffs();
631
632 if (m_locToGloMap->GetSignChange())
633 {
634 for (int j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j)
635 {
636 bcoeffs[j] = sign[bndcnt + j] * coeffs[bndmap[bndcnt + j]];
637 }
638 }
639 else
640 {
641 for (int j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j)
642 {
643 bcoeffs[j] = coeffs[bndmap[bndcnt + j]];
644 }
645 }
646
647 bndcnt += m_bndCondExpansions[i]->GetNcoeffs();
648 }
649}
650
652 const Array<OneD, NekDouble> coeffs)
653{
654 int bndcnt = 0;
655
656 ASSERTL1(nreg < m_bndCondExpansions.size(),
657 "nreg is out or range since this many boundary "
658 "regions to not exist");
659
661 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsSign();
662 const Array<OneD, const int> bndmap =
663 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsMap();
664
665 // Now fill in all other Dirichlet coefficients.
666 Array<OneD, NekDouble> &bcoeffs = m_bndCondExpansions[nreg]->UpdateCoeffs();
667
668 for (int j = 0; j < nreg; ++j)
669 {
670 bndcnt += m_bndCondExpansions[j]->GetNcoeffs();
671 }
672
673 if (m_locToGloMap->GetSignChange())
674 {
675 for (int j = 0; j < (m_bndCondExpansions[nreg])->GetNcoeffs(); ++j)
676 {
677 bcoeffs[j] = sign[bndcnt + j] * coeffs[bndmap[bndcnt + j]];
678 }
679 }
680 else
681 {
682 for (int j = 0; j < (m_bndCondExpansions[nreg])->GetNcoeffs(); ++j)
683 {
684 bcoeffs[j] = coeffs[bndmap[bndcnt + j]];
685 }
686 }
687}
688
689/**
690 * This operation is evaluated as:
691 * \f{tabbing}
692 * \hspace{1cm} \= Do \= $e=$ $1, N_{\mathrm{el}}$ \\
693 * > > Do \= $i=$ $0,N_m^e-1$ \\
694 * > > > $\boldsymbol{\hat{u}}^{e}[i] = \mbox{sign}[e][i] \cdot
695 * \boldsymbol{\hat{u}}_g[\mbox{map}[e][i]]$ \\
696 * > > continue \\
697 * > continue
698 * \f}
699 * where \a map\f$[e][i]\f$ is the mapping array and \a
700 * sign\f$[e][i]\f$ is an array of similar dimensions ensuring the
701 * correct modal connectivity between the different elements (both
702 * these arrays are contained in the data member #m_locToGloMap). This
703 * operation is equivalent to the scatter operation
704 * \f$\boldsymbol{\hat{u}}_l=\mathcal{A}\boldsymbol{\hat{u}}_g\f$,
705 * where \f$\mathcal{A}\f$ is the
706 * \f$N_{\mathrm{eof}}\times N_{\mathrm{dof}}\f$ permutation matrix.
707 *
708 */
710 Array<OneD, NekDouble> &outarray)
711{
712 m_locToGloMap->GlobalToLocal(inarray, outarray);
713}
714
716{
717 m_locToGloMap->GlobalToLocal(m_coeffs, m_coeffs);
718}
719
720/**
721 * This operation is evaluated as:
722 * \f{tabbing}
723 * \hspace{1cm} \= Do \= $e=$ $1, N_{\mathrm{el}}$ \\
724 * > > Do \= $i=$ $0,N_m^e-1$ \\
725 * > > > $\boldsymbol{\hat{u}}_g[\mbox{map}[e][i]] =
726 * \mbox{sign}[e][i] \cdot \boldsymbol{\hat{u}}^{e}[i]$\\
727 * > > continue\\
728 * > continue
729 * \f}
730 * where \a map\f$[e][i]\f$ is the mapping array and \a
731 * sign\f$[e][i]\f$ is an array of similar dimensions ensuring the
732 * correct modal connectivity between the different elements (both
733 * these arrays are contained in the data member #m_locToGloMap). This
734 * operation is equivalent to the gather operation
735 * \f$\boldsymbol{\hat{u}}_g=\mathcal{A}^{-1}\boldsymbol{\hat{u}}_l\f$,
736 * where \f$\mathcal{A}\f$ is the
737 * \f$N_{\mathrm{eof}}\times N_{\mathrm{dof}}\f$ permutation matrix.
738 *
739 */
740
742 Array<OneD, NekDouble> &outarray, bool useComm)
743{
744 m_locToGloMap->LocalToGlobal(inarray, outarray, useComm);
745}
746
748
749{
750 m_locToGloMap->LocalToGlobal(m_coeffs, m_coeffs, useComm);
751}
752
753/**
754 * Consider the two dimensional Helmholtz equation,
755 * \f[\nabla^2u(\boldsymbol{x})-\lambda u(\boldsymbol{x})
756 * = f(\boldsymbol{x}),\f] supplemented with appropriate boundary
757 * conditions (which are contained in the data member
758 * #m_bndCondExpansions). Applying a \f$C^0\f$ continuous Galerkin
759 * discretisation, this equation leads to the following linear system:
760 * \f[\left(\boldsymbol{L}+\lambda\boldsymbol{M}\right)
761 * \boldsymbol{\hat{u}}_g=\boldsymbol{\hat{f}}\f] where
762 * \f$\boldsymbol{L}\f$ and \f$\boldsymbol{M}\f$ are the Laplacian and
763 * mass matrix respectively. This function solves the system above for
764 * the global coefficients \f$\boldsymbol{\hat{u}}\f$ by a call to the
765 * function #GlobalSolve.
766 *
767 * @param inarray An Array<OneD, NekDouble> , containing the discrete
768 * evaluation of the forcing function
769 * \f$f(\boldsymbol{x})\f$ at the quadrature
770 * points
771 * @param factors The parameter \f$\lambda\f$ of the Helmholtz
772 * equation is specified through the factors map
773 */
775 const Array<OneD, const NekDouble> &inarray,
777 const StdRegions::VarCoeffMap &pvarcoeff,
778 const MultiRegions::VarFactorsMap &varfactors,
779 const Array<OneD, const NekDouble> &dirForcing, const bool PhysSpaceForcing)
780{
781 int i, j;
782
783 //----------------------------------
784 // Setup RHS Inner product
785 //----------------------------------
786 // Inner product of forcing
788 if (PhysSpaceForcing)
789 {
790 IProductWRTBase(inarray, wsp);
791 // Note -1.0 term necessary to invert forcing function to
792 // be consistent with matrix definition
793 Vmath::Neg(m_ncoeffs, wsp, 1);
794 }
795 else
796 {
797 Vmath::Smul(m_ncoeffs, -1.0, inarray, 1, wsp, 1);
798 }
799
800 int bndcnt = 0;
802 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsSign();
803 const Array<OneD, const int> map =
804 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsMap();
805 // Add weak boundary conditions to forcing
806 for (i = 0; i < m_bndCondExpansions.size(); ++i)
807 {
808 if (m_bndConditions[i]->GetBoundaryConditionType() ==
810 m_bndConditions[i]->GetBoundaryConditionType() ==
812 {
813
814 const Array<OneD, const NekDouble> bndcoeff =
816
817 if (m_locToGloMap->GetSignChange())
818 {
819 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
820 {
821 wsp[map[bndcnt + j]] += sign[bndcnt + j] * bndcoeff[j];
822 }
823 }
824 else
825 {
826 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
827 {
828 wsp[map[bndcnt + j]] += bndcoeff[j];
829 }
830 }
831 }
832 bndcnt += m_bndCondExpansions[i]->GetNcoeffs();
833 }
834
836
837 StdRegions::VarCoeffMap varcoeff(pvarcoeff);
839 {
840 // initialize if required
841 if (!m_GJPData)
842 {
845 }
846
847 if (m_GJPData->IsSemiImplicit())
848 {
850 }
851
852 // to set up forcing need initial guess in physical space
854 BwdTrans(outarray, phys);
855 NekDouble scale = -1.0 * factors.find(StdRegions::eFactorGJP)->second;
856
857 m_GJPData->Apply(phys, wsp,
858 pvarcoeff.count(StdRegions::eVarCoeffGJPNormVel)
859 ? pvarcoeff.find(StdRegions::eVarCoeffGJPNormVel)
860 ->second.GetValue()
862 scale);
863
864 varcoeff.erase(StdRegions::eVarCoeffGJPNormVel);
865 }
866
867 GlobalLinSysKey key(mtype, m_locToGloMap, factors, varcoeff, varfactors);
868
869 GlobalSolve(key, wsp, outarray, dirForcing);
870
871 return key;
872}
873
874/**
875 * First compute the inner product of forcing function with respect to
876 * base, and then solve the system with the linear advection operator.
877 * @param velocity Array of advection velocities in physical space
878 * @param inarray Forcing function.
879 * @param outarray Result.
880 * @param lambda reaction coefficient
881 * @param dirForcing Dirichlet Forcing.
882 */
883
884// could combine this with HelmholtzCG.
886 const Array<OneD, const NekDouble> &inarray,
888 const StdRegions::VarCoeffMap &pvarcoeff,
889 const MultiRegions::VarFactorsMap &varfactors,
890 const Array<OneD, const NekDouble> &dirForcing, const bool PhysSpaceForcing)
891{
892 // Inner product of forcing
894 if (PhysSpaceForcing)
895 {
896 IProductWRTBase(inarray, wsp);
897 // Note -1.0 term necessary to invert forcing function to
898 // be consistent with matrix definition
899 Vmath::Neg(m_ncoeffs, wsp, 1);
900 }
901 else
902 {
903 Vmath::Smul(m_ncoeffs, -1.0, inarray, 1, wsp, 1);
904 }
905
906 // Forcing function with weak boundary conditions
907 int i, j;
908 int bndcnt = 0;
910 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsSign();
911 const Array<OneD, const int> map =
912 m_locToGloMap->GetBndCondCoeffsToLocalCoeffsMap();
913 // Add weak boundary conditions to forcing
914 for (i = 0; i < m_bndCondExpansions.size(); ++i)
915 {
916 if (m_bndConditions[i]->GetBoundaryConditionType() ==
918 m_bndConditions[i]->GetBoundaryConditionType() ==
920 {
921
922 const Array<OneD, const NekDouble> bndcoeff =
924
925 if (m_locToGloMap->GetSignChange())
926 {
927 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
928 {
929 wsp[map[bndcnt + j]] += sign[bndcnt + j] * bndcoeff[j];
930 }
931 }
932 else
933 {
934 for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); j++)
935 {
936 wsp[map[bndcnt + j]] += bndcoeff[bndcnt + j];
937 }
938 }
939 }
940
941 bndcnt += m_bndCondExpansions[i]->GetNcoeffs();
942 }
943
946
947 StdRegions::VarCoeffMap varcoeff(pvarcoeff);
949 {
950 // initialize if required
951 if (!m_GJPData)
952 {
955 }
956
957 if (m_GJPData->IsSemiImplicit())
958 {
960 }
961
962 // to set up forcing need initial guess in physical space
964 BwdTrans(outarray, phys);
965 NekDouble scale = -1.0 * factors.find(StdRegions::eFactorGJP)->second;
966 /*
967 Array<OneD, NekDouble> tmp;
968 tmp = pvarcoeff.count(StdRegions::eVarCoeffGJPNormVel)
969 ? pvarcoeff.find(StdRegions::eVarCoeffGJPNormVel)
970 ->second.GetValue()
971 : NullNekDouble1DArray;
972 */
973
974 m_GJPData->Apply(phys, wsp,
975 pvarcoeff.count(StdRegions::eVarCoeffGJPNormVel)
976 ? pvarcoeff.find(StdRegions::eVarCoeffGJPNormVel)
977 ->second.GetValue()
979 scale);
980
981 varcoeff.erase(StdRegions::eVarCoeffGJPNormVel);
982 }
983
984 // Solve the system
985 GlobalLinSysKey key(mtype, m_locToGloMap, factors, pvarcoeff, varfactors);
986
987 GlobalSolve(key, wsp, outarray, dirForcing);
988
989 return key;
990}
991
992/**
993 * First compute the inner product of forcing function with respect to
994 * base, and then solve the system with the linear advection operator.
995 * @param velocity Array of advection velocities in physical space
996 * @param inarray Forcing function.
997 * @param outarray Result.
998 * @param lambda reaction coefficient
999 * @param dirForcing Dirichlet Forcing.
1000 */
1002 const Array<OneD, Array<OneD, NekDouble>> &velocity,
1003 const Array<OneD, const NekDouble> &inarray,
1004 Array<OneD, NekDouble> &outarray, const NekDouble lambda,
1005 const Array<OneD, const NekDouble> &dirForcing)
1006{
1007 // Inner product of forcing
1009 IProductWRTBase(inarray, wsp);
1010
1011 // Solve the system
1014 StdRegions::VarCoeffMap varcoeffs;
1015 varcoeffs[StdRegions::eVarCoeffVelX] = velocity[0];
1016 varcoeffs[StdRegions::eVarCoeffVelY] = velocity[1];
1018 factors, varcoeffs);
1019
1020 GlobalSolve(key, wsp, outarray, dirForcing);
1021}
1022
1023/**
1024 * Reset the GlobalLinSys Manager
1025 */
1027{
1028 m_globalLinSysManager.ClearManager("GlobalLinSys");
1029}
1030
1031/**
1032 * Get the pool count for the specified poolName
1033 */
1034int ContField::v_GetPoolCount(std::string poolName)
1035{
1036 return m_globalLinSysManager.PoolCount(poolName);
1037}
1038
1039/**
1040 * Clear all memory for GlobalLinSys
1041 * including StaticCond Blocks and LocalMatrix Blocks.
1042 * Avoids memory leakage if matrices are updated in time
1043 */
1045 bool clearLocalMatrices)
1046{
1047 // Get GlobalLinSys from key
1049
1050 // Loop all expansions
1051 for (int n = 0; n < m_exp->size(); ++n)
1052 {
1053 LinSys->DropStaticCondBlock(n);
1054
1055 if (clearLocalMatrices)
1056 {
1057 LinSys->DropBlock(n);
1058 }
1059 }
1060
1061 m_globalLinSysManager.DeleteObject(key);
1062}
1063
1064} // namespace MultiRegions
1065} // namespace Nektar
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:49
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
This class is the abstraction of a global continuous two- dimensional spectral/hp element expansion w...
Definition: ContField.h:57
virtual void v_FillBndCondFromField(const Array< OneD, NekDouble > coeffs) override
Definition: ContField.cpp:618
virtual ~ContField()
The default destructor.
Definition: ContField.cpp:227
LibUtilities::NekManager< GlobalLinSysKey, GlobalLinSys > m_globalLinSysManager
A manager which collects all the global linear systems being assembled, such that they should be cons...
Definition: ContField.h:163
void LaplaceSolve(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray, const Array< OneD, Array< OneD, NekDouble > > &variablecoeffs=NullNekDoubleArrayOfArray, NekDouble time=0.0)
Solves the two-dimensional Laplace equation, subject to the boundary conditions specified.
Definition: ContField.cpp:338
GlobalLinSysSharedPtr GenGlobalLinSys(const GlobalLinSysKey &mkey)
Definition: ContField.cpp:550
virtual GlobalLinSysKey v_HelmSolve(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing) override
Solves the two-dimensional Helmholtz equation, subject to the boundary conditions specified.
Definition: ContField.cpp:774
AssemblyMapCGSharedPtr m_locToGloMap
(A shared pointer to) the object which contains all the required information for the transformation f...
Definition: ContField.h:152
virtual void v_FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Template method virtual forwarder for FwdTrans().
Definition: ContField.cpp:244
int v_GetPoolCount(std::string) override
Definition: ContField.cpp:1034
virtual void v_SmoothField(Array< OneD, NekDouble > &field) override
Template method virtual forwarded for SmoothField().
Definition: ContField.cpp:261
virtual void v_ClearGlobalLinSysManager(void) override
Definition: ContField.cpp:1026
virtual void v_GlobalToLocal(void) override
Definition: ContField.cpp:715
void v_UnsetGlobalLinSys(GlobalLinSysKey, bool) override
Definition: ContField.cpp:1044
virtual void v_LocalToGlobal(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool useComm) override
Gathers the global coefficients from the local coefficients .
Definition: ContField.cpp:741
GlobalMatrixMapShPtr m_globalMat
(A shared pointer to) a list which collects all the global matrices being assembled,...
Definition: ContField.h:157
virtual void v_LinearAdvectionReactionSolve(const Array< OneD, Array< OneD, NekDouble > > &velocity, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const NekDouble lambda, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray) override
Definition: ContField.cpp:1001
GlobalLinSysSharedPtr GetGlobalLinSys(const GlobalLinSysKey &mkey)
Returns the linear system specified by the key mkey.
Definition: ContField.cpp:545
virtual void v_ImposeDirichletConditions(Array< OneD, NekDouble > &outarray) override
Impose the Dirichlet Boundary Conditions on outarray.
Definition: ContField.cpp:558
virtual void v_MultiplyByInvMassMatrix(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Template method virtual forwarder for MultiplyByInvMassMatrix().
Definition: ContField.cpp:279
GlobalMatrixSharedPtr GetGlobalMatrix(const GlobalMatrixKey &mkey)
Returns the global matrix specified by mkey.
Definition: ContField.cpp:515
ContField()
The default constructor.
Definition: ContField.cpp:89
void LinearAdvectionEigs(const NekDouble ax, const NekDouble ay, Array< OneD, NekDouble > &Real, Array< OneD, NekDouble > &Imag, Array< OneD, NekDouble > &Evecs=NullNekDouble1DArray)
Compute the eigenvalues of the linear advection operator.
Definition: ContField.cpp:416
virtual GlobalLinSysKey v_LinearAdvectionDiffusionReactionSolve(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing) override
Definition: ContField.cpp:885
void GlobalSolve(const GlobalLinSysKey &key, const Array< OneD, const NekDouble > &rhs, Array< OneD, NekDouble > &inout, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray)
Solves the linear system specified by the key key.
Definition: ContField.cpp:488
GJPStabilisationSharedPtr m_GJPData
Data for Gradient Jump Penalisation (GJP) stabilisaiton.
Definition: ContField.h:166
This class is the abstractio n of a global discontinuous two- dimensional spectral/hp element expansi...
Definition: DisContField.h:58
PeriodicMap m_periodicEdges
A map which identifies pairs of periodic edges.
Definition: DisContField.h:179
PeriodicMap m_periodicFaces
A map which identifies pairs of periodic faces.
Definition: DisContField.h:184
bool SameTypeOfBoundaryConditions(const DisContField &In)
Check to see if expansion has the same BCs as In.
Array< OneD, SpatialDomains::BoundaryConditionShPtr > m_bndConditions
An array which contains the information about the boundary condition structure definition on the diff...
Definition: DisContField.h:137
PeriodicMap m_periodicVerts
A map which identifies groups of periodic vertices.
Definition: DisContField.h:174
Array< OneD, MultiRegions::ExpListSharedPtr > m_bndCondExpansions
An object which contains the discretised boundary conditions.
Definition: DisContField.h:150
Base class for all multi-elemental spectral/hp expansions.
Definition: ExpList.h:102
Array< OneD, NekDouble > m_coeffs
Concatenation of all local expansion coefficients.
Definition: ExpList.h:1092
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function calculates the inner product of a function with respect to all local expansion modes .
Definition: ExpList.h:1665
int GetNcoeffs(void) const
Returns the total number of local degrees of freedom .
Definition: ExpList.h:1527
std::shared_ptr< GlobalMatrix > GenGlobalMatrix(const GlobalMatrixKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
Generates a global matrix from the given key and map.
Definition: ExpList.cpp:2530
const Array< OneD, const NekDouble > & GetCoeffs() const
This function returns (a reference to) the array (implemented as m_coeffs) containing all local expa...
Definition: ExpList.h:1967
std::shared_ptr< ExpList > GetSharedThisPtr()
Returns a shared pointer to the current object.
Definition: ExpList.h:966
std::shared_ptr< GlobalLinSys > GenGlobalLinSys(const GlobalLinSysKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
This operation constructs the global linear system of type mkey.
Definition: ExpList.cpp:2815
std::shared_ptr< LocalRegions::ExpansionVector > m_exp
The list of local expansions.
Definition: ExpList.h:1127
int m_ncoeffs
The total number of local degrees of freedom. m_ncoeffs .
Definition: ExpList.h:1072
std::shared_ptr< DNekMat > GenGlobalMatrixFull(const GlobalLinSysKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
Definition: ExpList.cpp:2663
LibUtilities::SessionReaderSharedPtr m_session
Session.
Definition: ExpList.h:1067
void MultiplyByInvMassMatrix(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: ExpList.h:1740
void BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function elementally evaluates the backward transformation of the global spectral/hp element exp...
Definition: ExpList.h:1732
Describes a matrix with ordering defined by a local to global map.
bool LocToGloMapIsDefined() const
Returns true if a local to global map is defined.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< GlobalLinSys > GlobalLinSysSharedPtr
Pointer to a GlobalLinSys object.
Definition: GlobalLinSys.h:53
std::shared_ptr< GlobalMatrix > GlobalMatrixSharedPtr
Shared pointer to a GlobalMatrix object.
Definition: GlobalMatrix.h:86
std::map< GlobalMatrixKey, GlobalMatrixSharedPtr > GlobalMatrixMap
Mapping from global matrix keys to global matrices.
Definition: GlobalMatrix.h:88
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
@ eLinearAdvectionDiffusionReactionGJP
Definition: StdRegions.hpp:111
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:408
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
Definition: StdRegions.hpp:352
StdRegions::ConstFactorMap factors
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
static Array< OneD, NekDouble > NullNekDouble1DArray
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
double NekDouble
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:513
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