MFEM  v3.2
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
volta_solver.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 "../../config/config.hpp"
13 
14 #ifdef MFEM_USE_MPI
15 
16 #include "volta_solver.hpp"
17 
18 using namespace std;
19 namespace mfem
20 {
21 using namespace miniapps;
22 
23 namespace electromagnetics
24 {
25 
26 VoltaSolver::VoltaSolver(ParMesh & pmesh, int order,
27  Array<int> & dbcs, Vector & dbcv,
28  Array<int> & nbcs, Vector & nbcv,
29  Coefficient & epsCoef,
30  double (*phi_bc )(const Vector&),
31  double (*rho_src)(const Vector&),
32  void (*p_src )(const Vector&, Vector&))
33  : myid_(0),
34  num_procs_(1),
35  order_(order),
36  pmesh_(&pmesh),
37  dbcs_(&dbcs),
38  dbcv_(&dbcv),
39  nbcs_(&nbcs),
40  nbcv_(&nbcv),
41  visit_dc_(NULL),
42  H1FESpace_(NULL),
43  HCurlFESpace_(NULL),
44  HDivFESpace_(NULL),
45  divEpsGrad_(NULL),
46  h1Mass_(NULL),
47  h1SurfMass_(NULL),
48  hCurlMass_(NULL),
49  hDivMass_(NULL),
50  hCurlHDivEps_(NULL),
51  hCurlHDiv_(NULL),
52  Grad_(NULL),
53  phi_(NULL),
54  rho_(NULL),
55  sigma_(NULL),
56  e_(NULL),
57  d_(NULL),
58  p_(NULL),
59  epsCoef_(&epsCoef),
60  phiBCCoef_(NULL),
61  rhoCoef_(NULL),
62  pCoef_(NULL),
63  phi_bc_(phi_bc),
64  rho_src_(rho_src),
65  p_src_(p_src)
66 {
67  // Initialize MPI variables
68  MPI_Comm_size(pmesh_->GetComm(), &num_procs_);
69  MPI_Comm_rank(pmesh_->GetComm(), &myid_);
70 
71  // Define compatible parallel finite element spaces on the parallel
72  // mesh. Here we use arbitrary order H1, Nedelec, and Raviart-Thomas finite
73  // elements.
74  H1FESpace_ = new H1_ParFESpace(pmesh_,order,pmesh_->Dimension());
75  HCurlFESpace_ = new ND_ParFESpace(pmesh_,order,pmesh_->Dimension());
76  HDivFESpace_ = new RT_ParFESpace(pmesh_,order,pmesh_->Dimension());
77 
78  // Select surface attributes for Dirichlet BCs
79  ess_bdr_.SetSize(pmesh.bdr_attributes.Max());
80  ess_bdr_ = 0; // Deselect all outer surfaces
81  for (int i=0; i<dbcs_->Size(); i++)
82  {
83  ess_bdr_[(*dbcs_)[i]-1] = 1;
84  }
85 
86  // Setup various coefficients
87 
88  // Potential on outer surface
89  if ( phi_bc_ != NULL )
90  {
91  phiBCCoef_ = new FunctionCoefficient(*phi_bc_);
92  }
93 
94  // Volume Charge Density
95  if ( rho_src_ != NULL )
96  {
97  rhoCoef_ = new FunctionCoefficient(rho_src_);
98  }
99 
100  // Polarization
101  if ( p_src_ != NULL )
102  {
103  pCoef_ = new VectorFunctionCoefficient(pmesh_->SpaceDimension(),
104  p_src_);
105  }
106 
107  // Bilinear Forms
108  divEpsGrad_ = new ParBilinearForm(H1FESpace_);
109  divEpsGrad_->AddDomainIntegrator(new DiffusionIntegrator(*epsCoef_));
110 
111  hDivMass_ = new ParBilinearForm(HDivFESpace_);
113 
114  hCurlHDivEps_ = new ParMixedBilinearForm(HCurlFESpace_,HDivFESpace_);
115  hCurlHDivEps_->AddDomainIntegrator(new VectorFEMassIntegrator(*epsCoef_));
116 
117  // Discrete Grad operator
118  Grad_ = new ParDiscreteGradOperator(H1FESpace_, HCurlFESpace_);
119 
120  // Build grid functions
121  phi_ = new ParGridFunction(H1FESpace_);
122  d_ = new ParGridFunction(HDivFESpace_);
123  e_ = new ParGridFunction(HCurlFESpace_);
124 
125  if ( rho_src_ )
126  {
127  rho_ = new ParGridFunction(H1FESpace_);
128 
129  h1Mass_ = new ParBilinearForm(H1FESpace_);
130  h1Mass_->AddDomainIntegrator(new MassIntegrator);
131  }
132 
133  if ( p_src_ )
134  {
135  p_ = new ParGridFunction(HCurlFESpace_);
136 
137  hCurlMass_ = new ParBilinearForm(HCurlFESpace_);
139 
140  hCurlHDiv_ = new ParMixedBilinearForm(HCurlFESpace_, HDivFESpace_);
142  }
143 
144  if ( nbcs_->Size() > 0 )
145  {
146  sigma_ = new ParGridFunction(H1FESpace_);
147 
148  h1SurfMass_ = new ParBilinearForm(H1FESpace_);
149  h1SurfMass_->AddBoundaryIntegrator(new MassIntegrator);
150  }
151 }
152 
154 {
155  delete phiBCCoef_;
156  delete rhoCoef_;
157  delete pCoef_;
158 
159  delete phi_;
160  delete rho_;
161  delete sigma_;
162  delete d_;
163  delete e_;
164  delete p_;
165 
166  delete Grad_;
167 
168  delete divEpsGrad_;
169  delete h1Mass_;
170  delete h1SurfMass_;
171  delete hCurlMass_;
172  delete hDivMass_;
173  delete hCurlHDivEps_;
174  delete hCurlHDiv_;
175 
176  delete H1FESpace_;
177  delete HCurlFESpace_;
178 
179  map<string,socketstream*>::iterator mit;
180  for (mit=socks_.begin(); mit!=socks_.end(); mit++)
181  {
182  delete mit->second;
183  }
184 }
185 
186 HYPRE_Int
188 {
189  return H1FESpace_->GlobalTrueVSize();
190 }
191 
192 void
194 {
195  HYPRE_Int size_h1 = H1FESpace_->GlobalTrueVSize();
196  HYPRE_Int size_nd = HCurlFESpace_->GlobalTrueVSize();
197  HYPRE_Int size_rt = HDivFESpace_->GlobalTrueVSize();
198  if (myid_ == 0)
199  {
200  cout << "Number of H1 unknowns: " << size_h1 << endl;
201  cout << "Number of H(Curl) unknowns: " << size_nd << endl;
202  cout << "Number of H(Div) unknowns: " << size_rt << endl;
203  }
204 }
205 
207 {
208  if (myid_ == 0) { cout << "Assembling ... " << flush; }
209 
210  divEpsGrad_->Assemble();
211  divEpsGrad_->Finalize();
212 
213  hDivMass_->Assemble();
214  hDivMass_->Finalize();
215 
216  hCurlHDivEps_->Assemble();
217  hCurlHDivEps_->Finalize();
218 
219  if ( h1Mass_ )
220  {
221  h1Mass_->Assemble();
222  h1Mass_->Finalize();
223  }
224  if ( h1SurfMass_ )
225  {
226  h1SurfMass_->Assemble();
227  h1SurfMass_->Finalize();
228  }
229  if ( hCurlMass_ )
230  {
231  hCurlMass_->Assemble();
232  hCurlMass_->Finalize();
233  }
234  if ( hCurlHDiv_ )
235  {
236  hCurlHDiv_->Assemble();
237  hCurlHDiv_->Finalize();
238  }
239 
240  if (myid_ == 0) { cout << "done." << endl << flush; }
241 }
242 
243 void
245 {
246  if (myid_ == 0) { cout << "Updating ..." << endl; }
247 
248  // Inform the spaces that the mesh has changed
249  // Note: we don't need to interpolate any GridFunctions on the new mesh
250  // so we pass 'false' to skip creation of any transformation matrices.
251  H1FESpace_->Update(false);
252  HCurlFESpace_->Update(false);
253  HDivFESpace_->Update(false);
254 
255  // Inform the grid functions that the space has changed.
256  phi_->Update();
257  d_->Update();
258  e_->Update();
259  if ( rho_ ) { rho_->Update(); }
260  if ( sigma_ ) { sigma_->Update(); }
261  if ( p_ ) { p_->Update(); }
262 
263  // Inform the bilinear forms that the space has changed.
264  divEpsGrad_->Update();
265  hDivMass_->Update();
266  hCurlHDivEps_->Update();
267 
268  if ( h1Mass_ ) { h1Mass_->Update(); }
269  if ( h1SurfMass_ ) { h1SurfMass_->Update(); }
270  if ( hCurlMass_ ) { hCurlMass_->Update(); }
271  if ( hCurlHDiv_ ) { hCurlHDiv_->Update(); }
272 
273  // Inform the other objects that the space has changed.
274  Grad_->Update();
275 }
276 
277 void
279 {
280  if (myid_ == 0) { cout << "Running solver ... " << endl; }
281 
282  // Initialize the electric potential with its boundary conditions
283  *phi_ = 0.0;
284 
285  if ( dbcs_->Size() > 0 )
286  {
287  if ( phiBCCoef_ )
288  {
289  // Apply gradient boundary condition
290  phi_->ProjectBdrCoefficient(*phiBCCoef_, ess_bdr_);
291  }
292  else
293  {
294  // Apply piecewise constant boundary condition
295  Array<int> dbc_bdr_attr(pmesh_->bdr_attributes.Max());
296  for (int i=0; i<dbcs_->Size(); i++)
297  {
298  ConstantCoefficient voltage((*dbcv_)[i]);
299  dbc_bdr_attr = 0;
300  dbc_bdr_attr[(*dbcs_)[i]-1] = 1;
301  phi_->ProjectBdrCoefficient(voltage, dbc_bdr_attr);
302  }
303  }
304  }
305 
306  // Initialize the RHS vector
307  HypreParVector *RHS = new HypreParVector(H1FESpace_);
308  *RHS = 0.0;
309 
310  // Initialize the volumetric charge density
311  if ( rho_ )
312  {
313  rho_->ProjectCoefficient(*rhoCoef_);
314 
315  HypreParMatrix *MassH1 = h1Mass_->ParallelAssemble();
316  HypreParVector *Rho = rho_->ParallelProject();
317 
318  MassH1->Mult(*Rho,*RHS);
319 
320  delete MassH1;
321  delete Rho;
322  }
323 
324  // Initialize the Polarization
325  HypreParVector *P = NULL;
326  if ( p_ )
327  {
328  p_->ProjectCoefficient(*pCoef_);
329  P = p_->ParallelProject();
330 
331  HypreParMatrix *MassHCurl = hCurlMass_->ParallelAssemble();
332  HypreParVector *PD = new HypreParVector(HCurlFESpace_);
333 
334  MassHCurl->Mult(*P,*PD);
335  Grad_->MultTranspose(*PD,*RHS,-1.0,1.0);
336 
337  delete MassHCurl;
338  delete PD;
339 
340  }
341 
342  // Initialize the surface charge density
343  if ( sigma_ )
344  {
345  *sigma_ = 0.0;
346 
347  Array<int> nbc_bdr_attr(pmesh_->bdr_attributes.Max());
348  for (int i=0; i<nbcs_->Size(); i++)
349  {
350  ConstantCoefficient sigma_coef((*nbcv_)[i]);
351  nbc_bdr_attr = 0;
352  nbc_bdr_attr[(*nbcs_)[i]-1] = 1;
353  sigma_->ProjectBdrCoefficient(sigma_coef, nbc_bdr_attr);
354  }
355 
356  HypreParMatrix *MassS = h1SurfMass_->ParallelAssemble();
357  HypreParVector *Sigma = sigma_->ParallelProject();
358 
359  MassS->Mult(*Sigma,*RHS,1.0,1.0);
360 
361  delete MassS;
362  delete Sigma;
363  }
364 
365  // Apply Dirichlet BCs to matrix and right hand side
366  HypreParMatrix *DivEpsGrad = divEpsGrad_->ParallelAssemble();
367  HypreParVector *Phi = phi_->ParallelProject();
368 
369  // Apply the boundary conditions to the assembled matrix and vectors
370  if ( dbcs_->Size() > 0 )
371  {
372  // According to the selected surfaces
373  divEpsGrad_->ParallelEliminateEssentialBC(ess_bdr_,
374  *DivEpsGrad,
375  *Phi, *RHS);
376  }
377  else
378  {
379  // No surfaces were labeled as Dirichlet so eliminate one DoF
380  Array<int> dof_list(0);
381  if ( myid_ == 0 )
382  {
383  dof_list.SetSize(1);
384  dof_list[0] = 0;
385  }
386  DivEpsGrad->EliminateRowsCols(dof_list, *Phi, *RHS);
387  }
388 
389  // Define and apply a parallel PCG solver for AX=B with the AMG
390  // preconditioner from hypre.
391  HypreSolver *amg = new HypreBoomerAMG(*DivEpsGrad);
392  HyprePCG *pcg = new HyprePCG(*DivEpsGrad);
393  pcg->SetTol(1e-12);
394  pcg->SetMaxIter(500);
395  pcg->SetPrintLevel(2);
396  pcg->SetPreconditioner(*amg);
397  pcg->Mult(*RHS, *Phi);
398 
399  delete amg;
400  delete pcg;
401  delete DivEpsGrad;
402  delete RHS;
403 
404  // Extract the parallel grid function corresponding to the finite
405  // element approximation Phi. This is the local solution on each
406  // processor.
407  *phi_ = *Phi;
408 
409  // Compute the negative Gradient of the solution vector. This is
410  // the magnetic field corresponding to the scalar potential
411  // represented by phi.
412  HypreParVector *E = new HypreParVector(HCurlFESpace_);
413  Grad_->Mult(*Phi,*E,-1.0);
414  *e_ = *E;
415 
416  delete Phi;
417 
418  // Compute electric displacement (D) from E and P
419  if (myid_ == 0) { cout << "Computing D ..." << flush; }
420 
421  ParGridFunction ed(HDivFESpace_);
422  hCurlHDivEps_->Mult(*e_, ed);
423  if ( p_ )
424  {
425  hCurlHDiv_->AddMult(*p_, ed, -1.0);
426  }
427 
428  HypreParMatrix MassHDiv;
429  Vector ED, D;
430 
431  Array<int> dbc_dofs_d;
432  hDivMass_->FormLinearSystem(dbc_dofs_d, *d_, ed, MassHDiv, D, ED);
433 
434  HyprePCG *pcgM = new HyprePCG(MassHDiv);
435  pcgM->SetTol(1e-12);
436  pcgM->SetMaxIter(500);
437  pcgM->SetPrintLevel(0);
438  HypreDiagScale diagM;
439  pcgM->SetPreconditioner(diagM);
440  pcgM->Mult(ED, D);
441 
442  hDivMass_->RecoverFEMSolution(D, ed, *d_);
443 
444  if (myid_ == 0) { cout << "done." << flush; }
445 
446  delete pcgM;
447  delete E;
448  delete P;
449 
450  if (myid_ == 0) { cout << "Solver done. " << endl; }
451 }
452 
453 void
455 {
456  if (myid_ == 0) { cout << "Estimating Error ... " << flush; }
457 
458  // Space for the discontinuous (original) flux
459  DiffusionIntegrator flux_integrator(*epsCoef_);
460  L2_FECollection flux_fec(order_, pmesh_->Dimension());
461  // ND_FECollection flux_fec(order_, pmesh_->Dimension());
462  ParFiniteElementSpace flux_fes(pmesh_, &flux_fec, pmesh_->SpaceDimension());
463 
464  // Space for the smoothed (conforming) flux
465  double norm_p = 1;
466  RT_FECollection smooth_flux_fec(order_-1, pmesh_->Dimension());
467  ParFiniteElementSpace smooth_flux_fes(pmesh_, &smooth_flux_fec);
468 
469  L2ZZErrorEstimator(flux_integrator, *phi_,
470  smooth_flux_fes, flux_fes, errors, norm_p);
471 
472  if (myid_ == 0) { cout << "done." << endl; }
473 }
474 
475 void
477 {
478  visit_dc_ = &visit_dc;
479 
480  visit_dc.RegisterField("Phi", phi_);
481  visit_dc.RegisterField("D", d_);
482  visit_dc.RegisterField("E", e_);
483  if ( rho_ ) { visit_dc.RegisterField("Rho", rho_); }
484  if ( p_ ) { visit_dc.RegisterField("P", p_); }
485  if ( sigma_ ) { visit_dc.RegisterField("Sigma", sigma_); }
486 }
487 
488 void
490 {
491  if ( visit_dc_ )
492  {
493  if (myid_ == 0) { cout << "Writing VisIt files ..." << flush; }
494 
495  HYPRE_Int prob_size = this->GetProblemSize();
496  visit_dc_->SetCycle(it);
497  visit_dc_->SetTime(prob_size);
498  visit_dc_->Save();
499 
500  if (myid_ == 0) { cout << " done." << endl; }
501  }
502 }
503 
504 void
506 {
507  if ( myid_ == 0 ) { cout << "Opening GLVis sockets." << endl; }
508 
509  socks_["Phi"] = new socketstream;
510  socks_["Phi"]->precision(8);
511 
512  socks_["D"] = new socketstream;
513  socks_["D"]->precision(8);
514 
515  socks_["E"] = new socketstream;
516  socks_["E"]->precision(8);
517 
518  if ( rho_)
519  {
520  socks_["Rho"] = new socketstream;
521  socks_["Rho"]->precision(8);
522  }
523  if ( p_)
524  {
525  socks_["P"] = new socketstream;
526  socks_["P"]->precision(8);
527  }
528  if ( sigma_)
529  {
530  socks_["Sigma"] = new socketstream;
531  socks_["Sigma"]->precision(8);
532  }
533 }
534 
535 void
537 {
538  if (myid_ == 0) { cout << "Sending data to GLVis ..." << flush; }
539 
540  char vishost[] = "localhost";
541  int visport = 19916;
542 
543  int Wx = 0, Wy = 0; // window position
544  int Ww = 350, Wh = 350; // window size
545  int offx = Ww+10, offy = Wh+45; // window offsets
546 
547  VisualizeField(*socks_["Phi"], vishost, visport,
548  *phi_, "Electric Potential (Phi)", Wx, Wy, Ww, Wh);
549  Wx += offx;
550 
551  VisualizeField(*socks_["D"], vishost, visport,
552  *d_, "Electric Displacement (D)", Wx, Wy, Ww, Wh);
553  Wx += offx;
554 
555  VisualizeField(*socks_["E"], vishost, visport,
556  *e_, "Electric Field (E)", Wx, Wy, Ww, Wh);
557 
558  Wx = 0; Wy += offy; // next line
559 
560  if ( rho_ )
561  {
562  VisualizeField(*socks_["Rho"], vishost, visport,
563  *rho_, "Charge Density (Rho)", Wx, Wy, Ww, Wh);
564  Wx += offx;
565  }
566  if ( p_ )
567  {
568  VisualizeField(*socks_["P"], vishost, visport,
569  *p_, "Electric Polarization (P)", Wx, Wy, Ww, Wh);
570  Wx += offx;
571  }
572  if ( sigma_ )
573  {
574  VisualizeField(*socks_["Sigma"], vishost, visport,
575  *sigma_, "Surface Charge Density (Sigma)", Wx, Wy, Ww, Wh);
576  Wx += offx;
577  }
578  if (myid_ == 0) { cout << " done." << endl; }
579 }
580 
581 } // namespace electromagnetics
582 
583 } // namespace mfem
584 
585 #endif // MFEM_USE_MPI
void SetTol(double tol)
Definition: hypre.cpp:1964
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:1260
virtual void AddMult(const Vector &x, Vector &y, const double a=1.0) const
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
virtual void RegisterField(const char *field_name, GridFunction *gf)
Add a grid function to the collection and update the root file.
Subclass constant coefficient.
Definition: coefficient.hpp:57
virtual void Update(bool want_transform=true)
Definition: pfespace.cpp:2155
HYPRE_Int MultTranspose(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A^t * x + beta * y.
Definition: pfem_extras.cpp:98
virtual void Save()
Save the collection and a VisIt root file.
Abstract parallel finite element space.
Definition: pfespace.hpp:28
void RegisterVisItFields(VisItDataCollection &visit_dc)
void ProjectCoefficient(Coefficient &coeff)
Definition: pgridfunc.cpp:247
virtual void Finalize(int skip_zeros=1)
Finalizes the matrix initialization.
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:940
void SetPrintLevel(int print_lvl)
Definition: hypre.cpp:1979
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
virtual void Update(FiniteElementSpace *nfes=NULL)
void GetErrorEstimates(Vector &errors)
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
The BoomerAMG solver in hypre.
Definition: hypre.hpp:705
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A * x + beta * y.
Definition: pfem_extras.cpp:82
void VisualizeField(socketstream &sock, const char *vishost, int visport, ParGridFunction &gf, const char *title, int x, int y, int w, int h)
Jacobi preconditioner in hypre.
Definition: hypre.hpp:666
Data collection with VisIt I/O routines.
T Max() const
Definition: array.cpp:90
void Assemble(int skip_zeros=1)
void Assemble(int skip_zeros=1)
Assemble the local matrix.
int Dimension() const
Definition: mesh.hpp:523
void SetTime(double t)
Set physical time (for time-dependent simulations)
void SetMaxIter(int max_iter)
Definition: hypre.cpp:1969
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition: fe_coll.hpp:179
int SpaceDimension() const
Definition: mesh.hpp:524
Wrapper for hypre&#39;s parallel vector class.
Definition: hypre.hpp:58
Array< int > bdr_attributes
Definition: mesh.hpp:141
MPI_Comm GetComm() const
Definition: pmesh.hpp:96
PCG solver in hypre.
Definition: hypre.hpp:565
Base class Coefficient that may optionally depend on time.
Definition: coefficient.hpp:31
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:331
double L2ZZErrorEstimator(BilinearFormIntegrator &flux_integrator, const ParGridFunction &x, ParFiniteElementSpace &smooth_flux_fes, ParFiniteElementSpace &flux_fes, Vector &errors, int norm_p, double solver_tol, int solver_max_it)
Definition: pgridfunc.cpp:542
void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
Class for parallel bilinear form.
virtual void Finalize(int skip_zeros=1)
Finalizes the matrix initialization.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi)
Adds new Boundary Integrator.
void FormLinearSystem(Array< int > &ess_tdof_list, Vector &x, Vector &b, HypreParMatrix &A, Vector &X, Vector &B, int copy_interior=0)
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
Definition: hypre.cpp:1984
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator.
void ParallelEliminateEssentialBC(const Array< int > &bdr_attr_is_ess, HypreParMatrix &A, const HypreParVector &X, HypreParVector &B) const
Class for parallel bilinear form.
Abstract class for hypre&#39;s solvers and preconditioners.
Definition: hypre.hpp:529
class for C-function coefficient
Vector data type.
Definition: vector.hpp:33
Class for parallel grid function.
Definition: pgridfunc.hpp:31
Wrapper for hypre&#39;s ParCSR matrix class.
Definition: hypre.hpp:150
virtual void Mult(const HypreParVector &b, HypreParVector &x) const
Solve Ax=b with hypre&#39;s PCG.
Definition: hypre.cpp:2005
Class for parallel meshes.
Definition: pmesh.hpp:28
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
Integrator for (Q u, v) for VectorFiniteElements.
Definition: bilininteg.hpp:465
void ProjectBdrCoefficient(Coefficient &coeff, Array< int > &attr)
Definition: gridfunc.hpp:173
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
Definition: pgridfunc.cpp:126
Arbitrary order &quot;L2-conforming&quot; discontinuous finite elements.
Definition: fe_coll.hpp:130