Nektar++
GlobalLinSysDirectFull.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File GlobalLinSys.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: GlobalLinSys definition
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
36 #include <MultiRegions/ExpList.h>
37 
38 using namespace std;
39 
40 namespace Nektar
41 {
42  namespace MultiRegions
43  {
44  /**
45  * @class GlobalLinSysDirect
46  *
47  * Consider a linear system
48  * \f$\boldsymbol{M\hat{u}}_g=\boldsymbol{\hat{f}}\f$
49  * to be solved, where \f$\boldsymbol{M}\f$ is a matrix of type
50  * specified by \a mkey. This function assembles the global system
51  * matrix \f$\boldsymbol{M}\f$ out of the elemental submatrices
52  * \f$\boldsymbol{M}^e\f$. This is equivalent to:
53  * \f[ \boldsymbol{M}=\boldsymbol{\mathcal{A}}^T
54  * \underline{\boldsymbol{M}}^e\boldsymbol{\mathcal{A}}.\f]
55  * where the matrix \f$\boldsymbol{\mathcal{A}}\f$ is a sparse
56  * permutation matrix of size \f$N_{\mathrm{eof}}\times
57  * N_{\mathrm{dof}}\f$. However, due to the size and sparsity of the
58  * matrix \f$\boldsymbol{\mathcal{A}}\f$, it is more efficient to
59  * assemble the global matrix using the mapping array \a
60  * map\f$[e][i]\f$ contained in the input argument \a locToGloMap.
61  * The global assembly is then evaluated as:
62  * \f[ \boldsymbol{M}\left[\mathrm{\texttt{map}}[e][i]\right]
63  * \left[\mathrm{\texttt{map}}[e][j]\right]
64  * =\mathrm{\texttt{sign}}[e][i]\cdot
65  * \mathrm{\texttt{sign}}[e][j] \cdot\boldsymbol{M}^e[i][j]\f]
66  * where the values \a sign\f$[e][i]\f$ ensure the correct connectivity.
67  */
68 
69  /**
70  * Registers the class with the Factory.
71  */
72  string GlobalLinSysDirectFull::className
74  "DirectFull",
75  GlobalLinSysDirectFull::create,
76  "Direct Full.");
77 
78 
79  /// Constructor for full direct matrix solve.
80  GlobalLinSysDirectFull::GlobalLinSysDirectFull(
81  const GlobalLinSysKey &pLinSysKey,
82  const std::weak_ptr<ExpList> &pExp,
83  const std::shared_ptr<AssemblyMap> &pLocToGloMap)
84  : GlobalLinSys(pLinSysKey, pExp, pLocToGloMap),
85  GlobalLinSysDirect(pLinSysKey, pExp, pLocToGloMap)
86  {
87 
89  "This routine should only be used when using a Full Direct"
90  " matrix solve");
91  ASSERTL1(pExp.lock()->GetComm()->GetSize() == 1,
92  "Direct full matrix solve can only be used in serial.");
93 
94  AssembleFullMatrix(pLocToGloMap);
95  }
96 
97 
99  {
100 
101  }
102 
103 
104  /**
105  * Solve the linear system using a full global matrix system.
106  */
108  const Array<OneD, const NekDouble> &pInput,
109  Array<OneD, NekDouble> &pOutput,
110  const AssemblyMapSharedPtr &pLocToGloMap,
111  const Array<OneD, const NekDouble> &pDirForcing)
112  {
113  bool dirForcCalculated = (bool) pDirForcing.num_elements();
114  int nDirDofs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
115  int nGlobDofs = pLocToGloMap->GetNumGlobalCoeffs();
116  Array<OneD, NekDouble> tmp(nGlobDofs);
117 
118  if(nDirDofs)
119  {
120  // calculate the dirichlet forcing
121  if(dirForcCalculated)
122  {
123  Vmath::Vsub(nGlobDofs,
124  pInput.get(), 1,
125  pDirForcing.get(), 1,
126  tmp.get(), 1);
127  }
128  else
129  {
130  Vmath::Zero(nGlobDofs-nDirDofs, &pOutput[nDirDofs], 1);
131  // Calculate Dirichlet forcing and subtract it from the rhs
132  m_expList.lock()->GeneralMatrixOp(
133  m_linSysKey, pOutput, tmp, eGlobal);
134 
135  Vmath::Vsub(nGlobDofs,
136  pInput.get(), 1,
137  tmp.get(), 1,
138  tmp.get(), 1);
139  }
140 
141  Array<OneD, NekDouble> out(nGlobDofs,0.0);
142  SolveLinearSystem(nGlobDofs, tmp, out, pLocToGloMap, nDirDofs);
143  Vmath::Vadd(nGlobDofs-nDirDofs, &out [nDirDofs], 1,
144  &pOutput[nDirDofs], 1, &pOutput[nDirDofs], 1);
145  }
146  else
147  {
148  SolveLinearSystem(nGlobDofs, pInput, pOutput, pLocToGloMap, nDirDofs);
149  }
150  }
151 
152 
153  /**
154  * Assemble a full matrix from the block matrix stored in
155  * #m_blkMatrices and the given local to global mapping information.
156  * @param locToGloMap Local to global mapping information.
157  */
159  const AssemblyMapSharedPtr& pLocToGloMap)
160  {
161  int i,j,n,cnt,gid1,gid2;
162  NekDouble sign1,sign2,value;
163  int totDofs = pLocToGloMap->GetNumGlobalCoeffs();
164  int NumDirBCs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
165 
166  unsigned int rows = totDofs - NumDirBCs;
167  unsigned int cols = totDofs - NumDirBCs;
168  NekDouble zero = 0.0;
169 
170  DNekMatSharedPtr Gmat;
171  int bwidth = pLocToGloMap->GetFullSystemBandWidth();
172  MatrixStorage matStorage = eFULL;
173 
174  switch(m_linSysKey.GetMatrixType())
175  {
176  // case for all symmetric matices
177  case StdRegions::eMass:
181  {
182  if( (2*(bwidth+1)) < rows)
183  {
186  ::AllocateSharedPtr(rows, cols, zero,
187  matStorage,
188  bwidth, bwidth);
189  }
190  else
191  {
192  matStorage = ePOSITIVE_DEFINITE_SYMMETRIC;
194  ::AllocateSharedPtr(rows, cols, zero,
195  matStorage);
196  }
197  break;
198  }
201  {
202  matStorage = eFULL;
204  ::AllocateSharedPtr(rows, cols, zero,
205  matStorage);
206  break;
207  }
208  default:
209  {
210  NEKERROR(ErrorUtil::efatal, "Add MatrixType to switch "
211  "statement");
212  }
213  }
214 
215  // fill global matrix
216  DNekScalMatSharedPtr loc_mat;
217 
218  int loc_lda;
219  for(n = cnt = 0; n < m_expList.lock()->GetNumElmts(); ++n)
220  {
221  loc_mat = GetBlock(n);
222  loc_lda = loc_mat->GetRows();
223 
224  for(i = 0; i < loc_lda; ++i)
225  {
226  gid1 = pLocToGloMap->GetLocalToGlobalMap(cnt + i)-NumDirBCs;
227  sign1 = pLocToGloMap->GetLocalToGlobalSign(cnt + i);
228  if(gid1 >= 0)
229  {
230  for(j = 0; j < loc_lda; ++j)
231  {
232  gid2 = pLocToGloMap->GetLocalToGlobalMap(cnt + j)
233  - NumDirBCs;
234  sign2 = pLocToGloMap->GetLocalToGlobalSign(cnt + j);
235  if(gid2 >= 0)
236  {
237  // When global matrix is symmetric,
238  // only add the value for the upper
239  // triangular part in order to avoid
240  // entries to be entered twice
241  if((matStorage == eFULL)||(gid2 >= gid1))
242  {
243  value = Gmat->GetValue(gid1,gid2)
244  + sign1*sign2*(*loc_mat)(i,j);
245  Gmat->SetValue(gid1,gid2,value);
246  }
247  }
248  }
249  }
250  }
251  cnt += loc_lda;
252  }
253 
254  if(rows)
255  {
258  }
259  }
260  }
261 }
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
DNekLinSysSharedPtr m_linSys
Basic linear system object.
void SolveLinearSystem(const int pNumRows, const Array< OneD, const NekDouble > &pInput, Array< OneD, NekDouble > &pOutput, const AssemblyMapSharedPtr &locToGloMap, const int pNumDir=0)
Solve the linear system for given input and output vectors.
Definition: GlobalLinSys.h:201
STL namespace.
void AssembleFullMatrix(const std::shared_ptr< AssemblyMap > &locToGloMap)
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
std::shared_ptr< AssemblyMap > AssemblyMapSharedPtr
Definition: AssemblyMap.h:52
Global coefficients.
DNekScalMatSharedPtr GetBlock(unsigned int n)
Definition: GlobalLinSys.h:222
StdRegions::MatrixType GetMatrixType() const
Return the matrix type.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble
Describe a linear system.
PointerWrapper
Specifies if the pointer passed to a NekMatrix or NekVector is copied into an internal representation...
const GlobalLinSysKey m_linSysKey
Key associated with this linear system.
Definition: GlobalLinSys.h:125
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.cpp:346
A global linear system.
Definition: GlobalLinSys.h:72
const std::weak_ptr< ExpList > m_expList
Local Matrix System.
Definition: GlobalLinSys.h:127
virtual void v_Solve(const Array< OneD, const NekDouble > &in, Array< OneD, NekDouble > &out, const AssemblyMapSharedPtr &locToGloMap, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray)
Solve the linear system for given input and output vectors using a specified local to global map...
GlobalSysSolnType GetGlobalSysSolnType() const
Return the associated solution type.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
GlobalLinSysFactory & GetGlobalLinSysFactory()
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
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:302