LifeV
MonolithicBlockMatrix.cpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*- */
2 //@HEADER
3 /*
4 *******************************************************************************
5 
6  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
7  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
8 
9  This file is part of LifeV.
10 
11  LifeV is free software; you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  LifeV is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
23 
24 *******************************************************************************
25 */
26 //@HEADER
27 
28 #include <lifev/core/LifeV.hpp>
29 
30 #include <lifev/fsi/solver/MonolithicBlockMatrix.hpp>
31 
32 namespace LifeV
33 {
34 
35 
36 
37 // ===================================================
38 //! Public Methods
39 // ===================================================
40 
41 
42 void MonolithicBlockMatrix::setDataFromGetPot (const GetPot& /*data*/, const std::string& /*section*/)
43 {
44 }
45 
46 void MonolithicBlockMatrix::setupSolver (solver_Type& solver, const GetPot& data)
47 {
48  solver.setupPreconditioner (data, "linear_system/prec"); //to avoid if we have already a prec.
49 }
50 
51 
52 void MonolithicBlockMatrix::GlobalAssemble()
53 {
54  M_globalMatrix->globalAssemble();
55  // M_globalMatrix->spy("Prec");
56 }
57 
58 void MonolithicBlockMatrix::coupler (mapPtr_Type& map,
59  const std::map<ID, ID>& locDofMap,
60  const vectorPtr_Type& numerationInterface,
61  const Real& timeStep,
62  const Real& coefficient = 1.,
63  const Real& rescaleFactor = 1.
64  )
65 {
66  ASSERT (!M_coupling.get(), "coupler must not be called twice \n");
67  M_coupling.reset (new matrix_Type (*map) );
68  super_Type::couplingMatrix ( M_coupling, (*M_couplingFlags) [0], super_Type::M_FESpace, super_Type::M_offset, locDofMap, numerationInterface, timeStep, 1., coefficient, rescaleFactor);
69 }
70 
71 
72 void MonolithicBlockMatrix::coupler (mapPtr_Type& /*map*/,
73  const std::map<ID, ID>& locDofMap,
74  const vectorPtr_Type& numerationInterface,
75  const Real& timeStep,
76  const Real& coefficient,
77  const Real& rescaleFactor,
78  UInt couplingBlock
79  )
80 {
81  super_Type::couplingMatrix ( M_coupling, (*M_couplingFlags) [couplingBlock], super_Type::M_FESpace, super_Type::M_offset, locDofMap, numerationInterface, timeStep, 1., coefficient, rescaleFactor);
82 }
83 
84 
85 int MonolithicBlockMatrix::solveSystem ( const vector_Type& rhs, vector_Type& step, solverPtr_Type& linearSolver)
86 {
87  return linearSolver->solveSystem (rhs, step, M_globalMatrix);
88 }
89 
90 void MonolithicBlockMatrix::push_back_matrix ( const matrixPtr_Type& Mat, bool /*recompute*/)
91 {
92  super_Type::M_blocks.push_back (Mat);
93 }
94 
95 
96 void MonolithicBlockMatrix::replace_matrix ( const matrixPtr_Type& Mat, UInt index)
97 {
98  super_Type::M_blocks[index] = Mat;
99 }
100 
101 
102 void MonolithicBlockMatrix::replace_precs ( const epetraOperatorPtr_Type& /*Mat*/, UInt /*index*/)
103 {
104  assert (false);
105 }
106 
107 
108 void MonolithicBlockMatrix::blockAssembling()
109 {
110  M_coupling->globalAssemble();
111  M_globalMatrix.reset (new matrix_Type (M_coupling->map() ) );
112  *M_globalMatrix += *M_coupling;
113  for (UInt k = 0; k < M_blocks.size(); ++k)
114  {
115  M_blocks[k]->globalAssemble();
116  *M_globalMatrix += *M_blocks[k];
117  }
118 }
119 
120 
121 
122 void MonolithicBlockMatrix::applyPreconditioner (const matrixPtr_Type matrix, vectorPtr_Type& rhsFull)
123 {
124  this->applyPreconditioner (matrix, M_globalMatrix);
125  *rhsFull = (*matrix) * (*rhsFull);
126 }
127 
128 
129 void MonolithicBlockMatrix::applyPreconditioner ( matrixPtr_Type robinCoupling, matrixPtr_Type prec, vectorPtr_Type& rhs)
130 {
131  applyPreconditioner (robinCoupling, prec);
132  applyPreconditioner (robinCoupling, M_globalMatrix);
133  (*rhs) = (*robinCoupling) * (*rhs);
134 }
135 
136 
137 void MonolithicBlockMatrix::applyPreconditioner ( const matrixPtr_Type prec, matrixPtr_Type& oper )
138 {
139  matrix_Type tmpMatrix (prec->map(), 1);
140  EpetraExt::MatrixMatrix::Multiply ( *prec->matrixPtr(),
141  false,
142  *oper->matrixPtr(),
143  false,
144  *tmpMatrix.matrixPtr() );
145  oper->swapCrsMatrix (tmpMatrix);
146 }
147 
148 
149 void MonolithicBlockMatrix::createInterfaceMap ( const MapEpetra& interfaceMap , const std::map<ID, ID>& locDofMap, const UInt subdomainMaxId, const std::shared_ptr<Epetra_Comm> epetraWorldComm )
150 {
151  //std::map<ID, ID> const& locDofMap = M_dofStructureToHarmonicExtension->locDofMap();
152  std::map<ID, ID>::const_iterator ITrow;
153 
154  Int numtasks = epetraWorldComm->NumProc();
155  int* numInterfaceDof (new int[numtasks]);
156  int pid = epetraWorldComm->MyPID();
157  int numMyElements = interfaceMap.map (Unique)->NumMyElements();
158  numInterfaceDof[pid] = numMyElements;
159  MapEpetra subMap (*interfaceMap.map (Unique), (UInt) 0, subdomainMaxId);
160 
161  M_numerationInterface.reset (new vector_Type (subMap, Unique) );
162  //should be an int vector instead of double
163  // M_numerationInterfaceInt.reset(new Epetra_IntVector(*M_interfaceMap.getMap(Unique)));
164 
165  for (int j = 0; j < numtasks; ++j)
166  {
167  epetraWorldComm->Broadcast ( &numInterfaceDof[j], 1, j);
168  }
169 
170  for (int j = numtasks - 1; j > 0 ; --j)
171  {
172  numInterfaceDof[j] = numInterfaceDof[j - 1];
173  }
174  numInterfaceDof[0] = 0;
175  for (int j = 1; j < numtasks ; ++j)
176  {
177  numInterfaceDof[j] += numInterfaceDof[j - 1];
178  }
179 
180  UInt l = 0;
181 
182  M_interface = (UInt) interfaceMap.map (Unique)->NumGlobalElements() / nDimensions;
183  //UInt solidDim=M_dFESpace->map().map(Unique)->NumGlobalElements()/nDimensions;
184  for (l = 0, ITrow = locDofMap.begin(); ITrow != locDofMap.end() ; ++ITrow)
185  {
186  if (interfaceMap.map (Unique)->LID ( static_cast<EpetraInt_Type> (ITrow->second /*+ dim*solidDim*/) ) >= 0)
187  {
188  (*M_numerationInterface) [ITrow->second /*+ dim*solidDim*/ ] = l + (int) (numInterfaceDof[pid] / nDimensions) /*+ dim*localInterface*/ ;
189  // (*M_numerationInterfaceInt)[ITrow->second /*+ dim*solidDim*/ ]=l+1+ (int)(M_numInterfaceDof[pid]/nDimensions)/*+ dim*localInterface*/ ;
190  if ( (int) (*M_numerationInterface) (ITrow->second ) != floor (l + numInterfaceDof[pid] / nDimensions + 0.2 /*+ dim*localInterface*/) )
191  {
192  std::cout << "ERROR! the numeration of the coupling map is not correct" << std::endl;
193  }
194  ++l;
195  }
196  }
197 
198  std::vector<int> couplingVector;
199  couplingVector.reserve ( (int) (interfaceMap.map (Unique)->NumMyElements() ) );
200 
201  for (UInt dim = 0; dim < nDimensions; ++dim)
202  {
203  for ( ITrow = locDofMap.begin(); ITrow != locDofMap.end() ; ++ITrow)
204  {
205  if (interfaceMap.map (Unique)->LID ( static_cast<EpetraInt_Type> (ITrow->second) ) >= 0)
206  {
207  couplingVector.push_back ( (*M_numerationInterface) (ITrow->second /*+ dim * solidDim*/) + dim * M_interface );
208  //couplingVector.push_back((*M_numerationInterfaceInt)[ITrow->second /*+ dim * solidDim*/]+ dim * M_interface );
209  }
210  }
211  }// so the map for the coupling part of the matrix is just Unique
212 
213  M_interfaceMap.reset (new MapEpetra (-1, static_cast< Int> ( couplingVector.size() ), &couplingVector[0], epetraWorldComm) );
214 }
215 
216 void MonolithicBlockMatrix::applyBoundaryConditions (const Real& time)
217 {
218  for ( UInt i = 0; i < super_Type::M_blocks.size(); ++i )
219  {
220  applyBoundaryConditions ( time, i );
221  }
222 }
223 
224 void MonolithicBlockMatrix::applyBoundaryConditions (const Real& time, vectorPtr_Type& rhs)
225 {
226  for ( UInt i = 0; i < super_Type::M_blocks.size(); ++i )
227  {
228  applyBoundaryConditions ( time, rhs, i );
229  }
230 }
231 
232 void MonolithicBlockMatrix::applyBoundaryConditions (const Real& time, vectorPtr_Type& rhs, const UInt block)
233 {
234 
235  bcManage ( *M_globalMatrix , *rhs, *super_Type::M_FESpace[block]->mesh(), super_Type::M_FESpace[block]->dof(), *super_Type::M_bch[block], super_Type::M_FESpace[block]->feBd(), 1., time);
236 }
237 
238 void MonolithicBlockMatrix::applyBoundaryConditions (const Real& time, const UInt block)
239 {
240 
241  bcManageMatrix ( *M_globalMatrix , *super_Type::M_FESpace[block]->mesh(), super_Type::M_FESpace[block]->dof(), *super_Type::M_bch[block], super_Type::M_FESpace[block]->feBd(), 1., time);
242 }
243 
244 void MonolithicBlockMatrix::addToCoupling ( const matrixPtr_Type& Mat, UInt /*position*/)
245 {
246  if (!M_coupling->matrixPtr()->Filled() )
247  {
248  *M_coupling += *Mat;
249  }
250  else
251  {
252  matrixPtr_Type tmp (new matrix_Type (M_coupling->map() ) );
253  *tmp += *M_coupling;
254  *tmp += *Mat;
255  M_coupling = tmp;
256  }
257 }
258 
259 
260 void MonolithicBlockMatrix::addToCoupling ( const Real& entry , UInt row, UInt col, UInt /*position*/ )
261 {
262  if (!M_coupling->matrixPtr()->Filled() )
263  {
264  M_coupling->setCoefficient (row, col, entry);
265  }
266  else
267  {
268  matrixPtr_Type tmp (new matrix_Type (M_coupling->map() ) );
269  *tmp += *M_coupling;
270  tmp->setCoefficient (row, col, entry);
271  M_coupling = tmp;
272  }
273 }
274 
275 
276 } // Namespace LifeV
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void updateInverseJacobian(const UInt &iQuadPt)
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
double Real
Generic real data.
Definition: LifeV.hpp:175
const UInt nDimensions(NDIM)
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191