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

ADInterfaceKernel #15397

Merged
merged 10 commits into from
Jun 12, 2020
Merged

ADInterfaceKernel #15397

merged 10 commits into from
Jun 12, 2020

Conversation

lindsayad
Copy link
Member

Support for both standard and vector variables.

This PR also contains a lot of const additions to Coupleable/NeighborCoupleable/MooseVariable* APIs since they should be such.

Closes #15307

@moosebuild
Copy link
Contributor

Job Partial Modules Parallel Test (In progress) on e1789d9 : invalidated by @lindsayad

huh?

@moosebuild
Copy link
Contributor

moosebuild commented Jun 4, 2020

Job Documentation on f7aad99 wanted to post the following:

View the site here

This comment will be updated on new commits.


std::size_t ad_offset;
if (type == Moose::ElementElement || type == Moose::NeighborElement)
ad_offset = jvar * _sys.getMaxVarNDofsPerElem();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cticenhour I believe the key change was here. I think you mostly copy-pasted this from ADDGKernel maybe where this isn't a concern...but previously I believe you had _var.number(). So we were getting the jacobian wrong when computing the Jacobians with respect to the neighbor residual because we were always using the "elemental" variable. So the change was to go from _var.number() -> jvar.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah you're right - I originally had ivar here. I actually didn't look at ADDGKernel, but a combo of ADIntegratedBC and ADKernel and then built something up from what I saw there and my understanding of InterfaceKernel. My core misunderstanding was the concept of an ad_offset in the first place, it seems. Could you explain that a bit more?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to remind myself about this sometimes because I forget...

Let's just think about continuous finite elements for a second. We use a variable major numbering scheme, such that each variables indices are in a contiguous block. Let's imagine we have two variables, u and v, and we're on a QUAD4. The AD indices will be ordered like this:

u0, u1, u2, u3, v0, v1, v2, v3

_sys.getMaxVarNDofsPerElem should return for a QUAD4: 4. For a QUAD9, 9. HEX27, 27. Etc. For CFEM the offset will be simply that element number times the var number. So for u on a QUAD4: 4 * 0 = 0. For v: 4 * 1. So u indices start at index 0, v indices start at index 4.

With DFEM or interface kernels it's a little more complicated. We essentially already have an indices block that is num_vars * num_dofs_per_elem long, so in our two var, QUAD4 example: 4 * 2 = 8. So what we do is that if we are on a neighbor element, we do an additional offset by num_vars * num_dofs_per_elem. So now our derivative indices are ordered like this:

u0, u1, u2, u3, v0, v1, v2, v3, u0_neighbor, u1_neighbor, u2_neighbor, u3_neighbor, v0_neighbor, v1_neighbor, v2_neighbor, v3_neighbor

Does that make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clear - thanks! :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just think about continuous finite elements for a second. We use a variable major numbering scheme, such that each variables indices are in a contiguous block. Let's imagine we have two variables, u and v, and we're on a QUAD4. The AD indices will be ordered like this:

u0, u1, u2, u3, v0, v1, v2, v3

_sys.getMaxVarNDofsPerElem should return for a QUAD4: 4. For a QUAD9, 9. HEX27, 27. Etc. For CFEM the offset will be simply that element number times the var number. So for u on a QUAD4: 4 * 0 = 0. For v: 4 * 1. So u indices start at index 0, v indices start at index 4.

With DFEM or interface kernels it's a little more complicated. We essentially already have an indices block that is num_vars * num_dofs_per_elem long, so in our two var, QUAD4 example: 4 * 2 = 8. So what we do is that if we are on a neighbor element, we do an additional offset by num_vars * num_dofs_per_elem. So now our derivative indices are ordered like this:

u0, u1, u2, u3, v0, v1, v2, v3, u0_neighbor, u1_neighbor, u2_neighbor, u3_neighbor, v0_neighbor, v1_neighbor, v2_neighbor, v3_neighbor

I would really appreciate it if you could add these sentences as comments into code.

@moosebuild
Copy link
Contributor

Job Mac Test on 9ef963b : invalidated by @cticenhour

Unrelated test crash

@lindsayad
Copy link
Member Author

@cticenhour feel free to review this although we'll need someone else to give approval since you have an important commit here

@lindsayad lindsayad requested a review from fdkong June 4, 2020 20:24
@lindsayad
Copy link
Member Author

@rwcarlsen this has your adCoupledNeighborValue API


/// The ad version of JxW
const MooseArray<ADReal> & _ad_JxW;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting.


std::size_t ad_offset;
if (type == Moose::ElementElement || type == Moose::NeighborElement)
ad_offset = jvar * _sys.getMaxVarNDofsPerElem();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just think about continuous finite elements for a second. We use a variable major numbering scheme, such that each variables indices are in a contiguous block. Let's imagine we have two variables, u and v, and we're on a QUAD4. The AD indices will be ordered like this:

u0, u1, u2, u3, v0, v1, v2, v3

_sys.getMaxVarNDofsPerElem should return for a QUAD4: 4. For a QUAD9, 9. HEX27, 27. Etc. For CFEM the offset will be simply that element number times the var number. So for u on a QUAD4: 4 * 0 = 0. For v: 4 * 1. So u indices start at index 0, v indices start at index 4.

With DFEM or interface kernels it's a little more complicated. We essentially already have an indices block that is num_vars * num_dofs_per_elem long, so in our two var, QUAD4 example: 4 * 2 = 8. So what we do is that if we are on a neighbor element, we do an additional offset by num_vars * num_dofs_per_elem. So now our derivative indices are ordered like this:

u0, u1, u2, u3, v0, v1, v2, v3, u0_neighbor, u1_neighbor, u2_neighbor, u3_neighbor, v0_neighbor, v1_neighbor, v2_neighbor, v3_neighbor

I would really appreciate it if you could add these sentences as comments into code.

ad_offset = jvar * _sys.getMaxVarNDofsPerElem();
else
ad_offset = jvar * _sys.getMaxVarNDofsPerElem() +
(_sys.system().n_vars() * _sys.getMaxVarNDofsPerElem());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ad_offset has to match what you are doing seed? If so, it may be a good idea to create an API somewhere, so we can retrieve the same value

@fdkong
Copy link
Contributor

fdkong commented Jun 9, 2020

Just minor things

@rwcarlsen
Copy link
Contributor

rwcarlsen commented Jun 9, 2020

I agree with @fdkong - that discussion about indexing for derivatives would be very helpful to have as comments in the code. Especially looking forward to FV reconstruction stuff I will probably end up working on eventually - where we will have to add in derivs. w.r.t. even more than just two elements.

@lindsayad
Copy link
Member Author

@fdkong @rwcarlsen please see 258ecaf

Copy link
Contributor

@rwcarlsen rwcarlsen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The adOffset func and doc comments are fantastic - a huge improvement. It looks like you missed a couple of replacements though - in FV flux kernels/bcs.

@lindsayad
Copy link
Member Author

Ok hopefully I got the framework holdovers in the latest commit. @joshuahansel please checkout the API I introduced in 0b8daa6 for computing the map you want

rwcarlsen
rwcarlsen previously approved these changes Jun 11, 2020
@lindsayad lindsayad marked this pull request as draft June 11, 2020 20:52
@lindsayad lindsayad force-pushed the ad-interface-kernels-15307 branch 2 times, most recently from 65f9efc to 7727869 Compare June 11, 2020 22:24
@lindsayad lindsayad marked this pull request as ready for review June 11, 2020 22:24
@joshuahansel
Copy link
Contributor

@lindsayad Thanks, might take me a day or so to test the API, but it looks like it'll do the trick.


/**
* A material that couples a material property
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a very useful doc comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to something a bit more meaningful

Comment on lines 19 to 27
std::unordered_map<dof_id_type, Real>
globalDofIndexToDerivative(const ADReal & ad_real,
const SystemBase & sys,
const Elem * elem,
const ElementType elem_type /*=ElementType::Element*/)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we anticipate this being used for in the future? Did you have anything in mind?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #15450

Comment on lines +39 to +65
dof_map.dof_indices(elem, global_indices, var_num);

// determine the AD offset for the current var
const auto ad_offset = adOffset(var_num, max_dofs_per_elem, elem_type, num_vars);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if elem isn't currently assembly's current elem or neighbor? Then we just get nonsense right? Maybe we should guard against that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or at least we need to know which dof indices were used when the dualnumbers that contributed to ad_real were seeded/initialized.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well just remove elem from the argument list then and just take it from assembly

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and removed elem from the argument list, and am just using the assembly elem APIs to get the current elements

This is actually only really a test in debug mode
rwcarlsen
rwcarlsen previously approved these changes Jun 11, 2020
Copy link
Contributor

@rwcarlsen rwcarlsen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I anticipate more work being done here eventually. I expect as Josh starts using this, and as we eventually start trying to to fv gradient reconstruction, more ideas will pop out about how to further improve this situation. Wouldn't it be nice if we just stored the global dof id's straight in the dual numbers?

@lindsayad
Copy link
Member Author

lindsayad commented Jun 11, 2020

I anticipate more work being done here eventually. I expect as Josh starts using this, and as we eventually start trying to to fv gradient reconstruction, more ideas will pop out about how to further improve this situation. Wouldn't it be nice if we just stored the global dof id's straight in the dual numbers?

I definitely agree with you. We could do this right now with the sparse container...

@fdkong fdkong merged commit 8ebd8b0 into idaholab:next Jun 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add AD template for InterfaceKernels
6 participants