20 using namespace common;
22 namespace electromagnetics
25 VoltaSolver::VoltaSolver(
ParMesh & pmesh,
int order,
29 double (*phi_bc )(
const Vector&),
30 double (*rho_src)(
const Vector&),
70 rho_src_func_(rho_src),
72 point_charge_params_(point_charges),
76 MPI_Comm_size(pmesh_->
GetComm(), &num_procs_);
77 MPI_Comm_rank(pmesh_->
GetComm(), &myid_);
93 if ( phi_bc_func_ != NULL )
99 if ( rho_src_func_ != NULL )
105 if ( p_src_func_ != NULL )
139 if ( point_charge_params_.
Size() > 0 )
142 int npts = point_charge_params_.
Size() / (dim + 1);
143 point_charges_.resize(npts);
146 for (
int i=0; i<npts; i++)
148 for (
int d=0; d<
dim; d++)
150 cent[d] = point_charge_params_[(dim + 1) * i + d];
152 double s = point_charge_params_[(dim + 1) * i + dim];
155 point_charges_[i]->SetScale(s);
156 point_charges_[i]->SetDeltaCenter(cent);
181 if ( nbcs_->
Size() > 0 )
214 delete hCurlHDivEps_;
219 delete HCurlFESpace_;
223 for (
unsigned int i=0; i<point_charges_.size(); i++)
225 delete point_charges_[i];
228 map<string,socketstream*>::iterator mit;
229 for (mit=socks_.begin(); mit!=socks_.end(); mit++)
250 cout <<
"Number of H1 unknowns: " << size_h1 << endl;
251 cout <<
"Number of H(Curl) unknowns: " << size_nd << endl;
252 cout <<
"Number of H(Div) unknowns: " << size_rt << endl;
253 cout <<
"Number of L2 unknowns: " << size_l2 << endl;
259 if (myid_ == 0) { cout <<
"Assembling ... " << flush; }
303 if (myid_ == 0) { cout <<
"done." << endl << flush; }
309 if (myid_ == 0) { cout <<
"Updating ..." << endl; }
314 H1FESpace_->
Update(
false);
315 HCurlFESpace_->
Update(
false);
316 HDivFESpace_->
Update(
false);
317 L2FESpace_->
Update(
false);
327 if ( rho_src_ ) { rho_src_->
Update(); }
328 if ( sigma_src_ ) { sigma_src_->
Update(); }
329 if ( p_src_ ) { p_src_->
Update(); }
336 if ( h1Mass_ ) { h1Mass_->
Update(); }
337 if ( h1SurfMass_ ) { h1SurfMass_->
Update(); }
338 if ( hCurlHDiv_ ) { hCurlHDiv_->
Update(); }
339 if ( weakDiv_ ) { weakDiv_->
Update(); }
349 if (myid_ == 0) { cout <<
"Running solver ... " << endl; }
354 if ( dbcs_->
Size() > 0 )
365 for (
int i=0; i<dbcs_->
Size(); i++)
369 if ((*dbcs_)[i] <= dbc_bdr_attr.Size())
371 dbc_bdr_attr[(*dbcs_)[i]-1] = 1;
382 h1Mass_->
AddMult(*rho_src_, *rhod_);
389 weakDiv_->
AddMult(*p_src_, *rhod_);
398 for (
int i=0; i<nbcs_->
Size(); i++)
402 if ((*nbcs_)[i] <= nbc_bdr_attr.Size())
404 nbc_bdr_attr[(*nbcs_)[i]-1] = 1;
408 h1SurfMass_->
AddMult(*sigma_src_, *rhod_);
412 if ( dbcs_->
Size() > 0 )
423 ess_bdr_tdofs_[0] = 0;
453 grad_->
Mult(*phi_, *e_); *e_ *= -1.0;
456 if (myid_ == 0) { cout <<
"Computing D ..." << flush; }
459 hCurlHDivEps_->
Mult(*e_, ed);
462 hCurlHDiv_->
AddMult(*p_src_, ed, -1.0);
482 div_->
Mult(*d_, *rho_);
484 if (myid_ == 0) { cout <<
"done." << flush; }
488 double charge_rho = (*l2_vol_int_)(*rho_);
491 double charge_D = (*rt_surf_int_)(*d_);
495 cout << endl <<
"Total charge: \n"
496 <<
" Volume integral of charge density: " << charge_rho
497 <<
"\n Surface integral of dielectric flux: " << charge_D
502 if (myid_ == 0) { cout <<
"Solver done. " << endl; }
508 if (myid_ == 0) { cout <<
"Estimating Error ... " << flush; }
522 smooth_flux_fes, flux_fes, errors, norm_p);
524 if (myid_ == 0) { cout <<
"done." << endl; }
530 visit_dc_ = &visit_dc;
536 if ( rho_src_ ) { visit_dc.
RegisterField(
"Rho Source", rho_src_); }
537 if ( p_src_ ) { visit_dc.
RegisterField(
"P Source", p_src_); }
538 if ( sigma_src_ ) { visit_dc.
RegisterField(
"Sigma Source", sigma_src_); }
546 if (myid_ == 0) { cout <<
"Writing VisIt files ..." << flush; }
553 if (myid_ == 0) { cout <<
" done." << endl; }
560 if ( myid_ == 0 ) { cout <<
"Opening GLVis sockets." << endl; }
563 socks_[
"Phi"]->precision(8);
566 socks_[
"D"]->precision(8);
569 socks_[
"E"]->precision(8);
572 socks_[
"Rho"]->precision(8);
577 socks_[
"RhoSrc"]->precision(8);
582 socks_[
"PSrc"]->precision(8);
587 socks_[
"SigmaSrc"]->precision(8);
594 if (myid_ == 0) { cout <<
"Sending data to GLVis ..." << flush; }
600 int Ww = 350,
Wh = 350;
604 *phi_,
"Electric Potential (Phi)", Wx,
Wy, Ww,
Wh);
608 *e_,
"Electric Field (E)", Wx,
Wy, Ww,
Wh);
612 *d_,
"Electric Displacement (D)", Wx,
Wy, Ww,
Wh);
616 *rho_,
"Charge Density", Wx,
Wy, Ww,
Wh);
622 *rho_src_,
"Charge Density Source (Rho)", Wx,
Wy, Ww,
Wh);
628 *p_src_,
"Electric Polarization Source (P)",
635 *sigma_src_,
"Surface Charge Density Source (Sigma)",
639 if (myid_ == 0) { cout <<
" done." << endl; }
646 #endif // MFEM_USE_MPI
void WriteVisItFields(int it=0)
int Size() const
Return the logical size of the array.
Class for domain integration L(v) := (f, v)
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1)
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
A coefficient that is constant across space and time.
void AttrToMarker(int max_attr, const Array< int > &attrs, Array< int > &marker)
Convert a set of attribute numbers to a marker array.
HYPRE_Int GetProblemSize()
virtual void Update(bool want_transform=true)
Delta function coefficient optionally multiplied by a weight coefficient and a scaled time dependent ...
int Size() const
Returns the size of the vector.
virtual void Save()
Save the collection and a VisIt root file.
Abstract parallel finite element space.
void RegisterVisItFields(VisItDataCollection &visit_dc)
virtual void ProjectCoefficient(Coefficient &coeff)
void SetPrintLevel(int print_lvl)
void GetErrorEstimates(Vector &errors)
The BoomerAMG solver in hypre.
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Jacobi preconditioner in hypre.
Data collection with VisIt I/O routines.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
HYPRE_Int GlobalTrueVSize() const
void SetTime(double t)
Set physical time (for time-dependent simulations)
void SetMaxIter(int max_iter)
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
A general vector function coefficient.
int SpaceDimension() const
Wrapper for hypre's parallel vector class.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, Array< int > &attr)
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
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)
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection and update the root file.
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
A general function coefficient.
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
Class for parallel grid function.
Wrapper for hypre's ParCSR matrix class.
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
virtual void Mult(const HypreParVector &b, HypreParVector &x) const
Solve Ax=b with hypre's PCG.
Class for parallel meshes.
Arbitrary order "L2-conforming" discontinuous finite elements.