23 namespace electromagnetics
29 MaxwellSolver::MaxwellSolver(
ParMesh & pmesh,
int order,
30 double (*eps )(
const Vector&),
80 MPI_Comm_size(pmesh_->
GetComm(), &num_procs_);
81 MPI_Comm_rank(pmesh_->
GetComm(), &myid_);
89 this->
height = HCurlFESpace_->GlobalTrueVSize();
93 lossy_ = abcs.
Size() > 0 || sigma_ != NULL;
105 if ( myid_ == 0 && logging_ > 0 )
107 cout <<
"Creating Permittivity Coefficient" << endl;
113 if ( muInv_ == NULL )
119 if ( myid_ == 0 && logging_ > 0 )
121 cout <<
"Creating Permeability Coefficient" << endl;
127 if ( sigma_ != NULL )
129 if ( myid_ == 0 && logging_ > 0 )
131 cout <<
"Creating Conductivity Coefficient" << endl;
137 if ( abcs.
Size() > 0 )
139 if ( myid_ == 0 && logging_ > 0 )
141 cout <<
"Creating Admittance Coefficient" << endl;
149 if ( dbcs.
Size() > 0 )
151 if ( myid_ == 0 && logging_ > 0 )
153 cout <<
"Configuring Dirichlet BC" << endl;
157 HCurlFESpace_->GetEssentialTrueDofs(dbc_marker_, dbc_dofs_);
159 if ( dEdt_bc_ != NULL )
171 if ( myid_ == 0 && logging_ > 0 )
173 cout <<
"Creating H(Div) Mass Operator" << endl;
178 if ( myid_ == 0 && logging_ > 0 )
180 cout <<
"Creating Weak Curl Operator" << endl;
193 if ( sigmaCoef_ || etaInvCoef_ )
195 if ( myid_ == 0 && logging_ > 0 )
197 cout <<
"Creating H(Curl) Loss Operator" << endl;
202 if ( myid_ == 0 && logging_ > 0 )
204 cout <<
"Adding domain integrator for conductive regions" << endl;
211 if ( myid_ == 0 && logging_ > 0 )
213 cout <<
"Adding boundary integrator for absorbing boundary" << endl;
227 if ( myid_ == 0 && logging_ > 0 )
229 cout <<
"Creating discrete curl operator" << endl;
255 if ( myid_ == 0 && logging_ > 0 )
257 cout <<
"Creating Current Source" << endl;
297 delete WeakCurlMuInv_;
299 delete hDivMassMuInv_;
301 delete weakCurlMuInv_;
303 delete HCurlFESpace_;
306 map<int, ParBilinearForm*>::iterator mit1;
307 for (mit1=a1_.begin(); mit1!=a1_.end(); mit1++)
311 delete diagScale_[i];
316 map<int, Coefficient*>::iterator mit2;
317 for (mit2=dtCoef_.begin(); mit2!=dtCoef_.end(); mit2++)
321 for (mit2=dtSigmaCoef_.begin(); mit2!=dtSigmaCoef_.end(); mit2++)
325 for (mit2=dtEtaInvCoef_.begin(); mit2!=dtEtaInvCoef_.end(); mit2++)
330 map<string, socketstream*>::iterator mit3;
331 for (mit3=socks_.begin(); mit3!=socks_.end(); mit3++)
350 cout <<
"Number of H(Curl) unknowns: " << size_nd << endl;
351 cout <<
"Number of H(Div) unknowns: " << size_rt << endl << flush;
358 eCoef_ = &EFieldCoef;
366 bCoef_ = &BFieldCoef;
374 implicitSolve(0.0, B, dEdt);
380 implicitSolve(dt, B, dEdt);
384 MaxwellSolver::setupSolver(
const int idt,
const double dt)
const 386 if ( pcg_.find(idt) == pcg_.end() )
388 if ( myid_ == 0 && logging_ > 0 )
390 cout <<
"Creating implicit operator for dt = " << dt << endl;
394 a1_[idt]->AddDomainIntegrator(
405 a1_[idt]->AddDomainIntegrator(
410 dtEtaInvCoef_[idt] =
new TransformedCoefficient(dtCoef_[idt],
413 a1_[idt]->AddBoundaryIntegrator(
414 new VectorFEMassIntegrator(dtEtaInvCoef_[idt]),
415 const_cast<Array<int>&
>(abc_marker_));
419 a1_[idt]->Assemble();
420 a1_[idt]->Finalize();
421 A1_[idt] = a1_[idt]->ParallelAssemble();
423 diagScale_[idt] =
new HypreDiagScale(*A1_[idt]);
424 pcg_[idt] =
new HyprePCG(*A1_[idt]);
425 pcg_[idt]->SetTol(1.0e-12);
426 pcg_[idt]->SetMaxIter(200);
427 pcg_[idt]->SetPrintLevel(0);
428 pcg_[idt]->SetPreconditioner(*diagScale_[idt]);
433 MaxwellSolver::implicitSolve(
double dt,
const Vector &B, Vector &dEdt)
const 435 int idt = hCurlLosses_ ? ((int)(dtScale_ * dt / dtMax_)) : 0;
438 weakCurlMuInv_->
Mult(*b_, *rhs_);
443 hCurlLosses_->
AddMult(*e_, *rhs_, -1.0);
457 const_cast<Array<int>&
>(dbc_marker_));
461 setupSolver(idt, dt);
464 a1_[idt]->FormLinearSystem(dbc_dofs_, *dedt_, *rhs_, *A1_[idt], dEdt, *RHS_);
467 pcg_[idt]->Mult(*RHS_, dEdt);
470 a1_[idt]->RecoverFEMSolution(dEdt, *rhs_, *dedt_);
494 int iter = 0, nstep = 20;
495 double dt0 = 1.0, dt1 = 1.0, change = 1.0, ptol = 0.001;
502 while ( iter < nstep && change > ptol )
507 NegCurl_->
Mult(*v0,*u0);
508 M2MuInv_->
Mult(*u0,*HD_);
511 pcg_[0]->Mult(*RHS_,*v1);
514 dt1 = 2.0/sqrt(lambda);
515 change = fabs((dt1-dt0)/dt0);
518 if ( myid_ == 0 && logging_ > 1 )
520 cout << iter <<
": " << dt0 <<
" " << change << endl;
540 A1_[0]->Mult(*E_,*RHS_);
541 M2MuInv_->
Mult(*B_,*HD_);
551 visit_dc_ = &visit_dc;
566 if ( myid_ == 0 && logging_ > 1 )
567 { cout <<
"Writing VisIt files ..." << flush; }
579 if ( myid_ == 0 && logging_ > 1 ) { cout <<
" " << endl << flush; }
586 if ( myid_ == 0 && logging_ > 0 )
587 { cout <<
"Opening GLVis sockets." << endl << flush; }
590 socks_[
"E"]->precision(8);
593 socks_[
"B"]->precision(8);
598 socks_[
"J"]->precision(8);
601 if ( myid_ == 0 && logging_ > 0 )
602 { cout <<
"GLVis sockets open." << endl << flush; }
608 if ( myid_ == 0 && logging_ > 1 )
609 { cout <<
"Sending data to GLVis ..." << flush; }
615 int Ww = 350,
Wh = 350;
619 *e_,
"Electric Field (E)",
Wx,
Wy,
Ww,
Wh);
623 *b_,
"Magnetic Flux Density (B)",
Wx,
Wy,
Ww,
Wh);
634 *j_,
"Current Density (J)",
Wx,
Wy,
Ww,
Wh);
636 if ( myid_ == 0 && logging_ > 1 ) { cout <<
" " << flush; }
643 #endif // MFEM_USE_MPI
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
Base class for vector Coefficients that optionally depend on time and space.
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.
Type type
Describes the form of the TimeDependentOperator.
int Dimension() const
Dimension of the reference space used within the elements.
double prodFunc(double a, double b)
Vector coefficient that is constant in space and time.
HypreParMatrix * ParallelAssemble() const
Returns the matrix "assembled" on the true dofs.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
HYPRE_BigInt GetProblemSize()
double muInv(const Vector &x)
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
void SetInitialBField(VectorCoefficient &BFieldCoef)
void ImplicitSolve(const double dt, const Vector &x, Vector &k)
Solve the equation: k = f(x + dt k, t), for the unknown k at the current time t.
void RegisterVisItFields(VisItDataCollection &visit_dc)
double GetMaximumTimeStep() const
This type assumes F(x,k,t) = k, i.e. k = f(x,t) = G(x,t).
Data collection with VisIt I/O routines.
HYPRE_Int Randomize(HYPRE_Int seed)
Set random values.
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
void VisualizeField(socketstream &sock, const char *vishost, int visport, ParGridFunction &gf, const char *title, int x=0, int y=0, int w=400, int h=400, bool vec=false)
This is the most general type, no assumptions on F and G.
void SetTime(double t)
Set physical time (for time-dependent simulations)
HYPRE_BigInt GlobalTrueVSize() const
A general vector function coefficient.
Wrapper for hypre's parallel vector class.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void WriteVisItFields(int it=0)
virtual void Save() override
Save the collection and a VisIt root file.
void Distribute(const Vector *tv)
int height
Dimension of the output / number of rows in the matrix.
double InnerProduct(HypreParVector *x, HypreParVector *y)
virtual void SetTime(double t)
Set the time for time dependent coefficients.
void Mult(const Vector &B, Vector &dEdt) const
Perform the action of the operator: y = k = f(x, t), where k solves the algebraic equation F(x...
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
Project the tangential components of the given VectorCoefficient on the boundary. Only boundary attri...
void j_src(const Vector &x, double t, Vector &j)
int Size() const
Return the logical size of the array.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
A general function coefficient.
double sigma(const Vector &x)
Class for parallel grid function.
HYPRE_Int MultTranspose(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0) const
Computes y = alpha * A^t * x + beta * y.
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
Class for parallel meshes.
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0) const
Computes y = alpha * A * x + beta * y.
int width
Dimension of the input / number of columns in the matrix.
void SetInitialEField(VectorCoefficient &EFieldCoef)
virtual void RegisterField(const std::string &field_name, GridFunction *gf) override
Add a grid function to the collection and update the root file.