-
Notifications
You must be signed in to change notification settings - Fork 7
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
Add generic nodal/modal bilinear form routines #103
base: main
Are you sure you want to change the base?
Add generic nodal/modal bilinear form routines #103
Conversation
Not sure why ruff was failing here. It wasn't failing locally, and I didn't change any of the files the ruff CI test was complaining about. Fixed them anyway, but happy to revert if it seems like a CI bug. The changes in |
That's a new check in ruff 0.8.2: astral-sh/ruff#14611. Thanks for fixing it! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks great! Just a few style quibbles below.
Seems like |
Those seem to be due to an issue with some new numpy typing changes: numpy/numpy#27957. |
modepy/matrices.py
Outdated
@@ -351,6 +354,77 @@ def mass_matrix( | |||
return la.inv(inverse_mass_matrix(basis, nodes)) | |||
|
|||
|
|||
def modal_quad_bilinear_form( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking about the naming of this. I'm not sure "bilinear form" is that great a fit, because the trial functions don't appear. I thought of "projection", but that also misses the mark, because the test functions could be derivatives. In a word, I'm not sure. I can probably be convinced to go along with "bilinear form", but I figured it might be good to at least discuss the naming.
(@alexfikl, if you're reading along, please feel free to chime in too)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not the biggest fan of the name, but I couldn't come up with anything better. modal_quadrature_operator
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this modal_quad_bilinear_form
supposed to be used? I'm guessing the nodal_quad_bilinear_form
is used to define a proper bilinear form somewhere?
EDIT: I mostly meant "proper" in the sense of defining an inner product, but maybe that's not super relevant..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modal_quad_bilinear_form
doesn't have any uses right now other than returning the operator that's transformed into a nodal operator.
nodal_quad_bilinear_form
will be used in a grudge update that evaluates operators using quadrature (inducer/grudge#362 is the staging area for this, although a little outdated at this point). While nodal_quadrature_operator
could be used for everything, nodal_quad_bilinear_form
makes the corresponding grudge code cleaner when there is no overintegration.
TLDR; modal_quad_bilinear_form
's current use is in nodal_quad_bilinear_form
. nodal_quad_bilinear_form
is used to evaluate DG operators in grudge when there is no overintegration. nodal_quadrature_operator
is used when there is overintegration.
Also, the original comment is outdated now since modal_quad_bilinear_form
does use trial functions (as of c063d23).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for explaining! I think I got a better idea of what this is for.. but no better recommendation for a name :\
The only thing that comes to mind is that if modal_quad_bilinear_form
is not actually supposed to be used outside of modepy
at the moment, we can just inline it in nodal_quad_bilinear_form
?
The first go was a confusing amalgamation of two versions of applying an operator to evaluate a bilinear form. They should now be cleanly separated with names that do a better job of describing what's happening. What I mean by "two versions" is:
Hopefully this is more clear. Happy to convert to a draft if we think more work needs to be done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just took a quick look and left some comments 😁
modepy/matrices.py
Outdated
@@ -351,6 +355,117 @@ def mass_matrix( | |||
return la.inv(inverse_mass_matrix(basis, nodes)) | |||
|
|||
|
|||
def modal_quadrature_operator( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_func_integration_matrix
?modal_test_matrix_quad
?
modal_operator = np.empty((len(test_functions), len(quadrature.weights))) | ||
|
||
for i, test_f in enumerate(test_functions): | ||
modal_operator[i] = test_f(quadrature.nodes) * quadrature.weights | ||
|
||
return modal_operator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return np.array([...])
?
return modal_operator | ||
|
||
|
||
def nodal_quad_operator( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have something like this instead?
def modal_to_nodal(basis, nodes, matrix):
vdm = vandermonde(proj_functions, nodes)
return la.solve(
vdm.T, matrix
)
and get rid of the nodal_...
versions?
if len(test_functions) != nodes.shape[1]: | ||
raise ValueError("volume_nodes not unisolvent with proj_functions") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if len(test_functions) != nodes.shape[1]: | |
raise ValueError("volume_nodes not unisolvent with proj_functions") | |
if len(proj_functions) != nodes.shape[1]: | |
raise ValueError("volume_nodes not unisolvent with proj_functions") |
(but this is probably going away anyway)
|
||
return la.solve(vdm.T, modal_operator) @ la.inv(vdm) | ||
|
||
|
||
def modal_quad_mass_matrix( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd vote in favor of deprecating the _mass_matrix
functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're at it, deprecate the *face_mass*
things, too, and (maybe) have a basis-with-node-transform-composer?
Unsubscribing... @-mention or request review once it's ready for a look or needs attention. |
It would be helpful to have a more general version of
nodal_quad_mass_matrix
. My specific use case for this routine is generating operators representing bilinear forms that have derivatives on the test functions but not necessarily on the trial functions. More generally, this can be useful to generate operators representing bilinear forms whose test and trial functions are not the same.Functionality of
nodal_quad_mass_matrix
andmodal_quad_mass_matrix
are updated to use the new, general routines.