MFEM  v3.1
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
staticcond.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.org.
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 "staticcond.hpp"
13 
14 namespace mfem
15 {
16 
18  : fes(fespace)
19 {
20  tr_fec = fespace->FEColl()->GetTraceCollection();
21  int vdim = fes->GetVDim();
22  int ordering = fes->GetOrdering();
23 #ifndef MFEM_USE_MPI
24  tr_fes = new FiniteElementSpace(fes->GetMesh(), tr_fec, vdim, ordering);
25 #else
26  pfes = dynamic_cast<ParFiniteElementSpace*>(fes);
27  if (!pfes)
28  {
29  tr_fes = new FiniteElementSpace(fes->GetMesh(), tr_fec, vdim, ordering);
30  tr_pfes = NULL;
31  }
32  else
33  {
34  tr_pfes = new ParFiniteElementSpace(pfes->GetParMesh(), tr_fec, vdim,
35  ordering);
36  tr_fes = tr_pfes;
37  }
38  pS = pS_e = NULL;
39 #endif
40  S = S_e = NULL;
41  symm = false;
42  A_data = NULL;
43  A_ipiv = NULL;
44 
45  Array<int> vdofs;
46  const int NE = fes->GetNE();
47  elem_pdof.MakeI(NE);
48  for (int i = 0; i < NE; i++)
49  {
50  const int npd = vdim*fes->GetNumElementInteriorDofs(i);
51  elem_pdof.AddColumnsInRow(i, npd);
52  }
53  elem_pdof.MakeJ();
54  for (int i = 0; i < NE; i++)
55  {
56  fes->GetElementVDofs(i, vdofs);
57  const int nsd = vdofs.Size()/vdim;
58  const int nspd = fes->GetNumElementInteriorDofs(i);
59  const int *dofs = vdofs.GetData();
60  for (int vd = 0; vd < vdim; vd++)
61  {
62 #ifdef MFEM_DEBUG
63  for (int j = 0; j < nspd; j++)
64  {
65  MFEM_ASSERT(dofs[nsd-nspd+j] >= 0, "");
66  }
67 #endif
68  elem_pdof.AddConnections(i, dofs+nsd-nspd, nspd);
69  dofs += nsd;
70  }
71  }
72  elem_pdof.ShiftUpI();
73  // Set the number of private dofs.
74  npdofs = elem_pdof.Size_of_connections();
75  MFEM_ASSERT(fes->GetVSize() == tr_fes->GetVSize() + npdofs,
76  "incompatible volume and trace FE spaces");
77  // Initialize the map rdof_edof.
78  rdof_edof.SetSize(tr_fes->GetVSize());
79  Array<int> rvdofs;
80  for (int i = 0; i < NE; i++)
81  {
82  fes->GetElementVDofs(i, vdofs);
83  tr_fes->GetElementVDofs(i, rvdofs);
84  const int nsd = vdofs.Size()/vdim;
85  const int nsrd = rvdofs.Size()/vdim;
86  for (int vd = 0; vd < vdim; vd++)
87  {
88  for (int j = 0; j < nsrd; j++)
89  {
90  int rvdof = rvdofs[j+nsrd*vd];
91  int vdof = vdofs[j+nsd*vd];
92  if (rvdof < 0)
93  {
94  rvdof = -1-rvdof;
95  vdof = -1-vdof;
96  }
97  MFEM_ASSERT(vdof >= 0, "incompatible volume and trace FE spaces");
98  rdof_edof[rvdof] = vdof;
99  }
100  }
101  }
102 }
103 
105 {
106 #ifdef MFEM_USE_MPI
107  delete pS_e;
108  delete pS;
109 #endif
110  delete S_e;
111  delete S;
112  delete [] A_data;
113  delete [] A_ipiv;
114  delete tr_fes;
115  delete tr_fec;
116 }
117 
119 {
120  if (!Parallel())
121  {
122  return (tr_fes->GetTrueVSize() < fes->GetTrueVSize());
123  }
124  else
125  {
126 #ifdef MFEM_USE_MPI
127  return (tr_pfes->GlobalTrueVSize() < pfes->GlobalTrueVSize());
128 #else
129  return false; // avoid compiler warning
130 #endif
131  }
132 }
133 
134 void StaticCondensation::Init(bool symmetric, bool block_diagonal)
135 {
136  const int NE = fes->GetNE();
137  // symm = symmetric; // TODO: handle the symmetric case
138  A_offsets.SetSize(NE+1);
139  A_ipiv_offsets.SetSize(NE+1);
140  A_offsets[0] = A_ipiv_offsets[0] = 0;
141  Array<int> rvdofs;
142  for (int i = 0; i < NE; i++)
143  {
144  tr_fes->GetElementVDofs(i, rvdofs);
145  const int ned = rvdofs.Size();
146  const int npd = elem_pdof.RowSize(i);
147  A_offsets[i+1] = A_offsets[i] + npd*(npd + (symm ? 1 : 2)*ned);
148  A_ipiv_offsets[i+1] = A_ipiv_offsets[i] + npd;
149  }
150  A_data = new double[A_offsets[NE]];
151  A_ipiv = new int[A_ipiv_offsets[NE]];
152  const int nedofs = tr_fes->GetVSize();
153  if (fes->GetVDim() == 1)
154  {
155  // The sparsity pattern of S is given by the map rdof->elem->rdof
156  Table rdof_rdof;
157  {
158  Table elem_rdof, rdof_elem;
159  elem_rdof.MakeI(NE);
160  for (int i = 0; i < NE; i++)
161  {
162  tr_fes->GetElementVDofs(i, rvdofs);
163  elem_rdof.AddColumnsInRow(i, rvdofs.Size());
164  }
165  elem_rdof.MakeJ();
166  for (int i = 0; i < NE; i++)
167  {
168  tr_fes->GetElementVDofs(i, rvdofs);
170  elem_rdof.AddConnections(i, rvdofs.GetData(), rvdofs.Size());
171  }
172  elem_rdof.ShiftUpI();
173  Transpose(elem_rdof, rdof_elem, nedofs);
174  mfem::Mult(rdof_elem, elem_rdof, rdof_rdof);
175  }
176  S = new SparseMatrix(rdof_rdof.GetI(), rdof_rdof.GetJ(), NULL,
177  nedofs, nedofs, true, true, false);
178  rdof_rdof.LoseData();
179  }
180  else
181  {
182  // For a block diagonal vector bilinear form, the sparsity of
183  // rdof->elem->rdof is overkill, so we use dynamically allocated
184  // sparsity pattern.
185  S = new SparseMatrix(nedofs);
186  }
187 }
188 
190 {
191  Array<int> rvdofs;
192  tr_fes->GetElementVDofs(el, rvdofs);
193  const int vdim = fes->GetVDim();
194  const int nvpd = elem_pdof.RowSize(el);
195  const int nved = rvdofs.Size();
196  DenseMatrix A_pp(A_data + A_offsets[el], nvpd, nvpd);
197  DenseMatrix A_pe(A_pp.Data() + nvpd*nvpd, nvpd, nved);
198  DenseMatrix A_ep;
199  if (symm) { A_ep.SetSize(nved, nvpd); }
200  else { A_ep.UseExternalData(A_pe.Data() + nvpd*nved, nved, nvpd); }
201  DenseMatrix A_ee(nved, nved);
202 
203  const int npd = nvpd/vdim;
204  const int ned = nved/vdim;
205  const int nd = npd + ned;
206  // Copy the blocks from elmat to A_xx
207  for (int i = 0; i < vdim; i++)
208  {
209  for (int j = 0; j < vdim; j++)
210  {
211  A_pp.CopyMN(elmat, npd, npd, i*nd+ned, j*nd+ned, i*npd, j*npd);
212  A_pe.CopyMN(elmat, npd, ned, i*nd+ned, j*nd, i*npd, j*ned);
213  A_ep.CopyMN(elmat, ned, npd, i*nd, j*nd+ned, i*ned, j*npd);
214  A_ee.CopyMN(elmat, ned, ned, i*nd, j*nd, i*ned, j*ned);
215  }
216  }
217  // Compute the Schur complement
218  LUFactors lu(A_pp.Data(), A_ipiv + A_ipiv_offsets[el]);
219  lu.Factor(nvpd);
220  lu.BlockFactor(nvpd, nved, A_pe.Data(), A_ep.Data(), A_ee.Data());
221 
222  // Assemble the Schur complement
223  const int skip_zeros = 0;
224  S->AddSubMatrix(rvdofs, rvdofs, A_ee, skip_zeros);
225 }
226 
228 {
229  Array<int> rvdofs;
230  tr_fes->GetBdrElementVDofs(el, rvdofs);
231  const int skip_zeros = 0;
232  S->AddSubMatrix(rvdofs, rvdofs, elmat, skip_zeros);
233 }
234 
236 {
237  if (!Parallel())
238  {
239  const int skip_zeros = 0;
240  S->Finalize(skip_zeros);
241  if (S_e) { S_e->Finalize(skip_zeros); }
242  const SparseMatrix *cP = tr_fes->GetConformingProlongation();
243  if (cP)
244  {
245  if (S->Height() != cP->Width())
246  {
247  SparseMatrix *cS = mfem::RAP(*cP, *S, *cP);
248  delete S;
249  S = cS;
250  }
251  if (S_e && S_e->Height() != cP->Width())
252  {
253  SparseMatrix *cS_e = mfem::RAP(*cP, *S_e, *cP);
254  delete S_e;
255  S = cS_e;
256  }
257  }
258  }
259  else // parallel
260  {
261 #ifdef MFEM_USE_MPI
262  if (!S) { return; } // already finalized
263  S->Finalize();
264  if (S_e) { S_e->Finalize(); }
265  HypreParMatrix *dS =
266  new HypreParMatrix(tr_pfes->GetComm(), tr_pfes->GlobalVSize(),
267  tr_pfes->GetDofOffsets(), S);
268  pS = RAP(dS, tr_pfes->Dof_TrueDof_Matrix());
269  delete dS;
270  delete S;
271  S = NULL;
272  if (S_e)
273  {
274  HypreParMatrix *dS_e =
275  new HypreParMatrix(tr_pfes->GetComm(), tr_pfes->GlobalVSize(),
276  tr_pfes->GetDofOffsets(), S_e);
277  pS_e = RAP(dS_e, tr_pfes->Dof_TrueDof_Matrix());
278  delete dS_e;
279  delete S_e;
280  S_e = NULL;
281  }
282 #endif
283  }
284 }
285 
287  const Array<int> &ess_rtdof_list, int keep_diagonal)
288 {
289  if (!Parallel() || S) // not parallel or not finalized
290  {
291  if (S_e == NULL)
292  {
293  S_e = new SparseMatrix(S->Height());
294  }
295  for (int i = 0; i < ess_rtdof_list.Size(); i++)
296  {
297  S->EliminateRowCol(ess_rtdof_list[i], *S_e, keep_diagonal);
298  }
299  }
300  else // parallel and finalized
301  {
302 #ifdef MFEM_USE_MPI
303  MFEM_ASSERT(pS_e == NULL, "essential b.c. already eliminated");
304  pS_e = pS->EliminateRowsCols(ess_rtdof_list);
305 #endif
306  }
307 }
308 
309 void StaticCondensation::ReduceRHS(const Vector &b, Vector &sc_b) const
310 {
311  // sc_b = b_e - A_ep A_pp_inv b_p
312 
313  MFEM_ASSERT(b.Size() == fes->GetVSize(), "'b' has incorrect size");
314 
315  const int NE = fes->GetNE();
316  const int nedofs = tr_fes->GetVSize();
317  const SparseMatrix *tr_cP = NULL;
318  Vector b_r;
319  if (!Parallel() && !(tr_cP = tr_fes->GetConformingProlongation()))
320  {
321  sc_b.SetSize(nedofs);
322  b_r.SetDataAndSize(sc_b.GetData(), sc_b.Size());
323  }
324  else
325  {
326  b_r.SetSize(nedofs);
327  }
328  for (int i = 0; i < nedofs; i++)
329  {
330  b_r(i) = b(rdof_edof[i]);
331  }
332 
333  DenseMatrix U_pe, L_ep;
334  Vector b_p, b_ep;
335  Array<int> rvdofs;
336  for (int i = 0; i < NE; i++)
337  {
338  tr_fes->GetElementVDofs(i, rvdofs);
339  const int ned = rvdofs.Size();
340  const int *rd = rvdofs.GetData();
341  const int npd = elem_pdof.RowSize(i);
342  const int *pd = elem_pdof.GetRow(i);
343  b_p.SetSize(npd);
344  b_ep.SetSize(ned);
345  for (int j = 0; j < npd; j++)
346  {
347  b_p(j) = b(pd[j]);
348  }
349 
350  LUFactors lu(A_data + A_offsets[i], A_ipiv + A_ipiv_offsets[i]);
351  lu.LSolve(npd, 1, b_p);
352 
353  if (symm)
354  {
355  // TODO: handle the symmetric case correctly.
356  U_pe.UseExternalData(lu.data + npd*npd, npd, ned);
357  U_pe.MultTranspose(b_p, b_ep);
358  }
359  else
360  {
361  L_ep.UseExternalData(lu.data + npd*(npd+ned), ned, npd);
362  L_ep.Mult(b_p, b_ep);
363  }
364  for (int j = 0; j < ned; j++)
365  {
366  if (rd[j] >= 0) { b_r(rd[j]) -= b_ep(j); }
367  else { b_r(-1-rd[j]) += b_ep(j); }
368  }
369  }
370  if (!Parallel())
371  {
372  if (tr_cP)
373  {
374  sc_b.SetSize(tr_cP->Width());
375  tr_cP->MultTranspose(b_r, sc_b);
376  }
377  }
378  else
379  {
380 #ifdef MFEM_USE_MPI
381  HypreParMatrix *tr_P = tr_pfes->Dof_TrueDof_Matrix();
382  sc_b.SetSize(tr_P->Width());
383  tr_P->MultTranspose(b_r, sc_b);
384 #endif
385  }
386 }
387 
388 void StaticCondensation::ReduceSolution(const Vector &sol, Vector &sc_sol) const
389 {
390  MFEM_ASSERT(sol.Size() == fes->GetVSize(), "'sol' has incorrect size");
391 
392  const int nedofs = tr_fes->GetVSize();
393  const SparseMatrix *tr_R = tr_fes->GetRestrictionMatrix();
394  Vector sol_r;
395  if (!tr_R)
396  {
397  sc_sol.SetSize(nedofs);
398  sol_r.SetDataAndSize(sc_sol.GetData(), sc_sol.Size());
399  }
400  else
401  {
402  sol_r.SetSize(nedofs);
403  }
404  for (int i = 0; i < nedofs; i++)
405  {
406  sol_r(i) = sol(rdof_edof[i]);
407  }
408  if (tr_R)
409  {
410  sc_sol.SetSize(tr_R->Height());
411  tr_R->Mult(sol_r, sc_sol);
412  }
413 }
414 
416  const Array<int> &ess_tdof_marker, Array<int> &ess_rtdof_marker) const
417 {
418  const int nedofs = tr_fes->GetVSize();
419  const SparseMatrix *R = fes->GetRestrictionMatrix();
420  Array<int> ess_dof_marker;
421  if (!R)
422  {
423  ess_dof_marker.MakeRef(ess_tdof_marker);
424  }
425  else
426  {
427  ess_dof_marker.SetSize(fes->GetVSize());
428  R->BooleanMultTranspose(ess_tdof_marker, ess_dof_marker);
429  }
430  const SparseMatrix *tr_R = tr_fes->GetRestrictionMatrix();
431  Array<int> ess_rdof_marker;
432  if (!tr_R)
433  {
434  ess_rtdof_marker.SetSize(nedofs);
435  ess_rdof_marker.MakeRef(ess_rtdof_marker);
436  }
437  else
438  {
439  ess_rdof_marker.SetSize(nedofs);
440  }
441  for (int i = 0; i < nedofs; i++)
442  {
443  ess_rdof_marker[i] = ess_dof_marker[rdof_edof[i]];
444  }
445  if (tr_R)
446  {
447  ess_rtdof_marker.SetSize(tr_R->Height());
448  tr_R->BooleanMult(ess_rdof_marker, ess_rtdof_marker);
449  }
450 }
451 
453  const Vector &b, const Vector &sc_sol, Vector &sol) const
454 {
455  // sol_e = sc_sol
456  // sol_p = A_pp_inv (b_p - A_pe sc_sol)
457 
458  MFEM_ASSERT(b.Size() == fes->GetVSize(), "'b' has incorrect size");
459 
460  const int nedofs = tr_fes->GetVSize();
461  Vector sol_r;
462  if (!Parallel())
463  {
464  const SparseMatrix *tr_cP = tr_fes->GetConformingProlongation();
465  if (!tr_cP)
466  {
467  sol_r.SetDataAndSize(sc_sol.GetData(), sc_sol.Size());
468  }
469  else
470  {
471  sol_r.SetSize(nedofs);
472  tr_cP->Mult(sc_sol, sol_r);
473  }
474  }
475  else
476  {
477 #ifdef MFEM_USE_MPI
478  sol_r.SetSize(nedofs);
479  tr_pfes->Dof_TrueDof_Matrix()->Mult(sc_sol, sol_r);
480 #endif
481  }
482  sol.SetSize(nedofs+npdofs);
483  for (int i = 0; i < nedofs; i++)
484  {
485  sol(rdof_edof[i]) = sol_r(i);
486  }
487  const int NE = fes->GetNE();
488  Vector b_p, s_e;
489  Array<int> rvdofs;
490  for (int i = 0; i < NE; i++)
491  {
492  tr_fes->GetElementVDofs(i, rvdofs);
493  const int ned = rvdofs.Size();
494  const int npd = elem_pdof.RowSize(i);
495  const int *pd = elem_pdof.GetRow(i);
496  b_p.SetSize(npd);
497 
498  for (int j = 0; j < npd; j++)
499  {
500  b_p(j) = b(pd[j]);
501  }
502  sol_r.GetSubVector(rvdofs, s_e);
503 
504  LUFactors lu(A_data + A_offsets[i], A_ipiv + A_ipiv_offsets[i]);
505  lu.LSolve(npd, 1, b_p);
506  lu.BlockBackSolve(npd, ned, 1, lu.data + npd*npd, s_e, b_p);
507 
508  for (int j = 0; j < npd; j++)
509  {
510  sol(pd[j]) = b_p(j);
511  }
512  }
513 }
514 
515 }
int Size() const
Logical size of the array.
Definition: array.hpp:109
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
Definition: hypre.cpp:1213
int GetVSize() const
Definition: fespace.hpp:164
int * GetJ()
Definition: table.hpp:108
virtual FiniteElementCollection * GetTraceCollection() const
Definition: fe_coll.cpp:38
~StaticCondensation()
Destroy a StaticCondensation object.
Definition: staticcond.cpp:104
void AddColumnsInRow(int r, int ncol)
Definition: table.hpp:72
bool ReducesTrueVSize() const
Definition: staticcond.cpp:118
void ReduceRHS(const Vector &b, Vector &sc_b) const
Definition: staticcond.cpp:309
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
Definition: table.cpp:74
HYPRE_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:963
void SetSize(int s)
Resizes the vector if the new size is different.
Definition: vector.hpp:259
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:161
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, but treat all elements as booleans (zero=false, nonzero=true).
Definition: sparsemat.cpp:573
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:445
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols.
Definition: operator.hpp:41
void BlockBackSolve(int m, int n, int r, const double *U12, const double *X2, double *Y1) const
Definition: densemat.cpp:3821
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Definition: vector.cpp:457
T * GetData()
Returns the data.
Definition: array.hpp:91
HYPRE_Int * GetDofOffsets()
Definition: pfespace.hpp:151
void EliminateRowCol(int rc, const double sol, Vector &rhs, int d=0)
Definition: sparsemat.cpp:1045
Data type dense matrix using column-major storage.
Definition: densemat.hpp:22
int Size() const
Returns the size of the vector.
Definition: vector.hpp:84
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
Definition: table.cpp:179
int GetNumElementInteriorDofs(int i) const
Definition: fespace.hpp:240
void LoseData()
Call this if data has been stolen.
Definition: table.hpp:138
Abstract parallel finite element space.
Definition: pfespace.hpp:28
void Factor(int m)
Definition: densemat.cpp:3557
StaticCondensation(FiniteElementSpace *fespace)
Construct a StaticCondensation object.
Definition: staticcond.cpp:17
void ComputeSolution(const Vector &b, const Vector &sc_sol, Vector &sol) const
Definition: staticcond.cpp:452
double * GetData() const
Definition: vector.hpp:88
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A * x + beta * y.
Definition: hypre.cpp:903
int Size_of_connections() const
Definition: table.hpp:92
void BooleanMultTranspose(const Array< int > &x, Array< int > &y) const
y = At * x, but treat all elements as booleans (zero=false, nonzero=true).
Definition: sparsemat.cpp:596
void AddConnections(int r, const int *c, int nc)
Definition: table.cpp:96
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:185
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
Definition: densemat.cpp:193
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
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:140
HypreParMatrix * RAP(HypreParMatrix *A, HypreParMatrix *P)
Returns the matrix P^t * A * P.
Definition: hypre.cpp:1318
void LSolve(int m, int n, double *X) const
Definition: densemat.cpp:3645
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
Definition: table.cpp:385
const SparseMatrix * GetConformingProlongation()
Definition: fespace.cpp:912
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:154
virtual void Finalize(int skip_zeros=1)
Definition: sparsemat.cpp:680
virtual const SparseMatrix * GetRestrictionMatrix()
Definition: fespace.hpp:150
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Definition: sparsemat.cpp:1733
HypreParMatrix * Dof_TrueDof_Matrix()
The true dof-to-dof interpolation matrix.
Definition: pfespace.cpp:411
int GetOrdering() const
Return the ordering method.
Definition: fespace.hpp:176
double * Data() const
Returns vector of the elements.
Definition: densemat.hpp:77
Abstract finite element space.
Definition: fespace.hpp:62
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
Definition: sparsemat.cpp:417
void Finalize()
Finalize the construction of the Schur complement matrix.
Definition: staticcond.cpp:235
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:323
void SetDataAndSize(double *d, int s)
Definition: vector.hpp:69
void AssembleBdrMatrix(int el, const DenseMatrix &elmat)
Definition: staticcond.cpp:227
void EliminateReducedTrueDofs(const Array< int > &ess_rtdof_list, int keep_diagonal)
Eliminate the given reduced true dofs from the Schur complement matrix S.
Definition: staticcond.cpp:286
void ShiftUpI()
Definition: table.cpp:107
virtual int GetTrueVSize()
Return the number of vector true (conforming) dofs.
Definition: fespace.hpp:167
void AssembleMatrix(int el, const DenseMatrix &elmat)
Definition: staticcond.cpp:189
void MakeJ()
Definition: table.cpp:84
void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
Definition: sparsemat.cpp:492
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Definition: array.hpp:466
Vector data type.
Definition: vector.hpp:33
const FiniteElementCollection * FEColl() const
Definition: fespace.hpp:178
void Mult(const double *x, double *y) const
Matrix vector multiplication.
Definition: densemat.cpp:142
int * GetI()
Definition: table.hpp:107
void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco)
Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this.
Definition: densemat.cpp:2450
void ReduceSolution(const Vector &sol, Vector &sc_sol) const
Definition: staticcond.cpp:388
void UseExternalData(double *d, int h, int w)
Definition: densemat.hpp:60
int RowSize(int i) const
Definition: table.hpp:102
void GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i&#39;th boundary element.
Definition: fespace.cpp:167
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition: densemat.hpp:71
Wrapper for hypre&#39;s ParCSR matrix class.
Definition: hypre.hpp:143
void Init(bool symmetric, bool block_diagonal)
Definition: staticcond.cpp:134
void ConvertMarkerToReducedTrueDofs(const Array< int > &ess_tdof_marker, Array< int > &ess_rtdof_marker) const
Definition: staticcond.cpp:415
static void AdjustVDofs(Array< int > &vdofs)
Definition: fespace.cpp:148
double * data
Definition: densemat.hpp:375