-
Notifications
You must be signed in to change notification settings - Fork 0
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
added test to gradient calculation logic described in #149 #150
Conversation
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 like it, but there is more to do
|
||
|
||
|
||
// Short test to check MoleculeHandler::get_neighbor_lists() function. |
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.
is description correct?
auto my_pair_2 = GridTools::find_active_cell_around_point(MappingQ1<dim>(), | ||
dof_handler, | ||
p2); | ||
std::vector<Point<dim>>points = {my_pair_1.second, my_pair_2.second}; |
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.
space after >
. p.s. did you run indentation on this?
ExcInternalError()); | ||
|
||
const unsigned int dofs_per_cell = fe.dofs_per_cell; | ||
LinearAlgebraDealII::Vector local_gradient_I, local_gradient_II; |
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 should just be dealii::Vector<double>
, it's not a parallel vector.
std::vector<dealii::types::global_dof_index> | ||
local_dof_indices(dofs_per_cell); | ||
|
||
FEValues<dim>fe_values(mapping, fe, Quadrature<dim>(points), update_values); |
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.
you need to have separate FEValues
for each cell. Currently you create a quadrature which has positions of both points inside each cell.
Also add space after >
.
|
||
for (unsigned int k = 0; k < dofs_per_cell; ++k) | ||
{ | ||
local_gradient_I [k] += fe_values.shape_value(k, 0); |
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.
you don't do the correct gradient, it should be
n^{ab}*N_i(X^a)
and you need extractors.
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 doing just one dof at a mesh node first.
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 doing just one dof
but that's not what i mean and you don't do one dof. You calculate force due to this pair on all dofs currently (for k=0; k < dofs_per_cell; ++k)
).
What I am saying is that as far as I can tell this line is wrong.
constraints.distribute_local_to_global(local_gradient_II, | ||
local_dof_indices, | ||
gradient); | ||
|
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.
at this point we have answer from our favourite approach, now we need to compare it to what we are doing at the moment. Otherwise we don't know if it actually works. The fact that the test compiles and gives you some numbers does not mean yet that it is working 😄
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 compared the values by manual calculation for each dof.
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.
but you did not do scalar product n^{ab} * N_i(X^a)
. i wonder how/why does it work in its current 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 was just comparing the difference of the shape 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 you do it correctly, you should probably get the same result as for your cases below n^{ab}={1,0,0}
.
p2); | ||
std::vector<Point<dim>>points = {my_pair_1.second, my_pair_2.second}; | ||
|
||
run(points); |
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.
may i suggest to rework it into:
run (const Point<dim> &X1, auto &my_pair_1, const Point<dim> &X2, auto &my_pair_2)
and correct internals accordingly.
Then you should get the same result from your test regardless of the order of points, i.e.
Point<3> p1(0.8,0.8,0.8),p2(1.8,0.8,0.8);
problem.check(p1,p2);
vs
Point<3> p2(0.8,0.8,0.8),p1(1.8,0.8,0.8);
problem.check(p1,p2);
I will work on the test again. It appears that I only compared manually the first component. Regarding the older method we didn't finish it to compare to. Edit: Should I finish the old method and then compare the both? |
May I suggest you use Maxima to produce MWE of the standard-QC (blessed output) and choose only 2 points which, however, have Xa-Xb not parallel to any of the axis? Then you only need to test
that's ok if you have MWE in Maxima or alike. |
I suggest to do 2D as it's easier to test properly in Maxima and also easier to visualize you can do vectors in Maxima easily:
depending on how you implement this, you could introduce DoFs for each element
you can get actual DoFs on the mesh in deal.II from extra output, i.e. https://github.com/dealii/dealii/blob/master/tests/dofs/dof_tools_extract_dofs_with_support_contained_within_01.cc#L90-L113 Here are some examples of how to do for loops in maxima:
Of course, the implementation should be along the standard QC approach where you can evaluate each shape function on any element. p.s. @vishalkenchan i edited this post to hopefully give enough Maxima syntax to implement the test. |
Thanks! I will have a look at it tomorrow. |
thinking about this MWE, i would probably proceeded by defining global shape functions for two elements as scalar-valued functions (so that you can evaluate it on any point Then, since the vector-valued shape functions in our case are primitive (i.e. At the end of the day you would have in Maxima |
here's how you can define such shape functions and plot them to make sure it's all good:
|
Thanks for the code snippets. This makes a sound way to write test. |
If I am using just |
Not really! In dealii u need to use vector-valued function as we use normally. In maxima u will have 2x6 values for forces, in deal.ii the vector will be of size 12. You can easily relate the two if u plot DoFs with the mesh (see above). |
fb3bbdc
to
8ae9fd5
Compare
for (unsigned int i = 0; i < dof_handler.n_dofs(); i+=dim) | ||
{ | ||
for (int d = 0; d < dim; ++d) | ||
std::cout << n[d]*gradient[i] << "\t"; |
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.
you use vector-valued functions, why don't you just output the gradient itself? I was expecting that you use actual positions of the two points in your run()
.
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.
see below on how i would rework 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.
I was trying get to the difference of shape function values and comparing before multiplying with the unit normal. But I could do this as well.
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 am just in favour to do it as close as the actual implementation so that you could just copy-paste this code and add partial_differentive_of_vector_wrt_dofs_02.cc
which does exactly the same but using our QC class (with whatever potential and unit cluster weights).
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.
Sure. I will change it.
//problem.write_dofs_and_support_points_info(); | ||
{ | ||
Point<2> p1(0.23, 0.37), p2(1.73, 0.43); | ||
problem.check(p1,p2); |
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.
please check
problem.check(p2,p1);
dof_handler, | ||
p2); | ||
|
||
run (my_pair_1.second, my_pair_2.second); |
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.
in order not to assume which point is in which cell, i would provide here my_pair_1, my_pair_2, p1, p2
|
||
for (unsigned int k = 0; k < dofs_per_cell; ++k) | ||
{ | ||
local_gradient_I [k] = fe_value_a.shape_value(k, 0); |
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.
Please use extractors and scalar products. Otherwise you may not be doing what you think you are doing.
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.
p.s. i don't think this would change the result as shape_value
returns
If the shape function is vector-valued, then this returns the only non- zero component
for primitive functions. So i guess it's fine to stick with it, but then at least get which component this corresponds to implement scalar product.
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's also how we should implement it in the code in order to avoid multiplications with zeroes.
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.
to get what is the only non-zero component for a given shape functions, you would need fe.system_to_component_index(k).first
, see dealii/dealii#3646 (comment)
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 in our case we have primitive shape functions, could I just do what we are doing in qc.cc
:
for (unsigned int k = 0; k < dofs_per_cell; ++k)
{
local_gradient_I [k] = fe_value_a[u_fe].value(k, 0);
local_gradient_II [k] = -fe_value_b[u_fe].value(k, 0);
}
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.
With scalar product.
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.
no, you misunderstand my point! You need to do
for (unsigned int k = 0; k < dofs_per_cell; ++k)
{
const unsigned int comp = fe.system_to_component_index(k).first;
local_gradient_I [k] = nab[comp] * fe_value_a.shape_value(k, 0);
}
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 the actual (TODO) implementation in QC class. Otherwise we will do 2 out of 3 multiplications with zeroes (in 3D case).
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.
nice, minor changes to make it closer to the actual (TODO) implementation.
8ae9fd5
to
77f5824
Compare
77f5824
to
e6c95c0
Compare
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.
nice, i guess we are now fully convinced that this approach works! 😄
👍 |
@vishalkenchan i would now add another test (together with MWE in Maxima) and use this logic in QC to calculate forces from two cluster atoms (say spring potential) for the same mesh. The MWE in Maxima is the same up to |
Are you going to touch |
I meant that it's the next logical step for u to do ;-) |
@vishalkenchan i will look at doing forces in QC, but not necessarily test it ;-) |
Edit: I will clean up the QC class with some updated documentation, with several test cases in the subsequent PRs.
in reference to #149 (comment)