Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GlobalLinSysIterativeFull.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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: GlobalLinSys definition
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <map>
39 
40 namespace Nektar
41 {
42  namespace MultiRegions
43  {
44  /**
45  * @class GlobalLinSysIterativeCG
46  *
47  * This class implements a conjugate gradient matrix solver.
48  * Preconditioning is implemented using a Jacobi (diagonal)
49  * preconditioner.
50  */
51 
52  /**
53  * Registers the class with the Factory.
54  */
57  "IterativeFull",
59  "Iterative solver for full matrix system.");
60 
61 
62  /**
63  * Constructor for full direct matrix solve.
64  * @param pKey Key specifying matrix to solve.
65  * @param pExp Shared pointer to expansion list for applying
66  * matrix evaluations.
67  * @param pLocToGloMap Local to global mapping.
68  */
70  const GlobalLinSysKey &pKey,
71  const boost::weak_ptr<ExpList> &pExp,
72  const boost::shared_ptr<AssemblyMap> &pLocToGloMap)
73  : GlobalLinSys (pKey, pExp, pLocToGloMap),
74  GlobalLinSysIterative(pKey, pExp, pLocToGloMap)
75  {
77  "This routine should only be used when using an Iterative "
78  "conjugate gradient matrix solve.");
79  }
80 
81 
82  /**
83  *
84  */
86  {
87 
88  }
89 
90 
91  /**
92  * Solve a global linear system with Dirichlet forcing using a
93  * conjugate gradient method. This routine performs handling of the
94  * Dirichlet forcing terms and wraps the underlying iterative solver
95  * used for the remaining degrees of freedom.
96  *
97  * Consider solving for \f$x\f$, the matrix system \f$Ax=b\f$, where
98  * \f$b\f$ is known. To enforce the Dirichlet terms we instead solve
99  * \f[A(x-x_0) = b - Ax_0 \f]
100  * where \f$x_0\f$ is the Dirichlet forcing.
101  *
102  * @param pInput RHS of linear system, \f$b\f$.
103  * @param pOutput On input, values of dirichlet degrees
104  * of freedom with initial guess on other values.
105  * On output, the solution \f$x\f$.
106  * @param pLocToGloMap Local to global mapping.
107  * @param pDirForcing Precalculated Dirichlet forcing.
108  */
110  const Array<OneD, const NekDouble> &pInput,
111  Array<OneD, NekDouble> &pOutput,
112  const AssemblyMapSharedPtr &pLocToGloMap,
113  const Array<OneD, const NekDouble> &pDirForcing)
114  {
115  boost::shared_ptr<MultiRegions::ExpList> expList = m_expList.lock();
116  bool vCG;
117  if ((m_locToGloMap = boost::dynamic_pointer_cast<AssemblyMapCG>(
118  pLocToGloMap)))
119  {
120  vCG = true;
121  }
122  else if ((m_locToGloMap = boost::dynamic_pointer_cast<
123  AssemblyMapDG>(pLocToGloMap)))
124  {
125  vCG = false;
126  }
127 
128  bool dirForcCalculated = (bool) pDirForcing.num_elements();
129  int nDirDofs = pLocToGloMap->GetNumGlobalDirBndCoeffs();
130  int nGlobDofs = pLocToGloMap->GetNumGlobalCoeffs();
131  int nDirTotal = nDirDofs;
132 
133  expList->GetComm()->AllReduce(nDirTotal, LibUtilities::ReduceSum);
134 
135  Array<OneD, NekDouble> tmp(nGlobDofs), tmp2;
136 
137  if(nDirTotal)
138  {
139  // calculate the Dirichlet forcing
140  if(dirForcCalculated)
141  {
142  Vmath::Vsub(nGlobDofs, pInput.get(), 1,
143  pDirForcing.get(), 1,
144  tmp.get(), 1);
145  }
146  else
147  {
148  // Calculate the dirichlet forcing B_b (== X_b) and
149  // substract it from the rhs
150  expList->GeneralMatrixOp(
151  m_linSysKey, pOutput, tmp, eGlobal);
152 
153  Vmath::Vsub(nGlobDofs, pInput.get(), 1,
154  tmp.get(), 1,
155  tmp.get(), 1);
156  }
157  if (vCG)
158  {
159  Array<OneD, NekDouble> out(nGlobDofs,0.0);
160 
161  // solve for perturbation from intiial guess in pOutput
163  nGlobDofs, tmp, out, pLocToGloMap, nDirDofs);
164  Vmath::Vadd(nGlobDofs-nDirDofs, &out [nDirDofs], 1,
165  &pOutput[nDirDofs], 1, &pOutput[nDirDofs], 1);
166  }
167  else
168  {
169  ASSERTL0(false, "Need DG solve if using Dir BCs");
170  }
171  }
172  else
173  {
174  Vmath::Vcopy(nGlobDofs, pInput, 1, tmp, 1);
175  SolveLinearSystem(nGlobDofs, tmp, pOutput, pLocToGloMap);
176  }
177  }
178 
179 
180  /**
181  *
182  */
184  const Array<OneD, NekDouble>& pInput,
185  Array<OneD, NekDouble>& pOutput)
186  {
187  boost::shared_ptr<MultiRegions::ExpList> expList = m_expList.lock();
188  // Perform matrix-vector operation A*d_i
189  expList->GeneralMatrixOp(m_linSysKey,
190  pInput, pOutput, eGlobal);
191 
192  // retrieve robin boundary condition information and apply robin
193  // boundary conditions to the solution.
194  const std::map<int, RobinBCInfoSharedPtr> vRobinBCInfo
195  = expList->GetRobinBCInfo();
196  if(vRobinBCInfo.size() > 0)
197  {
198  ASSERTL0(false,
199  "Robin boundaries not set up in IterativeFull solver.");
200  int nGlobal = m_locToGloMap->GetNumGlobalCoeffs();
201  int nLocal = m_locToGloMap->GetNumLocalCoeffs();
202  int nDir = m_locToGloMap->GetNumGlobalDirBndCoeffs();
203  int nNonDir = nGlobal - nDir;
204  Array<OneD, NekDouble> robin_A(nGlobal, 0.0);
205  Array<OneD, NekDouble> robin_l(nLocal, 0.0);
206  Array<OneD, NekDouble> tmp;
207  NekVector<NekDouble> robin(nNonDir,
208  tmp = robin_A + nDir, eWrapper);
209 
210  // Operation: p_A = A * d_A
211  // First map d_A to local solution
212  m_locToGloMap->GlobalToLocal(pInput, robin_l);
213 
214  // Iterate over all the elements computing Robin BCs where
215  // necessary
216  for (int n = 0; n < expList->GetNumElmts(); ++n)
217  {
218  int nel = expList->GetOffset_Elmt_Id(n);
219  int offset = expList->GetCoeff_Offset(n);
220  int ncoeffs = expList->GetExp(nel)->GetNcoeffs();
221 
222  if(vRobinBCInfo.count(nel) != 0) // add robin mass matrix
223  {
225  Array<OneD, NekDouble> tmp;
226  StdRegions::StdExpansionSharedPtr vExp = expList->GetExp(nel);
227 
228  // add local matrix contribution
229  for(rBC = vRobinBCInfo.find(nel)->second;rBC; rBC = rBC->next)
230  {
231  vExp->AddRobinEdgeContribution(rBC->m_robinID,rBC->m_robinPrimitiveCoeffs, tmp = robin_l + offset);
232  }
233  }
234  else
235  {
236  Vmath::Zero(ncoeffs, &robin_l[offset], 1);
237  }
238  }
239 
240  // Map local Robin contribution back to global coefficients
241  m_locToGloMap->LocalToGlobal(robin_l, robin_A);
242  // Add them to the output of the GeneralMatrixOp
243  Vmath::Vadd(nGlobal, pOutput, 1, robin_A, 1, pOutput, 1);
244  }
245 
246  }
247 
248  /**
249  *
250  */
252  {
253  m_map = m_locToGloMap->GetGlobalToUniversalMapUnique();
254  }
255 
256  }
257 }