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

Indirect access #2099

Open
wants to merge 37 commits into
base: develop
Choose a base branch
from
Open

Indirect access #2099

wants to merge 37 commits into from

Conversation

davidscn
Copy link
Member

@davidscn davidscn commented Oct 11, 2024

Main changes of this PR

Implements a read-consistent and write-conservative indirect access for nearest neighbor and PU-RBF.

#1843

@uekerman I know the naming in the mapping classes is not consistent at the moment. The conceptual idea in the DataContext and the interplay with waveforms should be final, however. As discussed there, we do a sample, then map.

  • Nearest-neighbor mapping (read and write)
  • PU-RBF mapping (read and write)
  • Testing: serial nearest-neighbor mapping (read and write)
  • Testing: serial PU-RBF mapping (read and write)
  • Parallization/repartitioning
  • Testing: parallel nearest-neighbor mapping (read)
  • Testing: parallel PU-RBF mapping (read and write)
  • More extensive parallel testing

Motivation and additional information

Author's checklist

  • I used the pre-commit hook to prevent dirty commits and used pre-commit run --all to format old commits.
  • I added a changelog file with make changelog if there are user-observable changes since the last release.
  • I added a test to cover the proposed changes in our test suite.
  • For breaking changes: I documented the changes in the appropriate porting guide.
  • I stuck to C++17 features.
  • I stuck to CMake version 3.22.1.
  • I squashed / am about to squash all commits that should be seen as one.

Reviewers' checklist

  • Does the changelog entry make sense? Is it formatted correctly?
  • Do you understand the code changes?

@davidscn davidscn added the enhancement A new feature, a new functionality of preCICE (from user perspective) label Oct 11, 2024
@davidscn davidscn self-assigned this Oct 11, 2024
@davidscn davidscn requested a review from uekerman October 11, 2024 12:42
Copy link
Member

@uekerman uekerman left a comment

Choose a reason for hiding this comment

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

I finally managed to have a look. Sorry for the delay.
Good job already 👍

I did not yet look into the PUM and RBF implementation details and into the tests.

Currently supported mappings are NN and PUM-RBF. There is currently no safeguard that checks this, right?
How much effort would it be to add NP and global-direct RBF? Not saying that we should add them now, but to better understand.

I would suggest to make the feature experimental for the time being and add safeguards to the API functions.

Could you please start working on a docs page in parallel? That would also simplify reviewing.

Comment on lines +120 to +121
/// Returns true if either the input or output is an indirect (dummy) mesh
bool isIndirectMapping() const;
Copy link
Member

Choose a reason for hiding this comment

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

Clear what an "indirect mesh" is? Could be helpful to add more docs here.

Comment on lines +197 to +203
virtual void writeConservativeAt(::precice::span<const double> coordinates, Eigen::Map<const Eigen::MatrixXd> &source, Eigen::Map<Eigen::MatrixXd> &target);

// @todo consider making this a private method in the RBFMapping/PUM mapping class
virtual void updateMappingDataCache(MappingDataCache &cache, Eigen::VectorXd &in);

// For now only for read-consistent
virtual void evaluateMappingDataCacheAt(::precice::span<const double> coordinates, const MappingDataCache &cache, ::precice::span<double> values);
Copy link
Member

Choose a reason for hiding this comment

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

Please add (significant) docs to these functions and then copy-doc to all mapping implementations.

Comment on lines +112 to +127
// @TODO: How to handle the parallel partitioning for indirect access here?
// in the usual case, we make use of the indexSet, which is pre-computed from the mapping
// for the indirect access, we can't do that since we don't have the output mesh
// what we would need to do in theory:
// find all nearest-neighbors at the 'boundary' of the access region, which would require an
// infinite fine sampling of output mesh nodes wo be used in the computeMapping below
// for now, we simply tag everything and move on.
if (this->isIndirectMapping()) {
// Depending on the mapping constraint, one of these tagAll calls will do nothing, as the vertex
// set of the mesh is empty. From a practical point of view, we only need to apply the
// tagging to one of the meshes (the remote one). But calling it on both sides reliefs us from any
// conditional code.
output()->tagAll();
input()->tagAll();
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

IMO, it is the right approach here to tag everything.

find all nearest-neighbors at the 'boundary' of the access region

This depends on how we interpret the access region. Is this the region where a user can call access any location or is this the region where the other mesh is accessed. In the latter case, the user needs to be aware that operating close to the boundary of the box can lead to a bad mapping. Meaning: use a safety margin.
I had this second interpretation in mind.

template <typename RADIAL_BASIS_FUNCTION_T>
void PartitionOfUnityMapping<RADIAL_BASIS_FUNCTION_T>::updateMappingDataCache(MappingDataCache &cache, Eigen::VectorXd &in)
{
// We cannot synchronize this event, as the call might to this function is rank-local only
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// We cannot synchronize this event, as the call might to this function is rank-local only
// We cannot synchronize this event, as the call to this function is rank-local only


// Step 1: use the indexed center mesh to find relevant cluster
query::Index &clusterIndex = _centerMesh->index();
// Step 4: find all clusters the output vertex lies in, i.e., find all cluster centers which have the distance of a cluster radius from the given output vertex
Copy link
Member

Choose a reason for hiding this comment

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

Step 4?

"Participant \"{}\" has a read mapping to mesh \"{}\", without providing it. "
"Please add a provide-mesh tag with name=\"{}\"",
participant->getName(), toMesh, toMesh);
} else {
// A write mapping maps from provided to received
PRECICE_CHECK(participant->isMeshProvided(fromMesh),
// The indirect cannot be on the "to" mesh, as only the combinations read-consistent and write conservative are allowed
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// The indirect cannot be on the "to" mesh, as only the combinations read-consistent and write conservative are allowed
// The indirect cannot be on the "to" mesh, as only the combinations read-consistent and write-conservative are allowed

Comment on lines +446 to 463
// The mesh context associated to the mappings
// impl::MeshContext &fromMeshContext = ;
// impl::MeshContext &toMeshContext = ;

Copy link
Member

Choose a reason for hiding this comment

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

TODO?

Comment on lines +162 to +163
* For conventional mappings, multiple MappingContexts can only occur in write direction (write
* to one local mesh, map it to different remote meshes). Since the indirect mapping operates
Copy link
Member

Choose a reason for hiding this comment

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

dataDims, dataName, meshName,
coordinates.size() / dim, values.size(), expectedDataSize, dataDims, coordinates.size() / dim);

// TODO: Add check that this vertex is within the access region?
Copy link
Member

Choose a reason for hiding this comment

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

yes!

* The usual mapping data structures have no notion about the underlying data.
* The Cache stores in addition a timestep the data corresponds to.
*/
struct MappingDataCache {
Copy link
Member

Choose a reason for hiding this comment

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

This class is currently specific to PUM, right?
This "only" works since NN doesn't need one and you have not yet touched the others, right?

In any case, would it makes sense to move this into impl?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement A new feature, a new functionality of preCICE (from user perspective)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants