-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Array kernel #13314
Array kernel #13314
Conversation
Hate conflicts... |
35a37b6
to
f211bee
Compare
This could be easier than i thought. I do not need to use array type in local residual or jacobian but can instead resizing the dense vector or matrix differently. Just need to managing the index carefully. |
Job Documentation on 8d2e314 wanted to post the following: View the site here This comment will be updated on new commits. |
(Going to write down something here for the design, that should be useful for reviewing.) An array variable is define as a set of standard field variables with the same finite element family and order. Each standard variable of an array variable is referred as a component of the array variable. An array kernel is a MOOSE kernel operating on an array variable and assemble the residuals and Jacobians for all the components of the array variable. The purpose of having array kernel is to reduce the number of kernels when the number of components of an array variable is large (potentially hundreds or thousands) and to avoid duplicated operations with lots of standard kernels. The array kernel can be useful for radiation transport where an extra independent direction variable can result into large number of standard variables. Similarly as array kernel, we will have array initial conditions, array boundary conditions, array DG kernels, array interface kernels, array constraints, etc. The design:
The following map is useful for understanding the template:
The three rows correspond to standard, vector and array variables. The final form of an array kernel is quite simple. Using
where Of course, if we have different diffusion coefficients, we will have something like
Correspondingly the
or
or
It is noted that only the diagonal entries of the diffusion coefficients are used in the fully-coupled (3rd) case because
The retuned value is in type of an Eigen matrix with number of rows and columns equal to the number of components. Future work:
|
I think this is ready for review. Tag @friedmud @lindsayad and @permcody . I am working on more array kernels, BCs, tests, but they should not affect the review. |
Still a fair number of test problems, have you looked at all the build boxes yet? Bighorn for instance is failing nearly every test with the same error. |
I looked the error messages and am quite certain they can be easily fixed. For example, Bighorn is probably doing something similar like chemical reaction module deriving |
Rattlesnake & MAMMOTH should have been fixed. |
This is going to have merge conflicts with #13056 because I've refactored |
I am ok to resolve the conflict. Should be fairly simple although could look intimidating. |
I will need |
I have not add interface functions in |
I think now I have all the functionalities in my mind in this PR. I am still missing documentations. The tests under |
The major pain on resolving the conflict is in variable and assembly, but looks may not be too bad... |
2a41873
to
223af90
Compare
…nterface kernels or constraints
This is the largest merge conflict I ever resolved, partly due to the bad arrangement of commits (it is very hard to keep a clean history of the commits for a large PR)... I am sure there are rough corners in this PR, but I think it is ready for review. The documentation failure is due to lack of SQA in some existing tests which I touched the |
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 have some questions, but overall I think this looks relatively unobtrusive for adding a neat new functionality, and in general it's well documented.
@@ -503,7 +556,36 @@ class MooseVariableData | |||
void fetchADDoFValues(); | |||
void zeroSizeDofValues(); | |||
|
|||
private: | |||
void getArrayDoFValues(const NumericVector<Number> & sol, |
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.
This method is long. I'd like to see it moved to the .C file
void | ||
MooseVariableFE<OutputType>::addSolution(const DenseVector<Number> & v) const | ||
{ | ||
_element_data->addSolution(_sys.solution(), v); |
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 actually don't know how this compiles...This method is marked const
so _sys
should be const
. That means it would call the const getter for solution
, which returns a const reference to the NumericVector
. And then we're trying to bind that const reference to a non-const reference...yea I don't know how this compiles!
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.
Indeed. Let me search a little to see why.
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.
Maybe the reference behaves like pointer? Although it is const, it just indicating the reference is not changed but not the content of the reference?
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.
Found an answer: The constness of execute() only affects the this pointer of the class. It makes the type of this a const T instead of just T*. This is not a 'deep' const though - it only means the members themselves cannot be changed, but anything they point to or reference still can.* at https://stackoverflow.com/questions/2523516/why-can-i-call-a-non-const-member-function-pointer-from-a-const-method. Not sure it is the standard (although probably).
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.
Yes, I'm aware of that, but what is the difference between our use case, and the program below, which emits the compiler error that I expect? (constness.cpp:25:62: error: binding value of type 'const int' to reference to type 'int' drops 'const' qualifier
)
#include <memory>
class SystemBase
{
public:
SystemBase() : _solution(5) {}
const int & solution() const { return _solution; }
private:
int _solution;
};
class MooseVariableData
{
public:
void addSolution(int & solution, int y) const { solution += y; }
};
class MooseVariableFE
{
public:
MooseVariableFE() { _element_data = std::make_unique<MooseVariableData>(); }
void addSolution(int y) const { _element_data->addSolution(_sys.solution(), y); }
private:
std::unique_ptr<MooseVariableData> _element_data;
SystemBase _sys;
};
int
main()
{
}
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.
Sorry, yea just like the post said; the program below doesn't compile, but if we change to the reference then the program does compile, and the non-const solution getter is called. That's sad as far as ensuring const-correctness goes 😢
#include <memory>
#include <iostream>
class SystemBase
{
public:
SystemBase() : _solution(5) {}
SystemBase(const SystemBase & copy) : _solution(copy._solution) {}
const int & solution() const
{
std::cout << "Const version\n";
return _solution;
}
int & solution()
{
std::cout << "Non-const version\n";
return _solution;
}
private:
int _solution;
};
class MooseVariableData
{
public:
void addSolution(int & solution, int y) const { solution += y; }
};
class MooseVariableFE
{
public:
MooseVariableFE(SystemBase & sys) : _sys(sys)
{
_element_data = std::make_unique<MooseVariableData>();
}
void addSolution(int y) const { _element_data->addSolution(_sys.solution(), y); }
private:
std::unique_ptr<MooseVariableData> _element_data;
// SystemBase & _sys;
SystemBase _sys;
};
int
main()
{
SystemBase sys;
MooseVariableFE var(sys);
var.addSolution(7);
}
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.
Do you want me to remove the const
deco for this method?
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.
Yes, since it is ultimately modifying a data member (through a reference)
@@ -654,11 +655,326 @@ MooseVariableData<OutputType>::computeValues() | |||
computeAD(num_dofs, nqp); | |||
} | |||
|
|||
template <> | |||
void | |||
MooseVariableData<RealArrayValue>::computeValues() |
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.
Sigh...so much code duplication here, but there's enough eigen specific logic that I don't have a better suggestion. If there were just a few different lines, I would suggest adding some shim methods, but there's too many.
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 thought of creating a derived Eigen class for ourselves and implement few more methods to avoid this duplication. But not sure if it is better or not.
template <typename OutputType> | ||
void | ||
MooseVariableData<OutputType>::setNodalValue(OutputType value, unsigned int idx /* = 0*/) | ||
MooseVariableData<OutputType>::setNodalValue(const OutputType & value, unsigned int idx) |
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.
👍
auto n = _dof_indices.size(); | ||
libmesh_assert(n); | ||
|
||
/* Idea of using Eigen::map from Derek Gaston (Yaqi: we can reevaluate this later) */ |
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.
So you may use these lines of code in the future?
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.
Might although I think we may not have it in a short term. @friedmud mentioned some multi-threading issue of this. So I am ok to remove this comment completely.
framework/include/base/Assembly.h
Outdated
@@ -1159,26 +1359,51 @@ class Assembly | |||
|
|||
void computeCurrentNeighborVolume(); | |||
|
|||
/// Appling scaling, constraints to the local residual block and populate the full DoF indices |
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.
Our convention is to use:
/**
*
*/
for methods and ///
for data.
The three rows correspond to standard, vector and array variables. | ||
OutputType is the data type used for templating. | ||
RealArrayValue is a typedef in [MooseTypes.h] as *Eigen::Matrix<Real, Eigen::Dynamic, 1>*. | ||
OutputShape is for the type of shape functions and OutputData is the type of basis function expansion coefficients that are stored in the solution vector. |
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.
One solution vector only holds one type (e.g. Real
), so I'm a little unclear on what the last part of this sentence means. Can you explain a little more?
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.
Oh, this should be the that are stored in the moose array variable, which are grabbed from the solution vector.
@@ -0,0 +1,89 @@ | |||
# ArrayMooseVariable |
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 appreciate the strong documentation!
Future work: | ||
|
||
- To profile the code with large number of variables to find the hot spots and fix them if there are any. | ||
- To change the current dof ordering for elemental variables so that we can avoid bunch of if statements with `isNodal()` in `MooseVariableFE.C`, (refer to [libMesh Issue 2114](https://github.com/libMesh/libmesh/issues/2114). |
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.
That would be fantastic. Can you open a ticket for this after this goes in?
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.
Will do.
else if (_dc_type == 1) | ||
_d_array = &getMaterialProperty<RealArrayValue>("diffusion_coefficient"); | ||
else if (_dc_type == 2) | ||
_d_2d_array = &getMaterialProperty<RealArray>("diffusion_coefficient"); |
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 looked at these typedefs in MooseTypes
and it's not immediately clear to me the motivation behind their names. I look at RealArray
and presume that it's an array of Reals
. Is that right? With the enumeration description of full
, I'm guessing that it's not. And what is RealArrayValue
supposed to mean?
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.
RealArrayValue is actually an Eigen vector type, equivalent with VectorXd
, where X
stands for dynamic, d
stands for double. RealArray
is actually an Eigen matrix, MatrixXd
. I have to admit that I came up this name without too much thinking, so I am willing to accept a better name. Or I can change it to RealMatrixValue
, what do you think?
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.
Hmm...we're starting to run out of names that don't clash with existing names. I personally like RealEigenVector
and RealEigenMatrix
. @friedmud likes names; maybe he has a suggestion.
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 do not quite Eigen
in the name because we also used it for eigenvalue. It can cause confusion although we know here Eigen
is the package name. The underlining data structures for vector and matrix in Eigen are the same. I do not have good ideas now for naming these two ;-) I will need the final for changing the code.
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.
Since I do not have better ideas, I will make this change, I like these names of differentiating vector and matrix.
@lindsayad comments are addressed. |
…d idea, codes are added to ensure the entries in the vectors are unique
Job Precheck on 1ba3315 wanted to post the following: Your code requires style changes. A patch was auto generated and copied here
Alternatively, with your repository up to date and in the top level of your repository:
|
@lindsayad do you have any further comments? Looks like our HPC is online. I'd like this to be merged so I can finish fixing apps before I go for a vacation next week. Thanks. |
We aren't going to merge anything until we get next moving along. We
definitely have a huge backup of PRs needing to go in, but with all of the
red boxes I'm not inclined to pile on even more just yet. It very well
could take us a week to get caught up again so I wouldn't worry about it!
…On Thu, May 16, 2019 at 10:27 AM Yaqi ***@***.***> wrote:
@lindsayad <https://github.com/lindsayad> do you have any further
comments? Looks like our HPC is online. I'd like this to be merged so I can
finish fixing apps before I go for a vacation next week. Thanks.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#13314?email_source=notifications&email_token=AAXFOIASSRY5XMNKAGQ5CZLPVWDNHA5CNFSM4HIQUPYKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVSLDLA#issuecomment-493138348>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAXFOIDYJFSGLW3254CV6TTPVWDNHANCNFSM4HIQUPYA>
.
|
I'm not going to approve anything while the documentation target is failing... |
@permcody said that he will take care of it. The problem is that I touched a tests file due to fixing a wrong error message. That tests file contains lots of tests which I don’t know how to write the missing SQA terms. Other than this all doc recipes passed. |
The added newsletter item can be found at https://mooseframework.inl.gov/docs/PRs/13314/site/newsletter/2019_06.html. |
Superseded by #13459 |
This is definitely still working in progress. I push it here to let you have an idea on what I am doing, particularly for @friedmud and @lindsayad .
The design here:
This map is useful for understanding the template:
So far, I have finished variables, coupeable, systems, initial condition. What I have not done is kernels, bcs, etc. but should be finished soon.
I also did not:
isNodal
inMooseVariableFE.C
due to the ordering scheme difference between nodal variables and high order elemental variables.So feel free to take a look. It is not mergeable yet.