Files
mfem/examples/maxwell-solver/FOSLS.cpp
T

236 lines
6.5 KiB
C++

#include "FOSLS.hpp"
ComplexMaxwellFOSLS::ComplexMaxwellFOSLS(ParFiniteElementSpace * fes_) : fes(fes_)
{ };
void ComplexMaxwellFOSLS::SetLoadData(Array<VectorFunctionCoefficient *> & loads_)
{
loads = loads_;
}
void ComplexMaxwellFOSLS::SetEssentialData(Array<VectorFunctionCoefficient *> & ess_data_)
{
ess_data = ess_data_;
}
void ComplexMaxwellFOSLS::GetFOSLSLinearSystem(Array2D<HypreParMatrix *> & A_,
BlockVector & X_,
BlockVector & Rhs_)
{
if (A.NumCols() == 0)
{
FormSystem(true);
}
A_ = A;
X_ = X;
Rhs_ = Rhs;
}
void ComplexMaxwellFOSLS::GetFOSLSMatrix(Array2D<HypreParMatrix *> & A_)
{
if (A.NumCols() == 0)
{
FormSystem(false);
}
A_ = A;
}
void ComplexMaxwellFOSLS::FormSystem(bool system)
{
HYPRE_Int size = fes->GlobalTrueVSize();
Array<int> ess_tdof_list;
Array<int> ess_bdr;
pmesh = fes->GetParMesh();
if (pmesh->bdr_attributes.Size())
{
ess_bdr.SetSize(pmesh->bdr_attributes.Max());
ess_bdr = 1;
fes->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
VectorFunctionCoefficient * E_ex_re = ess_data[0];
VectorFunctionCoefficient * H_ex_re = ess_data[1];
VectorFunctionCoefficient * E_ex_im = ess_data[2];
VectorFunctionCoefficient * H_ex_im = ess_data[3];
VectorFunctionCoefficient * f_ex_re = loads[0];
VectorFunctionCoefficient * g_ex_re = loads[1];
VectorFunctionCoefficient * f_ex_im = loads[2];
VectorFunctionCoefficient * g_ex_im = loads[3];
int n = fes->GetVSize();
int N = fes->GetTrueVSize();
block_offsets.SetSize(5);
block_offsets[0] = 0;
block_offsets[1] = n;
block_offsets[2] = n;
block_offsets[3] = n;
block_offsets[4] = n;
block_offsets.PartialSum();
block_trueOffsets.SetSize(5);
block_trueOffsets[0] = 0;
block_trueOffsets[1] = N;
block_trueOffsets[2] = N;
block_trueOffsets[3] = N;
block_trueOffsets[4] = N;
block_trueOffsets.PartialSum();
ParGridFunction E_gf_re, E_gf_im, H_gf_re, H_gf_im;
if(system)
{
x.Update(block_offsets);
rhs.Update(block_offsets);
X.Update(block_trueOffsets);
Rhs.Update(block_trueOffsets);
x = 0.0; rhs = 0.0; X = 0.0; Rhs = 0.0;
E_gf_re.MakeRef(fes,x.GetBlock(0)); E_gf_re = 0.0;
H_gf_re.MakeRef(fes,x.GetBlock(1)); H_gf_re = 0.0;
E_gf_im.MakeRef(fes,x.GetBlock(2)); E_gf_im = 0.0;
H_gf_im.MakeRef(fes,x.GetBlock(3)); H_gf_im = 0.0;
E_gf_re.ProjectCoefficient(*E_ex_re);
E_gf_im.ProjectCoefficient(*E_ex_im);
}
ConstantCoefficient one(1.0);
ConstantCoefficient negone(-1.0);
ConstantCoefficient negomeg(-omega);
ConstantCoefficient omeg(omega);
ConstantCoefficient omeg2(omega * omega);
ScalarVectorProductCoefficient wJi(omeg,*g_ex_im);
ScalarVectorProductCoefficient negJr(negone,*g_ex_re);
ScalarVectorProductCoefficient negwJr(negomeg,*g_ex_re);
ScalarVectorProductCoefficient negJi(negone,*g_ex_im);
ParLinearForm b0, b1, b2, b3;
if(system)
{
b0.Update(fes,rhs.GetBlock(0),0);
b1.Update(fes,rhs.GetBlock(1),0);
b2.Update(fes,rhs.GetBlock(2),0);
b3.Update(fes,rhs.GetBlock(3),0);
b0.AddDomainIntegrator(new VectorFEDomainLFIntegrator(wJi));
b1.AddDomainIntegrator(new VectorFEDomainLFCurlIntegrator(negJr));
b2.AddDomainIntegrator(new VectorFEDomainLFIntegrator(negwJr));
b3.AddDomainIntegrator(new VectorFEDomainLFCurlIntegrator(negJi));
b0.Assemble();
b1.Assemble();
b2.Assemble();
b3.Assemble();
}
A.SetSize(4,4);
for (int i = 0; i<4; i++)
{
for (int j = 0; j<4; j++)
{
A[i][j] = nullptr;
}
}
ParBilinearForm a00(fes);
a00.AddDomainIntegrator(new CurlCurlIntegrator(one));
a00.AddDomainIntegrator(new VectorFEMassIntegrator(omeg2));
a00.Assemble();
if (system)
{
a00.EliminateEssentialBC(ess_bdr,x.GetBlock(0),rhs.GetBlock(0),mfem::Operator::DIAG_ONE);
}
else
{
a00.EliminateEssentialBC(ess_bdr);
}
a00.Finalize();
A[0][0] = a00.ParallelAssemble();
ParMixedBilinearForm a03(fes,fes);
a03.AddDomainIntegrator(new MixedVectorCurlIntegrator(negomeg));
a03.AddDomainIntegrator(new MixedVectorWeakCurlIntegrator(negomeg));
a03.Assemble();
a03.EliminateTestDofs(ess_bdr);
a03.Finalize();
A[0][3] = a03.ParallelAssemble();
ParBilinearForm a11(fes);
a11.AddDomainIntegrator(new CurlCurlIntegrator(one));
a11.AddDomainIntegrator(new VectorFEMassIntegrator(omeg2));
a11.Assemble();
a11.Finalize();
A[1][1] = a11.ParallelAssemble();
ParMixedBilinearForm a21(fes,fes);
a21.AddDomainIntegrator(new MixedVectorCurlIntegrator(omeg));
a21.AddDomainIntegrator(new MixedVectorWeakCurlIntegrator(omeg));
a21.Assemble();
a21.EliminateTestDofs(ess_bdr);
a21.Finalize();
A[2][1] = a21.ParallelAssemble();
if (system)
{
ParMixedBilinearForm a12(fes,fes);
a12.AddDomainIntegrator(new MixedVectorCurlIntegrator(omeg));
a12.AddDomainIntegrator(new MixedVectorWeakCurlIntegrator(omeg));
a12.Assemble();
a12.EliminateTrialDofs(ess_bdr,x.GetBlock(2),rhs.GetBlock(1));
a12.Finalize();
A[1][2] = a12.ParallelAssemble();
}
else
{
A[1][2] = A[2][1]->Transpose();
}
ParBilinearForm a22(fes);
a22.AddDomainIntegrator(new CurlCurlIntegrator(one));
a22.AddDomainIntegrator(new VectorFEMassIntegrator(omeg2));
a22.Assemble();
if (system)
{
a22.EliminateEssentialBC(ess_bdr,x.GetBlock(2),rhs.GetBlock(2),mfem::Operator::DIAG_ONE);
}
else
{
a22.EliminateEssentialBC(ess_bdr);
}
a22.Finalize();
A[2][2] = a22.ParallelAssemble();
if (system)
{
ParMixedBilinearForm a30(fes,fes);
a30.AddDomainIntegrator(new MixedVectorCurlIntegrator(negomeg));
a30.AddDomainIntegrator(new MixedVectorWeakCurlIntegrator(negomeg));
a30.Assemble();
a30.EliminateTrialDofs(ess_bdr,x.GetBlock(0),rhs.GetBlock(3));
a30.Finalize();
A[3][0] = a30.ParallelAssemble();
}
else
{
A[3][0] = A[0][3]->Transpose();
}
ParBilinearForm a33(fes);
a33.AddDomainIntegrator(new CurlCurlIntegrator(one));
a33.AddDomainIntegrator(new VectorFEMassIntegrator(omeg2));
a33.Assemble();
a33.Finalize();
A[3][3] = a33.ParallelAssemble();
if (system)
{
for (int i = 0; i<4; i++)
{
fes->GetRestrictionMatrix()->Mult(x.GetBlock(i), X.GetBlock(i));
fes->GetProlongationMatrix()->MultTranspose(rhs.GetBlock(i),Rhs.GetBlock(i));
}
}
}