- Thank you received: 0
Calculating residual in finite element space with dirichlet boundary condition
5 years 7 months ago #1544
by NilsHM
Calculating residual in finite element space with dirichlet boundary condition was created by NilsHM
Hi!
I am working on a program that can calculate the induced eddy current given a periodic changing magnetic field in the frequency domain.
For the domain where eddy durrents can occur I use the following finite element space:
fes = HCurl(mesh, order = 3, nograds = True, complex = True, definedon = "iron", dirichlet = "gamma_iron")
I need the dirichlet boundary condition to make sure that the eddy current cannot escape the iron domain.
When using the inverse or the CG solver the system of equations converges and the result is physically correct.
To make sure the result is correct I want to calculate the residual of the problem: r = a*sol - f
r := residual, a := bilinear form, sol := solution, f := linear form
But the residual is not as low as expected although the solver says otherwise.
This only occurs in this finite element space when there is a dirichlet boundary condition.
I tried deleting all non-free dofs from the matrix and vectors using fes.FreeDofs(True) but that did not change the result.
Is there a way to calculate the residual just like the CG solver does?
Here is a short summary of all settings I set:
fes = HCurl(mesh, order = 3, nograds = True, complex = True, definedon = "iron", dirichlet = "gamma_iron")
a = BilinearForm(fes, symmetric = True)
a += SymbolicBFI(...)
a.Assemble()
a_inv = a.mat.Inverse(freedofs = fes.FreeDofs())
f = LinearForm(fes)
f += SymbolicLFI(..., definedon = mesh.Materials("iron"))
f.Assemble()
sol = GridFunction(fes)
sol.vec.data = a.inv*f.vec
res = GridFunction(fes)
res.vec.data = a.mat*sol.vec - f.vec
I am working on a program that can calculate the induced eddy current given a periodic changing magnetic field in the frequency domain.
For the domain where eddy durrents can occur I use the following finite element space:
fes = HCurl(mesh, order = 3, nograds = True, complex = True, definedon = "iron", dirichlet = "gamma_iron")
I need the dirichlet boundary condition to make sure that the eddy current cannot escape the iron domain.
When using the inverse or the CG solver the system of equations converges and the result is physically correct.
To make sure the result is correct I want to calculate the residual of the problem: r = a*sol - f
r := residual, a := bilinear form, sol := solution, f := linear form
But the residual is not as low as expected although the solver says otherwise.
This only occurs in this finite element space when there is a dirichlet boundary condition.
I tried deleting all non-free dofs from the matrix and vectors using fes.FreeDofs(True) but that did not change the result.
Is there a way to calculate the residual just like the CG solver does?
Here is a short summary of all settings I set:
fes = HCurl(mesh, order = 3, nograds = True, complex = True, definedon = "iron", dirichlet = "gamma_iron")
a = BilinearForm(fes, symmetric = True)
a += SymbolicBFI(...)
a.Assemble()
a_inv = a.mat.Inverse(freedofs = fes.FreeDofs())
f = LinearForm(fes)
f += SymbolicLFI(..., definedon = mesh.Materials("iron"))
f.Assemble()
sol = GridFunction(fes)
sol.vec.data = a.inv*f.vec
res = GridFunction(fes)
res.vec.data = a.mat*sol.vec - f.vec
5 years 7 months ago #1546
by joachim
Replied by joachim on topic Calculating residual in finite element space with dirichlet boundary condition
Hi Nils,
you gave the answer yourself: The residual of the linear equation should be 0 only for the non-Dirichlet rows.
You can define a projector
proj = Projector(fes.FreeDofs())
which is a diagonal matrix with diagonal entries 1/0 corresponding to the BitArray.
r2.data = proj * r
Conjugate gradients computes the error via
sqrt ( InnerProductd (r, pre *r) )
where pre is a preconditioner. The range of the preconditioner is exactly the sub-space corresponding to non-Dirichlet dofs.
Best,
Joachim
you gave the answer yourself: The residual of the linear equation should be 0 only for the non-Dirichlet rows.
You can define a projector
proj = Projector(fes.FreeDofs())
which is a diagonal matrix with diagonal entries 1/0 corresponding to the BitArray.
r2.data = proj * r
Conjugate gradients computes the error via
sqrt ( InnerProductd (r, pre *r) )
where pre is a preconditioner. The range of the preconditioner is exactly the sub-space corresponding to non-Dirichlet dofs.
Best,
Joachim
The following user(s) said Thank You: NilsHM
5 years 7 months ago #1550
by NilsHM
Replied by NilsHM on topic Calculating residual in finite element space with dirichlet boundary condition
Hi Joachim.
Thank You for the quick help. I did not know you could create a projector like that.
I solved my problem by calculating the residual like this:
fes = HCurl(mesh, order = 3, nograds = True, complex = True, definedon = "iron", dirichlet = "gamma_iron")
a = BilinearForm(fes, symmetric = True)
a += SymbolicBFI(...)
a.Assemble()
a_inv = a.mat.Inverse(freedofs = fes.FreeDofs())
f = LinearForm(fes)
f += SymbolicLFI(..., definedon = mesh.Materials("iron"))
f.Assemble()
sol = GridFunction(fes)
sol.vec.data = a.inv*f.vec
res = sol.vec.CreateVector()
res.data = a.mat*sol.vec - f.vec
res2 = sol.vec.CreateVector()
proj = Projector(fes.FreeDofs(), True)
res2.data = proj*res
res_value = numpy.absolute(sqrt(InnerProduct(res2,res2)))
Best regards,
Nils
Thank You for the quick help. I did not know you could create a projector like that.
I solved my problem by calculating the residual like this:
fes = HCurl(mesh, order = 3, nograds = True, complex = True, definedon = "iron", dirichlet = "gamma_iron")
a = BilinearForm(fes, symmetric = True)
a += SymbolicBFI(...)
a.Assemble()
a_inv = a.mat.Inverse(freedofs = fes.FreeDofs())
f = LinearForm(fes)
f += SymbolicLFI(..., definedon = mesh.Materials("iron"))
f.Assemble()
sol = GridFunction(fes)
sol.vec.data = a.inv*f.vec
res = sol.vec.CreateVector()
res.data = a.mat*sol.vec - f.vec
res2 = sol.vec.CreateVector()
proj = Projector(fes.FreeDofs(), True)
res2.data = proj*res
res_value = numpy.absolute(sqrt(InnerProduct(res2,res2)))
Best regards,
Nils
Time to create page: 0.096 seconds