21 using namespace miniapps;
23 namespace electromagnetics
27 double prodFunc(
double a,
double b) {
return a * b; }
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;
145 if ( abcs.
Size() == 1 && abcs[0] < 0 )
154 for (
int i=0; i<abcs.
Size(); i++)
156 abc_marker_[abcs[i]-1] = 1;
163 if ( dbcs.
Size() > 0 )
165 if ( myid_ == 0 && logging_ > 0 )
167 cout <<
"Configuring Dirichlet BC" << endl;
170 if ( dbcs.
Size() == 1 && dbcs[0] < 0 )
179 for (
int i=0; i<dbcs.
Size(); i++)
181 dbc_marker_[dbcs[i]-1] = 1;
185 HCurlFESpace_->GetEssentialTrueDofs(dbc_marker_, dbc_dofs_);
187 if ( dEdt_bc_ != NULL )
199 if ( myid_ == 0 && logging_ > 0 )
201 cout <<
"Creating H(Div) Mass Operator" << endl;
206 if ( myid_ == 0 && logging_ > 0 )
208 cout <<
"Creating Weak Curl Operator" << endl;
221 if ( sigmaCoef_ || etaInvCoef_ )
223 if ( myid_ == 0 && logging_ > 0 )
225 cout <<
"Creating H(Curl) Loss Operator" << endl;
230 if ( myid_ == 0 && logging_ > 0 )
232 cout <<
"Adding domain integrator for conductive regions" << endl;
239 if ( myid_ == 0 && logging_ > 0 )
241 cout <<
"Adding boundary integrator for absorbing boundary" << endl;
255 if ( myid_ == 0 && logging_ > 0 )
257 cout <<
"Creating discrete curl operator" << endl;
283 if ( myid_ == 0 && logging_ > 0 )
285 cout <<
"Creating Current Source" << endl;
325 delete hDivMassMuInv_;
327 delete weakCurlMuInv_;
329 delete HCurlFESpace_;
332 map<int, ParBilinearForm*>::iterator mit1;
333 for (mit1=a1_.begin(); mit1!=a1_.end(); mit1++)
337 delete diagScale_[i];
342 map<int, Coefficient*>::iterator mit2;
343 for (mit2=dtCoef_.begin(); mit2!=dtCoef_.end(); mit2++)
347 for (mit2=dtSigmaCoef_.begin(); mit2!=dtSigmaCoef_.end(); mit2++)
351 for (mit2=dtEtaInvCoef_.begin(); mit2!=dtEtaInvCoef_.end(); mit2++)
356 map<string, socketstream*>::iterator mit3;
357 for (mit3=socks_.begin(); mit3!=socks_.end(); mit3++)
376 cout <<
"Number of H(Curl) unknowns: " << size_nd << endl;
377 cout <<
"Number of H(Div) unknowns: " << size_rt << endl << flush;
384 eCoef_ = &EFieldCoef;
392 bCoef_ = &BFieldCoef;
400 implicitSolve(0.0, B, dEdt);
406 implicitSolve(dt, B, dEdt);
410 MaxwellSolver::setupSolver(
const int idt,
const double dt)
const
412 if ( pcg_.find(idt) == pcg_.end() )
414 if ( myid_ == 0 && logging_ > 0 )
416 cout <<
"Creating implicit operator for dt = " << dt << endl;
420 a1_[idt]->AddDomainIntegrator(
431 a1_[idt]->AddDomainIntegrator(
436 dtEtaInvCoef_[idt] =
new TransformedCoefficient(dtCoef_[idt],
439 a1_[idt]->AddBoundaryIntegrator(
440 new VectorFEMassIntegrator(dtEtaInvCoef_[idt]),
441 const_cast<Array<int>&
>(abc_marker_));
445 a1_[idt]->Assemble();
446 a1_[idt]->Finalize();
447 A1_[idt] = a1_[idt]->ParallelAssemble();
449 diagScale_[idt] =
new HypreDiagScale(*A1_[idt]);
450 pcg_[idt] =
new HyprePCG(*A1_[idt]);
451 pcg_[idt]->SetTol(1.0e-12);
452 pcg_[idt]->SetMaxIter(200);
453 pcg_[idt]->SetPrintLevel(0);
454 pcg_[idt]->SetPreconditioner(*diagScale_[idt]);
459 MaxwellSolver::implicitSolve(
double dt,
const Vector &B, Vector &dEdt)
const
461 int idt = hCurlLosses_ ? ((int)(dtScale_ * dt / dtMax_)) : 0;
464 weakCurlMuInv_->
Mult(*b_, *rhs_);
469 hCurlLosses_->
AddMult(*e_, *rhs_, -1.0);
483 const_cast<Array<int>&
>(dbc_marker_));
487 setupSolver(idt, dt);
490 a1_[idt]->FormLinearSystem(dbc_dofs_, *dedt_, *rhs_, *A1_[idt], dEdt, *RHS_);
493 pcg_[idt]->Mult(*RHS_, dEdt);
496 a1_[idt]->RecoverFEMSolution(dEdt, *rhs_, *dedt_);
520 int iter = 0, nstep = 20;
521 double dt0 = 1.0, dt1 = 1.0, change = 1.0, ptol = 0.001;
528 while ( iter < nstep && change > ptol )
533 NegCurl_->
Mult(*v0,*u0);
534 M2MuInv_->
Mult(*u0,*HD_);
537 pcg_[0]->Mult(*RHS_,*v1);
540 dt1 = 2.0/sqrt(lambda);
541 change = fabs((dt1-dt0)/dt0);
544 if ( myid_ == 0 && logging_ > 1 )
546 cout << iter <<
": " << dt0 <<
" " << change << endl;
566 A1_[0]->Mult(*E_,*RHS_);
567 M2MuInv_->
Mult(*B_,*HD_);
577 visit_dc_ = &visit_dc;
592 if ( myid_ == 0 && logging_ > 1 )
593 { cout <<
"Writing VisIt files ..." << flush; }
605 if ( myid_ == 0 && logging_ > 1 ) { cout <<
" " << endl << flush; }
612 if ( myid_ == 0 && logging_ > 0 )
613 { cout <<
"Opening GLVis sockets." << endl << flush; }
616 socks_[
"E"]->precision(8);
619 socks_[
"B"]->precision(8);
624 socks_[
"J"]->precision(8);
627 if ( myid_ == 0 && logging_ > 0 )
628 { cout <<
"GLVis sockets open." << endl << flush; }
634 if ( myid_ == 0 && logging_ > 1 )
635 { cout <<
"Sending data to GLVis ..." << flush; }
637 char vishost[] =
"localhost";
641 int Ww = 350, Wh = 350;
642 int offx = Ww+10, offy = Wh+45;
645 *e_,
"Electric Field (E)", Wx, Wy, Ww, Wh);
649 *b_,
"Magnetic Flux Density (B)", Wx, Wy, Ww, Wh);
660 *j_,
"Current Density (J)", Wx, Wy, Ww, Wh);
662 if ( myid_ == 0 && logging_ > 1 ) { cout <<
" " << flush; }
669 #endif // MFEM_USE_MPI
int Size() const
Logical size of the array.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
Subclass constant coefficient.
Type type
Describes the form of the TimeDependentOperator.
HYPRE_Int MultTranspose(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A^t * x + beta * y.
double prodFunc(double a, double b)
virtual void Save()
Save the collection and a VisIt root file.
virtual void ProjectCoefficient(Coefficient &coeff)
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A * x + beta * y.
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.
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, bool vec)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
double muInv(const Vector &x)
HYPRE_Int GlobalTrueVSize() const
HYPRE_Int Randomize(HYPRE_Int seed)
Set random values.
This is the most general type, no assumptions on F and G.
void SetTime(double t)
Set physical time (for time-dependent simulations)
HypreParMatrix * ParallelAssemble() const
Returns the matrix "assembled" on the true dofs.
Wrapper for hypre's parallel vector class.
HYPRE_Int GetProblemSize()
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 SetSize(int nsize)
Change logical size of the array, keep existing entries.
void Distribute(const Vector *tv)
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)
void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
for VectorFiniteElements (Nedelec, Raviart-Thomas)
class for C-function coefficient
Class for parallel grid function.
virtual void Assemble(int skip_zeros=1)
Class for parallel meshes.
int width
Dimension of the input / number of columns in the matrix.
Integrator for (Q u, v) for VectorFiniteElements.
void SetInitialEField(VectorCoefficient &EFieldCoef)
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
double sigma(const Vector &x)