MFEM  v3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
pbilinearform.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.googlecode.com.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #include "../config/config.hpp"
13 
14 #ifdef MFEM_USE_MPI
15 
16 #include "fem.hpp"
17 
18 namespace mfem
19 {
20 
22 {
23  int nbr_size = pfes->GetFaceNbrVSize();
24 
25  if (precompute_sparsity == 0 || fes->GetVDim() > 1)
26  {
27  if (keep_nbr_block)
28  mat = new SparseMatrix(height + nbr_size, width + nbr_size);
29  else
30  mat = new SparseMatrix(height, width + nbr_size);
31  return;
32  }
33 
34  // the sparsity pattern is defined from the map: face->element->dof
36  const Table &lelem_ldof = fes->GetElementToDofTable(); // <-- dofs
37  const Table &nelem_ndof = pfes->face_nbr_element_dof; // <-- vdofs
38  Table elem_dof; // element + nbr-element <---> dof
39  if (nbr_size > 0)
40  {
41  // merge lelem_ldof and nelem_ndof into elem_dof
42  int s1 = lelem_ldof.Size(), s2 = nelem_ndof.Size();
43  const int *I1 = lelem_ldof.GetI(), *J1 = lelem_ldof.GetJ();
44  const int *I2 = nelem_ndof.GetI(), *J2 = nelem_ndof.GetJ();
45  const int nnz1 = I1[s1], nnz2 = I2[s2];
46 
47  elem_dof.SetDims(s1 + s2, nnz1 + nnz2);
48 
49  int *I = elem_dof.GetI(), *J = elem_dof.GetJ();
50  for (int i = 0; i <= s1; i++)
51  I[i] = I1[i];
52  for (int j = 0; j < nnz1; j++)
53  J[j] = J1[j];
54  for (int i = 0; i <= s2; i++)
55  I[s1+i] = I2[i] + nnz1;
56  for (int j = 0; j < nnz2; j++)
57  J[nnz1+j] = J2[j] + height;
58  }
59  // dof_elem x elem_face x face_elem x elem_dof (keep_nbr_block = true)
60  // ldof_lelem x lelem_face x face_elem x elem_dof (keep_nbr_block = false)
61  Table dof_dof;
62  {
63  Table face_dof; // face_elem x elem_dof
64  {
65  Table *face_elem = pfes->GetParMesh()->GetFaceToAllElementTable();
66  if (nbr_size > 0)
67  mfem::Mult(*face_elem, elem_dof, face_dof);
68  else
69  mfem::Mult(*face_elem, lelem_ldof, face_dof);
70  delete face_elem;
71  if (nbr_size > 0)
72  elem_dof.Clear();
73  }
74 
75  if (keep_nbr_block)
76  {
77  Table dof_face;
78  Transpose(face_dof, dof_face, height + nbr_size);
79  mfem::Mult(dof_face, face_dof, dof_dof);
80  }
81  else
82  {
83  Table ldof_face;
84  {
85  Table face_ldof;
86  Table *face_lelem = fes->GetMesh()->GetFaceToElementTable();
87  mfem::Mult(*face_lelem, lelem_ldof, face_ldof);
88  delete face_lelem;
89  Transpose(face_ldof, ldof_face, height);
90  }
91  mfem::Mult(ldof_face, face_dof, dof_dof);
92  }
93  }
94 
95  int *I = dof_dof.GetI();
96  int *J = dof_dof.GetJ();
97  int nrows = dof_dof.Size();
98  double *data = new double[I[nrows]];
99 
100  mat = new SparseMatrix(I, J, data, nrows, height + nbr_size);
101  *mat = 0.0;
102 
103  dof_dof.LoseData();
104 }
105 
107 {
108  if (m == NULL)
109  return NULL;
110 
111  HypreParMatrix *A;
112  if (fbfi.Size() == 0)
113  {
114  // construct a parallel block-diagonal wrapper matrix A based on m
115  A = new HypreParMatrix(pfes->GetComm(),
116  pfes->GlobalVSize(), pfes->GetDofOffsets(), m);
117  }
118  else
119  {
120  // handle the case when 'm' contains offdiagonal
121  int lvsize = pfes->GetVSize();
122  int *face_nbr_glob_ldof = pfes->GetFaceNbrGlobalDofMap();
123  int ldof_offset = pfes->GetMyDofOffset();
124 
125  Array<int> glob_J(m->NumNonZeroElems());
126  int *J = m->GetJ();
127  for (int i = 0; i < glob_J.Size(); i++)
128  if (J[i] < lvsize)
129  glob_J[i] = J[i] + ldof_offset;
130  else
131  glob_J[i] = face_nbr_glob_ldof[J[i] - lvsize];
132 
133  A = new HypreParMatrix(pfes->GetComm(), lvsize, pfes->GlobalVSize(),
134  pfes->GlobalVSize(), m->GetI(), glob_J,
135  m->GetData(), pfes->GetDofOffsets(),
136  pfes->GetDofOffsets());
137  }
138 
140 
141  delete A;
142 
143  return rap;
144 }
145 
147 {
148  ParMesh *pmesh = pfes->GetParMesh();
150  Array<int> vdofs1, vdofs2, vdofs_all;
152 
153  int nfaces = pmesh->GetNSharedFaces();
154  for (int i = 0; i < nfaces; i++)
155  {
156  T = pmesh->GetSharedFaceTransformations(i);
157  pfes->GetElementVDofs(T->Elem1No, vdofs1);
158  pfes->GetFaceNbrElementVDofs(T->Elem2No, vdofs2);
159  vdofs1.Copy(vdofs_all);
160  for (int j = 0; j < vdofs2.Size(); j++)
161  vdofs2[j] += height;
162  vdofs_all.Append(vdofs2);
163  for (int k = 0; k < fbfi.Size(); k++)
164  {
165  fbfi[k]->AssembleFaceMatrix(*pfes->GetFE(T->Elem1No),
166  *pfes->GetFaceNbrFE(T->Elem2No),
167  *T, elemmat);
168  if (keep_nbr_block)
169  mat->AddSubMatrix(vdofs_all, vdofs_all, elemmat, skip_zeros);
170  else
171  mat->AddSubMatrix(vdofs1, vdofs_all, elemmat, skip_zeros);
172  }
173  }
174 }
175 
176 void ParBilinearForm::Assemble(int skip_zeros)
177 {
178  if (mat == NULL && fbfi.Size() > 0)
179  {
181  pAllocMat();
182  }
183 
184  BilinearForm::Assemble(skip_zeros);
185 
186  if (fbfi.Size() > 0)
187  AssembleSharedFaces(skip_zeros);
188 }
189 
190 void ParBilinearForm::TrueAddMult(const Vector &x, Vector &y, const double a)
191  const
192 {
193  MFEM_VERIFY(fbfi.Size() == 0, "the case of interior face integrators is not"
194  " implemented");
195 
196  if (X.ParFESpace() != pfes)
197  {
198  X.Update(pfes);
199  Y.Update(pfes);
200  }
201 
202  X.Distribute(&x);
203  mat->Mult(X, Y);
204  pfes->Dof_TrueDof_Matrix()->MultTranspose(a, Y, 1.0, y);
205 }
206 
207 
209 {
210  if (m == NULL)
211  return NULL;
212 
213  int *I = m->GetI();
214  int *J = m->GetJ();
215  double *data = m->GetData();
216 
217  // remap to tdof local row and tdof global column indices
219  for (int i = 0; i < m->Height(); i++)
220  {
221  int lti = range_fes->GetLocalTDofNumber(i);
222  if (lti >= 0)
223  for (int j = I[i]; j < I[i+1]; j++)
224  local.Set(lti, domain_fes->GetGlobalTDofNumber(J[j]), data[j]);
225  }
226  local.Finalize();
227 
228  // construct and return a global ParCSR matrix by splitting the local matrix
229  // into diag and offd parts
230  return new HypreParMatrix(range_fes->GetComm(),
231  range_fes->TrueVSize(),
234  local.GetI(), local.GetJ(), local.GetData(),
237 }
238 
240 {
241  int rdim = range_fes->GetVDim();
242  int ddim = domain_fes->GetVDim();
243 
244  blocks.SetSize(rdim, ddim);
245 
246  int i, j, n;
247 
248  // construct the scalar versions of the row/coll offset arrays
249  int *row_starts, *col_starts;
250  if (HYPRE_AssumedPartitionCheck())
251  n = 2;
252  else
253  n = range_fes->GetNRanks()+1;
254  row_starts = new int[n];
255  col_starts = new int[n];
256  for (i = 0; i < n; i++)
257  {
258  row_starts[i] = (range_fes->GetTrueDofOffsets())[i] / rdim;
259  col_starts[i] = (domain_fes->GetTrueDofOffsets())[i] / ddim;
260  }
261 
262  Array2D<SparseMatrix *> lblocks;
263  GetBlocks(lblocks);
264 
265  for (int bi = 0; bi < rdim; bi++)
266  for (int bj = 0; bj < ddim; bj++)
267  {
268  int *I = lblocks(bi,bj)->GetI();
269  int *J = lblocks(bi,bj)->GetJ();
270  double *data = lblocks(bi,bj)->GetData();
271 
272  // remap to tdof local row and tdof global column indices
273  SparseMatrix local(range_fes->TrueVSize()/rdim,
274  domain_fes->GlobalTrueVSize()/ddim);
275  for (i = 0; i < lblocks(bi,bj)->Height(); i++)
276  {
277  int lti = range_fes->GetLocalTDofNumber(i);
278  if (lti >= 0)
279  for (j = I[i]; j < I[i+1]; j++)
280  local.Set(lti,
282  data[j]);
283  }
284  local.Finalize();
285 
286  delete lblocks(bi,bj);
287 
288  // construct and return a global ParCSR matrix by splitting the local
289  // matrix into diag and offd parts
290  blocks(bi,bj) = new HypreParMatrix(range_fes->GetComm(),
291  range_fes->TrueVSize()/rdim,
292  range_fes->GlobalTrueVSize()/rdim,
293  domain_fes->GlobalTrueVSize()/ddim,
294  local.GetI(), local.GetJ(), local.GetData(),
295  row_starts, col_starts);
296  }
297 
298  delete [] row_starts;
299  delete [] col_starts;
300 }
301 
303 {
304  int nproc = trial_pfes -> GetNRanks();
305  int *trial_dof_off = trial_pfes -> GetDofOffsets();
306  int *test_dof_off = test_pfes -> GetDofOffsets();
307 
308  // construct the block-diagonal matrix A
309  HypreParMatrix *A;
310  if (HYPRE_AssumedPartitionCheck())
311  A = new HypreParMatrix(trial_pfes->GetComm(), test_dof_off[2], trial_dof_off[2], test_dof_off, trial_dof_off, mat);
312  else
313  A = new HypreParMatrix(trial_pfes->GetComm(), test_dof_off[nproc], trial_dof_off[nproc], test_dof_off, trial_dof_off, mat);
314 
315  HypreParMatrix *rap = RAP(test_pfes -> Dof_TrueDof_Matrix(), A, trial_pfes -> Dof_TrueDof_Matrix());
316 
317  delete A;
318 
319  return rap;
320 }
321 
322 }
323 
324 #endif
HypreParMatrix * ParallelAssemble()
Returns the matrix &quot;assembled&quot; on the true dofs.
int Size() const
Logical size of the array.
Definition: array.hpp:108
int GetVSize() const
Definition: fespace.hpp:151
virtual int NumNonZeroElems() const
Returns the number of the nonzero elements in the matrix.
Definition: sparsemat.cpp:693
int * GetJ()
Definition: table.hpp:88
Array< BilinearFormIntegrator * > fbfi
Set of interior face Integrators to be applied.
void Assemble(int skip_zeros=1)
Assembles the form i.e. sums over all domain/bdr integrators.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:351
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
Definition: pmesh.cpp:1191
void SetDims(int rows, int nnz)
Definition: table.cpp:107
void Copy(Array &copy) const
Create a copy of the current array.
Definition: array.hpp:155
Data type dense matrix.
Definition: densemat.hpp:22
void LoseData()
Call this if data has been stolen.
Definition: table.hpp:112
void AssembleSharedFaces(int skip_zeros=1)
ParFiniteElementSpace * ParFESpace()
Definition: pgridfunc.hpp:61
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void GetFaceNbrElementVDofs(int i, Array< int > &vdofs) const
Definition: pfespace.cpp:689
void SetSize(int m, int n)
Definition: array.hpp:226
ParFiniteElementSpace * pfes
int GetGlobalTDofNumber(int ldof)
Returns the global tdof number of the given local degree of freedom.
Definition: pfespace.cpp:448
const FiniteElement * GetFaceNbrFE(int i) const
Definition: pfespace.cpp:695
int MultTranspose(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A^t * x + beta * y.
Definition: hypre.cpp:631
Data type sparse matrix.
Definition: sparsemat.hpp:38
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows.
Definition: operator.hpp:35
int Append(const T &el)
Append element to array, resize if necessary.
Definition: array.hpp:330
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:132
void Clear()
Definition: table.cpp:265
SparseMatrix * mat
Sparse matrix to be associated with the form.
HypreParMatrix * RAP(HypreParMatrix *A, HypreParMatrix *P)
Returns the matrix P^t * A * P.
Definition: hypre.cpp:781
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
Definition: table.cpp:305
int GetLocalTDofNumber(int ldof)
Definition: pfespace.cpp:440
int GetGlobalScalarTDofNumber(int sldof)
Definition: pfespace.cpp:462
ParFiniteElementSpace * test_pfes
int Size() const
Returns the number of TYPE I elements.
Definition: table.hpp:66
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:143
double * GetData() const
Return element data.
Definition: sparsemat.hpp:101
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Definition: sparsemat.cpp:1468
void GetBlocks(Array2D< SparseMatrix * > &blocks) const
int * GetI() const
Return the array I.
Definition: sparsemat.hpp:97
HypreParMatrix * Dof_TrueDof_Matrix()
The true dof-to-dof interpolation matrix.
Definition: pfespace.cpp:303
ParFiniteElementSpace * domain_fes
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
Definition: sparsemat.cpp:312
void GetElementVDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:117
void Distribute(const Vector *tv)
Definition: pgridfunc.cpp:78
Table * GetFaceToElementTable() const
Definition: mesh.cpp:3506
void Update(ParFiniteElementSpace *f)
Definition: pgridfunc.cpp:64
ParFiniteElementSpace * range_fes
FiniteElementSpace * fes
FE space on which the form lives.
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i&#39;th element.
Definition: fespace.cpp:814
DenseMatrix elemmat
ParFiniteElementSpace * trial_pfes
int GetFaceNbrVSize() const
Definition: pfespace.hpp:160
Vector data type.
Definition: vector.hpp:29
void GetParBlocks(Array2D< HypreParMatrix * > &blocks) const
int * GetI()
Definition: table.hpp:87
const Table & GetElementToDofTable() const
Definition: fespace.hpp:257
Table * GetFaceToAllElementTable() const
Definition: pmesh.cpp:1092
FaceElementTransformations * GetSharedFaceTransformations(int)
Definition: pmesh.cpp:1136
Wrapper for hypre&#39;s ParCSR matrix class.
Definition: hypre.hpp:103
void TrueAddMult(const Vector &x, Vector &y, const double a=1.0) const
Compute y += a (P^t A P) x, where x and y are vectors on the true dofs.
int * GetJ() const
Return the array J.
Definition: sparsemat.hpp:99
Class for parallel meshes.
Definition: pmesh.hpp:27