Nektar++
PreconditionerLinearWithLowEnergy.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: PreconditionerLinearWithLowEnergy.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: PreconditionerLinearWithLowEnergy definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
36 #include <LocalRegions/MatrixKey.h>
40 #include <cmath>
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 namespace MultiRegions
47 {
48 /**
49  * Registers the class with the Factory.
50  */
51 
52 string PreconditionerLinearWithLowEnergy::className =
54  "FullLinearSpaceWithLowEnergyBlock",
55  PreconditionerLinearWithLowEnergy::create,
56  "Full Linear space and low energy block preconditioning");
57 
58 /**
59  * @class PreconditionerLinearWithLowEnergy
60  *
61  * This class implements preconditioning for the conjugate
62  * gradient matrix solver.
63  */
64 
65 PreconditionerLinearWithLowEnergy::PreconditionerLinearWithLowEnergy(
66  const std::shared_ptr<GlobalLinSys> &plinsys,
67  const AssemblyMapSharedPtr &pLocToGloMap)
68  : Preconditioner(plinsys, pLocToGloMap)
69 {
70 }
71 
72 /**
73  *
74  */
76 {
78  "FullLinearSpace", m_linsys.lock(), m_locToGloMap.lock());
80  "LowEnergyBlock", m_linsys.lock(), m_locToGloMap.lock());
81 
82  // Set up multiplicity array for inverse transposed transformation matrix
83  int nDirBnd = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
84  int nGlobHomBnd = m_locToGloMap.lock()->GetNumGlobalBndCoeffs() - nDirBnd;
85  int nLocBnd = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
86 
87  m_invMultiplicity = Array<OneD, NekDouble>(nGlobHomBnd, 1.0);
88  Array<OneD, NekDouble> loc(nLocBnd);
89 
90  // need to scatter from global array to handle sign changes
91  m_locToGloMap.lock()->GlobalToLocalBnd(m_invMultiplicity, loc, nDirBnd);
92 
93  // Now assemble values back together to get multiplicity
94  m_locToGloMap.lock()->AssembleBnd(loc, m_invMultiplicity, nDirBnd);
95  Vmath::Sdiv(nGlobHomBnd, 1.0, m_invMultiplicity, 1, m_invMultiplicity, 1);
96 }
97 
98 /**
99  *
100  */
102  Array<OneD, NekDouble> &pInOut)
103 {
104  m_lowEnergyPrecon->DoTransformBasisToLowEnergy(pInOut);
105 }
106 
107 /**
108  *
109  */
111  Array<OneD, NekDouble> &pInput)
112 {
113  m_lowEnergyPrecon->DoTransformCoeffsFromLowEnergy(pInput);
114 }
115 
116 /**
117  *
118  */
120  const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput)
121 {
122  m_lowEnergyPrecon->DoTransformCoeffsToLowEnergy(pInput, pOutput);
123 }
124 
125 /**
126  *
127  */
129  const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput)
130 {
131  m_lowEnergyPrecon->DoTransformBasisFromLowEnergy(pInput, pOutput);
132 }
133 
135  int n, int offset, const std::shared_ptr<DNekScalMat> &loc_mat)
136 {
137  DNekScalMatSharedPtr returnval;
138  returnval = m_lowEnergyPrecon->TransformedSchurCompl(n, offset, loc_mat);
139  return returnval;
140 }
141 
142 /**
143  *
144  */
146 {
147  m_linSpacePrecon->BuildPreconditioner();
148  m_lowEnergyPrecon->BuildPreconditioner();
149 }
150 
151 /**
152  *
153  */
155  const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput)
156 {
157  int nDirBndDofs = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
158  int nGlobHomBndDofs =
159  m_locToGloMap.lock()->GetNumGlobalBndCoeffs() - nDirBndDofs;
160  int nLocBndDofs = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
161 
162  Array<OneD, NekDouble> tmp(nGlobHomBndDofs, 0.0);
163 
164  Array<OneD, NekDouble> InputLinear(nGlobHomBndDofs);
165  Array<OneD, NekDouble> OutputLowEnergy(nGlobHomBndDofs);
166  Array<OneD, NekDouble> OutputLinear(nGlobHomBndDofs);
167  Array<OneD, NekDouble> local(nLocBndDofs);
168 
169  // Transform input from low energy to original basis
170  Vmath::Vmul(nGlobHomBndDofs, m_invMultiplicity, 1, pInput, 1, OutputLinear,
171  1);
172  m_locToGloMap.lock()->GlobalToLocalBnd(OutputLinear, local, nDirBndDofs);
173  m_lowEnergyPrecon->DoTransformBasisFromLowEnergy(local, local);
174  m_locToGloMap.lock()->AssembleBnd(local, InputLinear, nDirBndDofs);
175 
176  // Apply linear space preconditioner
177  m_linSpacePrecon->DoPreconditionerWithNonVertOutput(InputLinear,
178  OutputLinear, tmp);
179 
180  // transform coefficients back to low energy space
181  m_locToGloMap.lock()->GlobalToLocalBnd(OutputLinear, local, nDirBndDofs);
182  m_lowEnergyPrecon->DoTransformCoeffsToLowEnergy(local, local);
183  m_locToGloMap.lock()->LocalBndToGlobal(local, pOutput, nDirBndDofs, false);
184 
185  // Apply Low Energy preconditioner
186  m_lowEnergyPrecon->DoPreconditioner(pInput, OutputLowEnergy);
187 
188  ASSERTL1(pOutput.size() >= nGlobHomBndDofs, "Output array is not correct");
189  Vmath::Vadd(nGlobHomBndDofs, pOutput, 1, OutputLowEnergy, 1, pOutput, 1);
190 }
191 
192 } // namespace MultiRegions
193 } // namespace Nektar
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
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
const std::weak_ptr< GlobalLinSys > m_linsys
std::weak_ptr< AssemblyMap > m_locToGloMap
virtual void v_DoTransformBasisFromLowEnergy(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput) override
Multiply by the block transposed inverse transformation matrix.
virtual void v_DoTransformCoeffsFromLowEnergy(Array< OneD, NekDouble > &pInOut) override
Transform from low energy coeffs to orignal basis.
virtual void v_DoTransformCoeffsToLowEnergy(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput) override
Multiply by the block inverse transformation matrix.
virtual void v_DoTransformBasisToLowEnergy(Array< OneD, NekDouble > &pInOut) override
Transform from original basis to low energy basis.
virtual DNekScalMatSharedPtr v_TransformedSchurCompl(int n, int offset, const std::shared_ptr< DNekScalMat > &loc_mat) override
Get block elemental transposed transformation matrix .
virtual void v_DoPreconditioner(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput) override
Apply a preconditioner to the conjugate gradient method.
PreconFactory & GetPreconFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:51
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
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:209
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:359
void Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/y.
Definition: Vmath.cpp:324