Nektar++
PreconditionerLinearWithLowEnergy.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File Preconditioner.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: Preconditioner definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
39 #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  {
77  m_linSpacePrecon = GetPreconFactory().CreateInstance("FullLinearSpace",m_linsys.lock(),m_locToGloMap.lock());
78  m_lowEnergyPrecon = GetPreconFactory().CreateInstance("LowEnergyBlock",m_linsys.lock(),m_locToGloMap.lock());
79 
80  //Set up multiplicity array for inverse transposed transformation matrix
81  int nDirBnd = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
82  int nGlobHomBnd = m_locToGloMap.lock()->GetNumGlobalBndCoeffs() - nDirBnd;
83  int nLocBnd = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
84 
85  m_invMultiplicity = Array<OneD,NekDouble>(nGlobHomBnd,1.0);
86  Array<OneD,NekDouble> loc(nLocBnd);
87 
88  // need to scatter from global array to handle sign changes
89  m_locToGloMap.lock()->GlobalToLocalBnd(m_invMultiplicity, loc, nDirBnd);
90 
91  // Now assemble values back together to get multiplicity
92  m_locToGloMap.lock()->AssembleBnd(loc,m_invMultiplicity, nDirBnd);
93  Vmath::Sdiv(nGlobHomBnd,1.0,m_invMultiplicity,1,m_invMultiplicity,1);
94  }
95 
96  /**
97  *
98  */
100  Array<OneD, NekDouble>& pInOut)
101  {
102  m_lowEnergyPrecon->DoTransformBasisToLowEnergy(pInOut);
103  }
104 
105  /**
106  *
107  */
109  Array<OneD, NekDouble>& pInput)
110  {
111  m_lowEnergyPrecon->DoTransformCoeffsFromLowEnergy(pInput);
112  }
113 
114  /**
115  *
116  */
118  const Array<OneD, NekDouble>& pInput,
119  Array<OneD, NekDouble>& pOutput)
120  {
121  m_lowEnergyPrecon->DoTransformCoeffsToLowEnergy(pInput,pOutput);
122  }
123 
124  /**
125  *
126  */
128  const Array<OneD, NekDouble>& pInput,
129  Array<OneD, NekDouble>& pOutput)
130  {
131  m_lowEnergyPrecon->DoTransformBasisFromLowEnergy(pInput,pOutput);
132  }
133 
134 
136  v_TransformedSchurCompl(int n, int offset,
137  const std::shared_ptr<DNekScalMat > &loc_mat)
138  {
139  DNekScalMatSharedPtr returnval;
140  returnval=m_lowEnergyPrecon->TransformedSchurCompl(n,offset, loc_mat);
141  return returnval;
142  }
143 
144  /**
145  *
146  */
148  {
149  m_linSpacePrecon->BuildPreconditioner();
150  m_lowEnergyPrecon->BuildPreconditioner();
151  }
152 
153 
154  /**
155  *
156  */
158  const Array<OneD, NekDouble>& pInput,
159  Array<OneD, NekDouble>& pOutput)
160  {
161  int nDirBndDofs = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
162  int nGlobHomBndDofs = m_locToGloMap.lock()->GetNumGlobalBndCoeffs() - nDirBndDofs;
163  int nLocBndDofs = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
164 
165  Array<OneD, NekDouble> tmp(nGlobHomBndDofs, 0.0);
166 
167  Array<OneD, NekDouble> InputLinear(nGlobHomBndDofs);
168  Array<OneD, NekDouble> OutputLowEnergy(nGlobHomBndDofs);
169  Array<OneD, NekDouble> OutputLinear(nGlobHomBndDofs);
170  Array<OneD, NekDouble> local(nLocBndDofs);
171 
172 
173  //Transform input from low energy to original basis
174  Vmath::Vmul(nGlobHomBndDofs,m_invMultiplicity,1,
175  pInput,1,OutputLinear,1);
176  m_locToGloMap.lock()->GlobalToLocalBnd(OutputLinear,local,nDirBndDofs);
177  m_lowEnergyPrecon->DoTransformBasisFromLowEnergy(local,local);
178  m_locToGloMap.lock()->AssembleBnd(local,InputLinear,nDirBndDofs);
179 
180  //Apply linear space preconditioner
181  m_linSpacePrecon->DoPreconditionerWithNonVertOutput
182  (InputLinear, OutputLinear, tmp);
183 
184  // transform coefficients back to low energy space
185  m_locToGloMap.lock()->GlobalToLocalBnd(OutputLinear,local,nDirBndDofs);
186  m_lowEnergyPrecon->DoTransformCoeffsToLowEnergy(local,local);
187  m_locToGloMap.lock()->LocalBndToGlobal(local,pOutput,nDirBndDofs,false);
188 
189  //Apply Low Energy preconditioner
190  m_lowEnergyPrecon->DoPreconditioner(pInput, OutputLowEnergy);
191 
192  ASSERTL1(pOutput.size() >= nGlobHomBndDofs, "Output array is not correct");
193  Vmath::Vadd(nGlobHomBndDofs,pOutput,1,OutputLowEnergy,1,pOutput,1);
194  }
195 
196  }
197 }
198 
199 
200 
201 
202 
203 
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:250
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:145
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)
Multiply by the block transposed inverse transformation matrix.
virtual void v_DoPreconditioner(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
Apply a preconditioner to the conjugate gradient method.
virtual void v_DoTransformCoeffsToLowEnergy(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput)
Multiply by the block inverse transformation matrix.
virtual void v_DoTransformBasisToLowEnergy(Array< OneD, NekDouble > &pInOut)
Transform from original basis to low energy basis.
virtual DNekScalMatSharedPtr v_TransformedSchurCompl(int n, int offset, const std::shared_ptr< DNekScalMat > &loc_mat)
Get block elemental transposed transformation matrix .
virtual void v_DoTransformCoeffsFromLowEnergy(Array< OneD, NekDouble > &pInOut)
Transform from low energy coeffs to orignal basis.
PreconFactory & GetPreconFactory()
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:52
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
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:192
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:322
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:291