21 using namespace common;
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
int Size() const
Return the logical size of the array.
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.
double prodFunc(double a, double b)
Vector coefficient that is constant in space and time.
HYPRE_BigInt GlobalTrueVSize() const
virtual void Save()
Save the collection and a VisIt root file.
HYPRE_BigInt GetProblemSize()
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.
double GetMaximumTimeStep() const
void RegisterVisItFields(VisItDataCollection &visit_dc)
This type assumes F(x,k,t) = k, i.e. k = f(x,t) = G(x,t).
Data collection with VisIt I/O routines.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
double muInv(const Vector &x)
HYPRE_Int Randomize(HYPRE_Int seed)
Set random values.
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)
A general vector function coefficient.
HypreParMatrix * ParallelAssemble() const
Returns the matrix "assembled" on the true dofs.
Wrapper for hypre's parallel vector class.
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...
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void j_src(const Vector &x, double t, Vector &j)
void WriteVisItFields(int it=0)
void Distribute(const Vector *tv)
HYPRE_Int MultTranspose(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0) const
Computes y = alpha * A^t * x + beta * y.
int height
Dimension of the output / number of rows in the matrix.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection and update the root file.
double InnerProduct(HypreParVector *x, HypreParVector *y)
virtual void SetTime(double t)
Set the time for time dependent coefficients.
FDualNumber< tbase > sqrt(const FDualNumber< tbase > &f)
sqrt([dual number])
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
Project the tangential components of the given VectorCoefficient on the boundary. Only boundary attri...
for VectorFiniteElements (Nedelec, Raviart-Thomas)
A general function coefficient.
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0) const
Computes y = alpha * A * x + beta * y.
Class for parallel grid function.
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
Class for parallel meshes.
int width
Dimension of the input / number of columns in the matrix.
void SetInitialEField(VectorCoefficient &EFieldCoef)
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
double sigma(const Vector &x)