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
39#include <cmath>
40
41using namespace std;
42
43namespace Nektar
44{
45namespace MultiRegions
46{
47/**
48 * Registers the class with the Factory.
49 */
50
53 "FullLinearSpaceWithLowEnergyBlock",
55 "Full Linear space and low energy block preconditioning");
56
57/**
58 * @class PreconditionerLinearWithLowEnergy
59 *
60 * This class implements preconditioning for the conjugate
61 * gradient matrix solver.
62 */
63
65 const std::shared_ptr<GlobalLinSys> &plinsys,
66 const AssemblyMapSharedPtr &pLocToGloMap)
67 : Preconditioner(plinsys, pLocToGloMap)
68{
69}
70
71/**
72 *
73 */
75{
77 "FullLinearSpace", m_linsys.lock(), m_locToGloMap.lock());
79 "LowEnergyBlock", m_linsys.lock(), m_locToGloMap.lock());
80
81 // Set up multiplicity array for inverse transposed transformation matrix
82 int nDirBnd = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
83 int nGlobHomBnd = m_locToGloMap.lock()->GetNumGlobalBndCoeffs() - nDirBnd;
84 int nLocBnd = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
85
86 m_invMultiplicity = Array<OneD, NekDouble>(nGlobHomBnd, 1.0);
88
89 // need to scatter from global array to handle sign changes
90 m_locToGloMap.lock()->GlobalToLocalBnd(m_invMultiplicity, loc, nDirBnd);
91
92 // Now assemble values back together to get multiplicity
93 m_locToGloMap.lock()->AssembleBnd(loc, m_invMultiplicity, nDirBnd);
94 Vmath::Sdiv(nGlobHomBnd, 1.0, m_invMultiplicity, 1, m_invMultiplicity, 1);
95}
96
97/**
98 *
99 */
102{
103 m_lowEnergyPrecon->DoTransformBasisToLowEnergy(pInOut);
104}
105
106/**
107 *
108 */
111{
112 m_lowEnergyPrecon->DoTransformCoeffsFromLowEnergy(pInput);
113}
114
115/**
116 *
117 */
119 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput)
120{
121 m_lowEnergyPrecon->DoTransformCoeffsToLowEnergy(pInput, pOutput);
122}
123
124/**
125 *
126 */
128 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput)
129{
130 m_lowEnergyPrecon->DoTransformBasisFromLowEnergy(pInput, pOutput);
131}
132
134 int n, int offset, const std::shared_ptr<DNekScalMat> &loc_mat)
135{
136 DNekScalMatSharedPtr returnval;
137 returnval = m_lowEnergyPrecon->TransformedSchurCompl(n, offset, loc_mat);
138 return returnval;
139}
140
141/**
142 *
143 */
145{
146 m_linSpacePrecon->BuildPreconditioner();
147 m_lowEnergyPrecon->BuildPreconditioner();
148}
149
150/**
151 *
152 */
154 const Array<OneD, NekDouble> &pInput, Array<OneD, NekDouble> &pOutput,
155 const bool &isLocal)
156{
157 ASSERTL0(isLocal == false, "PreconditionerLinearWithLowEnergy"
158 " is only set up for Global iteratives sovles");
159 int nDirBndDofs = m_locToGloMap.lock()->GetNumGlobalDirBndCoeffs();
160 int nGlobHomBndDofs =
161 m_locToGloMap.lock()->GetNumGlobalBndCoeffs() - nDirBndDofs;
162 int nLocBndDofs = m_locToGloMap.lock()->GetNumLocalBndCoeffs();
163
164 Array<OneD, NekDouble> tmp(nGlobHomBndDofs, 0.0);
165
166 Array<OneD, NekDouble> InputLinear(nGlobHomBndDofs);
167 Array<OneD, NekDouble> OutputLowEnergy(nGlobHomBndDofs);
168 Array<OneD, NekDouble> OutputLinear(nGlobHomBndDofs);
169 Array<OneD, NekDouble> local(nLocBndDofs);
170
171 // Transform input from low energy to original basis
172 Vmath::Vmul(nGlobHomBndDofs, m_invMultiplicity, 1, pInput, 1, OutputLinear,
173 1);
174 m_locToGloMap.lock()->GlobalToLocalBnd(OutputLinear, local, nDirBndDofs);
175 m_lowEnergyPrecon->DoTransformBasisFromLowEnergy(local, local);
176 m_locToGloMap.lock()->AssembleBnd(local, InputLinear, nDirBndDofs);
177
178 // Apply linear space preconditioner
179 m_linSpacePrecon->DoPreconditionerWithNonVertOutput(InputLinear,
180 OutputLinear, tmp);
181
182 // transform coefficients back to low energy space
183 m_locToGloMap.lock()->GlobalToLocalBnd(OutputLinear, local, nDirBndDofs);
184 m_lowEnergyPrecon->DoTransformCoeffsToLowEnergy(local, local);
185 m_locToGloMap.lock()->LocalBndToGlobal(local, pOutput, nDirBndDofs, false);
186
187 // Apply Low Energy preconditioner
188 m_lowEnergyPrecon->DoPreconditioner(pInput, OutputLowEnergy);
189
190 ASSERTL1(pOutput.size() >= nGlobHomBndDofs, "Output array is not correct");
191 Vmath::Vadd(nGlobHomBndDofs, pOutput, 1, OutputLowEnergy, 1, pOutput, 1);
192}
193
194} // namespace MultiRegions
195} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#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_DoPreconditioner(const Array< OneD, NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const bool &isLocal=false) override
Apply a preconditioner to the conjugate gradient method.
PreconditionerLinearWithLowEnergy(const std::shared_ptr< GlobalLinSys > &plinsys, const AssemblyMapSharedPtr &pLocToGloMap)
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.
static PreconditionerSharedPtr create(const std::shared_ptr< GlobalLinSys > &plinsys, const std::shared_ptr< AssemblyMap > &pLocToGloMap)
Creates an instance of this class.
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 .
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: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:207
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 Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/x.
Definition: Vmath.cpp:319