Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finding edge dofs based on values in integration points #421

Open
ettaka opened this issue Aug 28, 2023 · 11 comments
Open

Finding edge dofs based on values in integration points #421

ettaka opened this issue Aug 28, 2023 · 11 comments

Comments

@ettaka
Copy link
Contributor

ettaka commented Aug 28, 2023

Assuming we know edge element dofs we can calculate values at integration points:
$a_\mathrm{ip}=R_\mathrm{w} a_\mathrm{dofs}$

or

$a_\mathrm{ip}^T=a_\mathrm{dofs} R_\mathrm{w}^T$

Explicitly in code:
a_ip(1:3) = MATMUL(a_dofs(nd-np), wbasis(nd-np, 1:3))

Assuming we know values at integration points, we need to do the reverse, solve the linear system:
$a_\mathrm{dofs} = R_\mathrm{w}^{-1} a_\mathrm{ip}$

However, $R_\mathrm{w}$ is not a square matrix, it is

$3\times (n_{d}-n_{p})$, ($3\times6$ in first Whitney form).

This system is under determined. Though, we can assemble all the integration points to the same matrix, then we have a matrix size

$3n_\mathrm{ip}\times (n_\mathrm{d}-n_\mathrm{p})$, ($12\times6$ in the first Whitney form)

So to solve this, one can do

$a_\mathrm{dofs} = (R^T R_\mathrm{w})^{-1} R^T a_\mathrm{ip}$

We thus need a subroutine SUBROUTINE InvWbasis(Wbasis, a_ip) that can generate $(R^T R_\mathrm{w})^{-1} R^T$ based on curl basis and values of variable at integration points.

@ettaka
Copy link
Contributor Author

ettaka commented Aug 28, 2023

@mmalinen what do you think about this?

@mmalinen
Copy link
Contributor

I believe creating directly a square (N x N)-matrix, with N the count of edge element DOFs, would be the most natural approach. If one proceeds in a point-wise and coordinate-wise manner to obtain new rows, one could just stop adding new equations when N constraints have been obtained. The pattern of points where the matching has been done may then look unsymmetric, but I believe it shouldn't be a major problem ?

@ettaka
Copy link
Contributor Author

ettaka commented Aug 28, 2023

Maybe I made a mistake earlier when creating NxN, but I had trouble finding the inverse.
I made this in a new branch:
Edge dofs linear system built here at the moment:
https://github.com/ElmerCSC/elmerfem/blob/sr_decomposition/fem/src/modules/MagnetoDynamics/WhitneyAVSolver.F90#L1927

Test case:
https://github.com/ElmerCSC/elmerfem/blob/sr_decomposition/fem/tests/mgdyn_sr_decomp/sif/box.sif

I get garbage out at the moment, If you see an obvious mistake, let me know.

Thanks!

@mmalinen
Copy link
Contributor

To obtain a local interpolant having a guaranteed error estimate, I'd use a different approach and start by writing an additional integration loop in order to integrate the local mass matrix and evaluate suitable linear forms for the local interpolation. That is, I'd solve

$$ (W_i,\sum\limits_{j=1}^N W_j) d_j = (W_i,A) $$

where $W_i$ are the edge basis functions and $A$ is the function to approximate. After this computation of the degrees of freedom $d_k$, one could evaluate the value of the approximation within another loop over integration points. The evaluation could of course be done for any point in the element.

@raback
Copy link
Contributor

raback commented Aug 29, 2023

This may be a little similar as
InterpolateMeshToMesh.F90 -> Ip2DgFieldInElement()
The purpose of which is to allow on-the-fly computation of dg fields for postprocessing.

ettaka added a commit that referenced this issue Aug 30, 2023
@ettaka
Copy link
Contributor Author

ettaka commented Aug 30, 2023

Thanks for the info @mmalinen @raback !

Does this look about right to you https://github.com/ElmerCSC/elmerfem/blob/sr_decomposition/fem/src/modules/MagnetoDynamics/WhitneyAVSolver.F90#L1928

I am still getting garbage btw.

@ettaka
Copy link
Contributor Author

ettaka commented Sep 1, 2023

I am trying to debug the field by directly outputting the field.

I get the variable

BVar => VariableGet(Solver % Mesh % Variables, &

But when I try to set a vector [1,2,3] everywhere (as a test)

BVar % Values( BVar % DOFs*(ind(j)-1)+k) = k

I don't get exactly correct result in Paraview (see the small blue dots, it should be completely red)
image

Please advice. Thanks!

@ettaka
Copy link
Contributor Author

ettaka commented Sep 4, 2023

Coming back to this. The previous seems to be due to face elements showing at the same time as body elements. But if we filter only the body elements, the field seems fine for debugging purposes.

I am now showing here the vector potential (z component, as all others are 0) from which we calculate the magnetic flux density:
image
So this should be equivalent to a homogeneic magnetic flux density in y-direction (and other components 0)

This is the resulting magnetic flux density:
x direction
image
y direction
image
z direction
image

This is clearly not what we expect.

So it seems there is some issue with the algorithm to compute the magnetic flux density.

Does the block at


look correct to you @raback?

@mmalinen
Copy link
Contributor

mmalinen commented Sep 4, 2023

It seems that the DOFs (the content of the array Asloc after the first BLOCK) are computed correctly. I verified this with some simple source fields which should be contained in the FE space so that an accurate FE representation should be possible. These tests included the case of constant fields and the field $A = (z,0,-x)$, which produces constant curl along the y-axis.

However, the loop

DO k = 1,AsVar % DOFs
AsVar % Values( AsVar % DOFs*(ind(t)-1)+k) = SRDAatIp(k)
END DO

makes valgrind to say "Invalid read of size 4". I commented this out, since I checked only the first BLOCK which doesn't need AsVar % Values after writing it.

@mmalinen
Copy link
Contributor

mmalinen commented Sep 5, 2023

It seems that your code at the moment (4c822dc) supposes the variables AsVar and BsVar to have their value arrays suitable for representing the variable at integration points. However, they are defined to be elementwise variables and therefore picking indices as Ind(t) is not right when you write the arrays AsVar % Values and BsVar % Values.

@raback
Copy link
Contributor

raback commented Dec 1, 2023

I was going through old issues and looked into this. My recommendation would be to use the Elemental routinies here since the initial field may be more accurate directly on IP points. Does not really make sense to go through the nodal points. Also the resulting fields may be saved directly as IP fields and let the code take care of the interpolation.

Unfortunately I do not be able to get the projection to work any better than you. For my eye it should work. The initial vector potential looks good as an IP field. But it fitted version and the resulting rotor does not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants