-
Notifications
You must be signed in to change notification settings - Fork 83
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
Make interpolator work for vector valued base functions #1156
base: master
Are you sure you want to change the base?
Conversation
There exists an open issue about this feature, #973. There were some remaining open questions, e.g.,
I didn't yet pursue analysing these questions in detail because the workaround to the issue was very simple: project the interesting component onto a scalar finite element basis and interpolate as follows: Vh_scalar = Vh.with_element(ElementDG(ElementTriP1()))
ajx = Vh_scalar.project(Vh.interpolate(aj)[0])
valx = Vh_scalar.interpolator(ajx)
# ... use valx to interpolate the x-component Note that I don't oppose solving this issue as presented by this PR, I just think those two questions above should be taken into account by the implementation, and omitting the matrix valued interpolator is also fine if there is a clear path towards how to implement it in future. I would also like to see some pros/cons type of analysis on possible alternative ideas concerning the output shape. Comments on this PR:
|
To be concrete, for three points and multiple components (vector like or matrix like) point 1, first component -->
I think it would be necessary to define is a parameter/function in element or basis indicating the structure of the base function, e.g. In principle I did that by
but maby that could be done routinely when calling e.g. fem.ElementTriN1() or fem.Basis(mesh,e) Your are mentioning Basis._detect_tensor_order. Is there already such a parameter? I did not found it, to be honest. BTW. What happens by doing ElementVector(ElementTriP1()) ? |
|
I introduced This parameter is used to compute the number of components (1, 2, 4 for the examples above) and the matrix is assembled as described above. on output of I also checked if ElementVector(ElementTriN1()) works |
Sorry for the delay in responding - I was busy with teaching tasks this autumn. I think it makes sense. Are you still willing to push this forward and proceed with tests and such? I can also continue from your prototype at some point if you don't have the time. |
With the interpolator function the value of an expansion at multiple x can be calculated according to
However for vector valued base functions ( e.g. e=fem.ElementTriN1() ) this does not work
The error is due to the fact that the rows and cols are not correctly assembled.
This pull request fixes the error. In cell_basis.py the probes() function returns a matrix. The rows refer to the different points in the array xx, the cols refer to the dof-values.
In the fixed version the rows are simply extended by the additional components, so the first k (k number of points the sum has to calculate) rows belong to the first component, the next k rows to the second component and so on.
The following code is an example for Nedelec, first order in a triangle.
I was not able to find a parameter that directly gives the number of components of a element or base, so it is determined in a first step by calculating the first basefunction at the origin of the local coordinate system and counting the number of values. Then the matrix is restructured using the phis and the number of components as described above.
The values returned after the matrix vector multiplication are therefore ordered in the same way. Currently they are not yet reshaped.
remarks
If there is a parameter like number_of_components I did not see
comp = len(self.elem.lbasis(self.elem.dim*[0],0)[0])
could be replaced
In the example above the returned array val is reshaped externally to separate the components. This could be done also in the interpolator function. A comp parameter would be helpful here too.