-
Notifications
You must be signed in to change notification settings - Fork 0
external mesh deformation base class #9
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
base: landlab-aspect
Are you sure you want to change the base?
external mesh deformation base class #9
Conversation
d7f4b32 to
5f7cb5f
Compare
| - why put when to call set_evaluation_points() with invalidation logic into user code? turn around? | ||
| - user function should be called update() or do_surface_step(dt) or something | ||
| - nodes: derived class should define dim-1 surface points, we translate to 3d points | ||
| - initial topography ASPECT->external or the other way around? compute_initial_deformation_on_boundary() <- std::vector<> initial_topography() |
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.
we need compute_initial_deformation_on_boundary(). we should get the initial deformation from landlab
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.
need to refactor code in base class where we build a vector of initial deformations, so that we query by node index, not by node point.
5134922 to
d1a58cc
Compare
|
@bangerth Thank you. This is now ready for a first review. We will need to switch to 9.6 for the tests to pass, see geodynamics#6638 Additionally, I have not done the refactor for the initial conditions so far, but I think this could be merged without. |
|
@bangerth ping |
5c5ba97 to
79afe3e
Compare
79afe3e to
2023709
Compare
|
@bangerth Ping. The tests now pass. |
bangerth
left a 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.
Here's the PointDataOut class. I'm going to have to go teach, but will be back at this for the rest when back.
| // We have one more data components than dataset_names (the particle id) | ||
| patches[i].data.reinit(n_data_components, 1); | ||
|
|
||
| patches[i].data(0, 0) = i; // id |
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 we eventually want to make this so that in parallel, we don't re-use ids?
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 make sense, but the class has currently no knowledge about the MPI communicator to use.
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, perhaps an issue for the future.
bangerth
left a 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.
Here's the rest. I apologize for taking so long to actually get to this! :-(
| const LinearAlgebra::Vector v_interpolated | ||
| = interpolate_velocities_to_surface_points(external_surface_velocities); | ||
|
|
||
| // TODO: need ghost values of v_interpolated? |
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. We use this vector to evaluate at all boundary DoFs of the current process because this is what DoFTools::extract_boundary_dofs does:
/**
* Extract all degrees of freedom which are at the boundary and belong to
* specified components of the solution. The function returns its results in
* the form of an IndexSet that contains those entries that correspond to
* these selected degrees of freedom, i.e., which are at the boundary and
* belong to one of the selected components.
*
* By specifying the @p boundary_ids variable, you can select which boundary
* indicators the faces have to have on which the degrees of freedom are
* located that shall be extracted. If it is an empty list (the default), then
* all boundary indicators are accepted.
*
* This function is used in step-11 and step-15, for example.
*
* @note If the DoFHandler object is defined on a
* parallel Triangulation object, then the computed index set
* will contain only those degrees of freedom on the boundary that belong to
* the locally relevant set (see **********************************
* @ref GlossLocallyRelevantDof "locally relevant DoFs"), i.e., the function
* only considers faces of locally owned and ghost cells, but not of
* artificial cells.
* [...]
*/
template <int dim, int spacedim>
IndexSet
extract_boundary_dofs(const DoFHandler<dim, spacedim> &dof_handler,
const ComponentMask &component_mask = {},
const std::set<types::boundary_id> &boundary_ids = {});
| // constraint. We later make that consistent across processors to | ||
| // ensure we also know about the locally relevant DoFs' | ||
| // constraints: |
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 may want to adjust this part of the comment. We are already consistent on the locally relevant DoFs. The call to make_consistent() is probably not wrong, but I think also not necessary.
| } | ||
| } | ||
|
|
||
| // TODO: make consistent? |
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.
Your choice :-)
|
Thank you @bangerth. I replied to some of your comments and will address everything else in the next few days. |
ef3ba5f to
bcdab67
Compare
|
Tell me if you want me to take another look! |
bcdab67 to
a7f7720
Compare
|
I am stuck with one problem prompted by your remarks:
I don't think this is true: On each rank we receive data in all evaluation points that are contained within any of our locally owned cells. We then proceed to set each surface DoF of the ASPECT mesh to the value of the closest point and store this in This means:
I don't see an easy way to do this correctly, because it would involve communicating values and distance to evaluation point for each DoF on a processor interface and then picking the best value (probably by the DoF owner followed by a broadcast to the others). Sigh. |
|
That said, I would also be okay to merge what we have here and incrementally improve. The tests are passing... |
Oh yes, I get it now. You're computing this also going for ghost nodes, which I thought was enough to be consistent. But you may be computing the wrong thing. So yes, you need to call the
Hm, good point. And if two processes write constraints into locally active DoFs that are different, then At first I was thinking that you need to make sure that you only ever create constraints for locally owned DoFs. That avoids the conflicts, but you're right that that doesn't mean that these are correct. In particular, you'd end up with a situation where you'd get different results depending on the number of processes. Do you need to split the loop you have into two? Perhaps something like this (I think this is what you are proposing above):
|
Let's see if we can come up with a solution over the next couple of days. If not, we'll just go with what you have for now... |
Yes, this is what I was hinting at. But, as you said, it would involve a custom communication step.
You make an important point. I think this situation is not only theoretical but very likely to happen considering one use case are structured grids that do not line up. I think the only reasonable option is to (somehow) precompute a globally injective mapping from evaluation point index to DoF. The owner of the DoF can play the role of the tie breaker for points with equal distance. With this mapping, each processors loops over their list and writes their values into a global vector. After a call to I would construct the list in the following way:
With this map in place it is as simple as iterating over all evaluation points, looking them up in the map, and setting the values. This sounds like a custom MPI routine where I can not use any linear algebra or other high-level deal.II functionality. Luckily, this is all point to point communication. Any suggestions for simplification? |
|
ping @bangerth |
|
Yes, tough problem. You're right that that sounds like a function best suited to I think that encapsulates the interface you need. The steps you mention seem reasonable to me. Perhaps you need to pass more information in than just the locally owned node points (the locally relevant ones? but then you also have to express ownership). I did think that at one point you have to perform some kind of min-operations on the elements of a vector of distances (or a vector of (distance, rank) tuples) to figure out who has the closest node. (If you store 1/distance, then it just becomes a max operation, and if you need a tie breaker, that involves the |
|
Do you think you can break this problem into smaller chunks that you could independently implement and test? I think that would make it much easier to review and convince ourselves that that's the way to go. |
|
Yeah, sounds good. I think we can implement these things independently of the mesh deformation class (the code in this PR) and unit test it.
I think we should do all of this in this repo even though 2 could go into deal.II eventually. |
FYI @bangerth