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 WeakCurlMuInv_;
327 delete hDivMassMuInv_;
329 delete weakCurlMuInv_;
331 delete HCurlFESpace_;
334 map<int, ParBilinearForm*>::iterator mit1;
335 for (mit1=a1_.begin(); mit1!=a1_.end(); mit1++)
339 delete diagScale_[i];
344 map<int, Coefficient*>::iterator mit2;
345 for (mit2=dtCoef_.begin(); mit2!=dtCoef_.end(); mit2++)
349 for (mit2=dtSigmaCoef_.begin(); mit2!=dtSigmaCoef_.end(); mit2++)
353 for (mit2=dtEtaInvCoef_.begin(); mit2!=dtEtaInvCoef_.end(); mit2++)
358 map<string, socketstream*>::iterator mit3;
359 for (mit3=socks_.begin(); mit3!=socks_.end(); mit3++)
378 cout <<
"Number of H(Curl) unknowns: " << size_nd << endl;
379 cout <<
"Number of H(Div) unknowns: " << size_rt << endl << flush;
386 eCoef_ = &EFieldCoef;
394 bCoef_ = &BFieldCoef;
402 implicitSolve(0.0, B, dEdt);
408 implicitSolve(dt, B, dEdt);
412 MaxwellSolver::setupSolver(
const int idt,
const double dt)
const
414 if ( pcg_.find(idt) == pcg_.end() )
416 if ( myid_ == 0 && logging_ > 0 )
418 cout <<
"Creating implicit operator for dt = " << dt << endl;
422 a1_[idt]->AddDomainIntegrator(
433 a1_[idt]->AddDomainIntegrator(
438 dtEtaInvCoef_[idt] =
new TransformedCoefficient(dtCoef_[idt],
441 a1_[idt]->AddBoundaryIntegrator(
442 new VectorFEMassIntegrator(dtEtaInvCoef_[idt]),
443 const_cast<Array<int>&
>(abc_marker_));
447 a1_[idt]->Assemble();
448 a1_[idt]->Finalize();
449 A1_[idt] = a1_[idt]->ParallelAssemble();
451 diagScale_[idt] =
new HypreDiagScale(*A1_[idt]);
452 pcg_[idt] =
new HyprePCG(*A1_[idt]);
453 pcg_[idt]->SetTol(1.0e-12);
454 pcg_[idt]->SetMaxIter(200);
455 pcg_[idt]->SetPrintLevel(0);
456 pcg_[idt]->SetPreconditioner(*diagScale_[idt]);
461 MaxwellSolver::implicitSolve(
double dt,
const Vector &B, Vector &dEdt)
const
463 int idt = hCurlLosses_ ? ((int)(dtScale_ * dt / dtMax_)) : 0;
466 weakCurlMuInv_->
Mult(*b_, *rhs_);
471 hCurlLosses_->
AddMult(*e_, *rhs_, -1.0);
485 const_cast<Array<int>&
>(dbc_marker_));
489 setupSolver(idt, dt);
492 a1_[idt]->FormLinearSystem(dbc_dofs_, *dedt_, *rhs_, *A1_[idt], dEdt, *RHS_);
495 pcg_[idt]->Mult(*RHS_, dEdt);
498 a1_[idt]->RecoverFEMSolution(dEdt, *rhs_, *dedt_);
522 int iter = 0, nstep = 20;
523 double dt0 = 1.0, dt1 = 1.0, change = 1.0, ptol = 0.001;
530 while ( iter < nstep && change > ptol )
535 NegCurl_->
Mult(*v0,*u0);
536 M2MuInv_->
Mult(*u0,*HD_);
539 pcg_[0]->Mult(*RHS_,*v1);
542 dt1 = 2.0/sqrt(lambda);
543 change = fabs((dt1-dt0)/dt0);
546 if ( myid_ == 0 && logging_ > 1 )
548 cout << iter <<
": " << dt0 <<
" " << change << endl;
568 A1_[0]->Mult(*E_,*RHS_);
569 M2MuInv_->
Mult(*B_,*HD_);
579 visit_dc_ = &visit_dc;
594 if ( myid_ == 0 && logging_ > 1 )
595 { cout <<
"Writing VisIt files ..." << flush; }
607 if ( myid_ == 0 && logging_ > 1 ) { cout <<
" " << endl << flush; }
614 if ( myid_ == 0 && logging_ > 0 )
615 { cout <<
"Opening GLVis sockets." << endl << flush; }
618 socks_[
"E"]->precision(8);
621 socks_[
"B"]->precision(8);
626 socks_[
"J"]->precision(8);
629 if ( myid_ == 0 && logging_ > 0 )
630 { cout <<
"GLVis sockets open." << endl << flush; }
636 if ( myid_ == 0 && logging_ > 1 )
637 { cout <<
"Sending data to GLVis ..." << flush; }
639 char vishost[] =
"localhost";
643 int Ww = 350,
Wh = 350;
647 *e_,
"Electric Field (E)", Wx,
Wy, Ww,
Wh);
651 *b_,
"Magnetic Flux Density (B)", Wx,
Wy, Ww,
Wh);
662 *j_,
"Current Density (J)", Wx,
Wy, Ww,
Wh);
664 if ( myid_ == 0 && logging_ > 1 ) { cout <<
" " << flush; }
671 #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.
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)
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)
class for C-function coefficient
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.
Integrator for (Q u, v) for VectorFiniteElements.
void SetInitialEField(VectorCoefficient &EFieldCoef)
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)
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
double sigma(const Vector &x)