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

475 lines
13 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));
}
}
};
HelmholtzFOSLS::HelmholtzFOSLS(Array<ParFiniteElementSpace * > & fes_,
bool definite_, bool complex_) : fes(fes_), definite(definite_), complex(complex_)
{
n = complex ? 2 : 1;
Init();
};
void HelmholtzFOSLS::Init()
{
f.SetSize(n);
Q.SetSize(n);
p_ex_coeff.SetSize(n);
u_ex_coeff.SetSize(n);
for (int i = 0; i<n; i++)
{
f[i] = nullptr;
Q[i] = nullptr;
p_ex_coeff[i] = nullptr;
u_ex_coeff[i] = nullptr;
}
}
void HelmholtzFOSLS::SetLoadData(Array<FunctionCoefficient * > & f_)
{
f = f_;
}
void HelmholtzFOSLS::SetLoadData(Array<VectorFunctionCoefficient * > & Q_)
{
Q = Q_;
}
void HelmholtzFOSLS::SetEssentialData(Array<FunctionCoefficient * > & p_ex_coeff_)
{
p_ex_coeff = p_ex_coeff_;
}
void HelmholtzFOSLS::SetEssentialData(Array<VectorFunctionCoefficient * > & u_ex_coeff_)
{
u_ex_coeff = u_ex_coeff_;
}
void HelmholtzFOSLS::GetFOSLSLinearSystem(Array2D<HypreParMatrix *> & A_,
BlockVector & X_,
BlockVector & Rhs_)
{
if (A.NumCols() == 0)
{
FormSystem(true);
}
A_ = A;
X_ = X;
Rhs_ = Rhs;
}
void HelmholtzFOSLS::GetFOSLSMatrix(Array2D<HypreParMatrix *> & A_)
{
if (A.NumCols() == 0)
{
FormSystem(false);
}
A_ = A;
}
void HelmholtzFOSLS::FormSystem(bool system)
{
// HYPRE_Int size = fes[0]->GlobalTrueVSize() + fes[1]->GlobalTrueVSize();
Array<int> ess_tdof_list;
Array<int> ess_bdr;
pmesh = fes[0]->GetParMesh();
if (pmesh->bdr_attributes.Size())
{
ess_bdr.SetSize(pmesh->bdr_attributes.Max());
ess_bdr = 1;
}
int blksize = complex ? 5 : 3;
block_offsets.SetSize(blksize);
block_offsets[0] = 0;
block_offsets[1] = fes[0]->GetVSize();
block_offsets[2] = fes[1]->GetVSize();
if (complex)
{
block_offsets[3] = fes[0]->GetVSize();
block_offsets[4] = fes[1]->GetVSize();
}
block_offsets.PartialSum();
block_trueOffsets.SetSize(blksize);
block_trueOffsets[0] = 0;
block_trueOffsets[1] = fes[0]->GetTrueVSize();
block_trueOffsets[2] = fes[1]->GetTrueVSize();
if (complex)
{
block_trueOffsets[3] = fes[0]->GetTrueVSize();
block_trueOffsets[4] = fes[1]->GetTrueVSize();
}
block_trueOffsets.PartialSum();
ParGridFunction p_gf_re, u_gf_re, p_gf_im, u_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;
p_gf_re.MakeRef(fes[0],x.GetBlock(0)); p_gf_re = 0.0;
u_gf_re.MakeRef(fes[1],x.GetBlock(1)); u_gf_re = 0.0;
if (complex)
{
p_gf_im.MakeRef(fes[0],x.GetBlock(2)); p_gf_im = 0.0;
u_gf_im.MakeRef(fes[1],x.GetBlock(3)); u_gf_im = 0.0;
}
if (p_ex_coeff[0])
{
p_gf_re.ProjectCoefficient(*p_ex_coeff[0]);
}
if (u_ex_coeff[0])
{
u_gf_re.ProjectCoefficient(*u_ex_coeff[0]);
}
if (complex)
{
if (p_ex_coeff[1])
{
p_gf_im.ProjectCoefficient(*p_ex_coeff[1]);
}
if (u_ex_coeff[1])
{
u_gf_im.ProjectCoefficient(*u_ex_coeff[1]);
}
}
}
ConstantCoefficient negone(-1.0);
ConstantCoefficient one(1.0);
ConstantCoefficient negomeg(-omega);
ConstantCoefficient omeg(omega);
ConstantCoefficient omeg2(omega * omega);
ProductCoefficient omega_f(omeg,*f[0]);
ProductCoefficient neg_f(negone,*f[0]);
ParLinearForm b0, b1;
if(system)
{
b0.Update(fes[0],rhs.GetBlock(0),0);
b1.Update(fes[1],rhs.GetBlock(1),0);
b0.AddDomainIntegrator(new DomainLFIntegrator(omega_f));
if (definite)
{
b1.AddDomainIntegrator(new VectorFEDomainLFDivIntegrator(neg_f));
}
else
{
b1.AddDomainIntegrator(new VectorFEDomainLFDivIntegrator(*f[0]));
}
b0.Assemble();
b1.Assemble();
}
A.SetSize(2,2);
for (int i = 0; i<2; i++)
{
for (int j = 0; j<2; j++)
{
A[i][j] = nullptr;
}
}
ParBilinearForm a00(fes[0]);
a00.AddDomainIntegrator(new DiffusionIntegrator(one));
a00.AddDomainIntegrator(new MassIntegrator(omeg2));
a00.Assemble();
if (system)
{
a00.EliminateEssentialBC(ess_bdr,x.GetBlock(0),rhs.GetBlock(0),mfem::Operator::DIAG_ONE);
}
else
{
a00.EliminateEssentialBC(ess_bdr,mfem::Operator::DIAG_ONE);
}
a00.Finalize();
A[0][0] = a00.ParallelAssemble();
ParMixedBilinearForm a01(fes[1],fes[0]);
if (definite)
{
a01.AddDomainIntegrator(new MixedScalarDivergenceIntegrator(negomeg));
}
else
{
a01.AddDomainIntegrator(new MixedScalarDivergenceIntegrator(omeg));
}
a01.AddDomainIntegrator(new MixedVectorWeakDivergenceIntegrator(omeg));
a01.Assemble();
a01.EliminateTestDofs(ess_bdr);
a01.Finalize();
A[0][1] = a01.ParallelAssemble();
if (system)
{
ParMixedBilinearForm a10(fes[0],fes[1]);
if (definite)
{
a10.AddDomainIntegrator(new MixedScalarWeakGradientIntegrator(omeg));
}
else
{
a10.AddDomainIntegrator(new MixedScalarWeakGradientIntegrator(negomeg));
}
a10.AddDomainIntegrator(new MixedVectorGradientIntegrator(negomeg));
a10.Assemble();
a10.EliminateTrialDofs(ess_bdr,x.GetBlock(0),rhs.GetBlock(1));
a10.Finalize();
A[1][0] = a10.ParallelAssemble();
}
else
{
A[1][0] = A[0][1]->Transpose();
}
ParBilinearForm a11(fes[1]);
a11.AddDomainIntegrator(new DivDivIntegrator(one));
a11.AddDomainIntegrator(new VectorFEMassIntegrator(omeg2));
a11.Assemble();
a11.Finalize();
A[1][1] = a11.ParallelAssemble();
if (system)
{
fes[0]->GetRestrictionMatrix()->Mult(x.GetBlock(0), X.GetBlock(0));
fes[1]->GetRestrictionMatrix()->Mult(x.GetBlock(1), X.GetBlock(1));
fes[0]->GetProlongationMatrix()->MultTranspose(rhs.GetBlock(0),Rhs.GetBlock(0));
fes[1]->GetProlongationMatrix()->MultTranspose(rhs.GetBlock(1),Rhs.GetBlock(1));
}
}