-
-
Notifications
You must be signed in to change notification settings - Fork 210
Add global/meshless data #1549
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
Add global/meshless data #1549
Conversation
0603299 to
cf02bf3
Compare
|
The many changes are due to the github pr pointing to develop-3.0.0 instead of develop. |
uekerman
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.
Had a first more thorough look at this. Nice that it works for simple problems already 👍
Please rebase often. A few recent changes might have a big influence here. Good news: I think they simplify things.
The amount of code duplication looks a bit unfortunate. Maybe we could reduce this by defining a common interface for both data types (mesh-based and global)?
@fsimonis Any quick suggestions?
Connected to the discussion in #202, "size" is currently fixed at 1. In my opinion, this is completely OK as a first step. Let's only try to generalize this later if required.
Probably clear, but we need to increase test coverage, especially tests that combine global and mesh-based data. Also, the combination with waveform iteration and data initialization needs testing.
In general, please don't commit commented-out code. Only leads to confusion in the long run.
|
There is actually no real difference between |
Yes agree; I also felt and suggested the same back in January. Will check now if changing all And actually this is only one of the multiple classes/structs associated with global data that are just slightly modified equivalents of their mesh-data cousins. So there is more potential for removing code duplication, but others might not be so straightfoward as reusing |
BenjaminRodenberg
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.
I added a few comments on the question whether there should be a GlobalDataContext or rather a GlobalReadDataContext and GlobalWriteDataContext.
| * - GlobalDataContext is basically a stripped-down equivalent of DataContext. | ||
| * Unlike DataContext, it has no associated mappings or meshes. | ||
| */ | ||
| class GlobalDataContext { |
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.
Why does GlobalDataContext not inherit from DataContext? (compared to ReadDataContext and WriteDataContext)
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.
DataContext has a pointer _mesh and mesh-associated query functions which were not needed for global, so I created a new GlobalDataContext (just like GlobalData was created instead of reusing Data).
But now following the same philosophy of getting rid of GlobalData and making Data itself versatile, we can do the same here, i.e., reuse DataContext for global by for e.g. setting _mesh to nullptr in case of global contexts.
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 now following the same philosophy of getting rid of
GlobalDataand makingDataitself versatile, we can do the same here, i.e., reuseDataContextfor global by for e.g. setting_meshto nullptr in case of global contexts.
Sounds to me like a risky approach: We then get a general Data that is either implicitly global (has, for example, empty gradients and no _mesh) or lives on a mesh. To me this sounds like there should be an AbstractData which provides the base for MeshData and GlobalData. But not sure about all the implications this might have, though.
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.
For now I've made Data work for both mesh and global datas, and it looks good.
Regarding an AabstractData: The current Data class has no knowledge of any mesh (Datas don't point to any meshes. Only meshes point to their Datas).
Since Data is already dumb, it makes sense to me to use it as it is for both mesh-associated and global use cases.
33552c0 to
0576ed3
Compare
| * @param[in] mappingContext Context of the mapping | ||
| * @param[in] meshContext Context of mesh this mapping is mapping from or to | ||
| */ | ||
| virtual void appendMappingConfiguration(MappingContext &mappingContext, const MeshContext &meshContext) = 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.
Explanation: This function is removed because Global read/write DataContexts inherit from DataContext, but don't implement appendMappingConfiguration(...)
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 then you have to declare this function in ReadDataContext and WriteDataContext. We could, of course, introduce an intermediate layer LocalDataContext just for this purpose, but this looks overengineered. You can also just implement it in Read/WriteGlobalDataContext and trigger an assertion, if somebody tries to call the function.
In the end this is a hint for some problem with the class design, but I think we can live with 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 am really sorry, but I think we need another rebase. But those massive changes should soon be over 🙈
In general, please resolve done conversations. Such that we can keep a better overview of what we still need to do.
To reduce some of the code duplication here (e.g. convergence measures), maybe we could restrict the feature to explicit coupling for the moment??
Before merging we definitely need:
- Integration tests that combine mesh-based and global data
- Mark feature as experimental
Open TODOS that could also come later, but should be documented in a follow-up issue:
- Implementation in Fortran and C bindings
- Get rid of the hacks
- Support for parallel participants
- Support implicit coupling
- Package name
mesh
55ca9fa to
3fac740
Compare
37dd7a7 to
3453ef0
Compare
We can also allow global data exchange during implicit coupling without offering convergence measures for global data. |
uekerman
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.
Couldn't we save a lot of code duplication if we create an abstract bases class CouplingData from which then the current CouplingData (needs a different name then) and GlobalCouplingData inherits? Then, we don't need a GlobalDataMap etc
Ah yes. There was actually nothing new in GlobalCouplingData, so I've removed it altogether. Drawback: No more |
Sounds good 👍
-> sth for the follow-up issue |
072668c to
04d3600
Compare
uekerman
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.
In a good-enough state to merge from my perspective. Remaining TODOs are documented in #1716.
Thanks for the patient and extensive contribution @kanishkbh 🚀
@BenjaminRodenberg Please check again the interplay with waveforms. Are we missing anything?
@fsimonis Please have a brief general look again. Anything we might regret in the future?
BenjaminRodenberg
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.
I think some tests using a MultiCouplingScheme or CompositionalCouplingScheme would be good, because this is often a place where the integration of experimental features causes problems. Besides that: I don't see a problem right now. The amount of code-duplication will require some refactoring in the future, but that's ok.
src/cplscheme/BaseCouplingScheme.cpp
Outdated
| if (not data->isGlobal()) { | ||
| meshID = data->getMeshID(); | ||
| } else { | ||
| meshID = -1; |
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.
Using something like mesh::GLOBAL_DATA_ID would be better here. (compare to time::Storage::WINDOW_START)
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.
Agree. Added a mesh::Mesh::GLOBAL_DATA_MESH_ID{-2}
(-1 is reserved for MESH_ID_UNDEFINED)
| // TODO: store mesh and global data together in a `DataMap _allData ` (currently produces a bug), see https://github.com/precice/precice/issues/1716 | ||
| if (isGlobal) { | ||
| if (!utils::contained(id, _allGlobalData)) { // data is not used by this coupling scheme yet, create new CouplingData | ||
| _allGlobalData.emplace(id, ptrCplData); | ||
| } else { // data is already used by another exchange of this coupling scheme, use existing CouplingData | ||
| ptrCplData = _allGlobalData[id]; | ||
| } | ||
| } else { // mesh data | ||
| if (!utils::contained(id, _allMeshData)) { // data is not used by this coupling scheme yet, create new CouplingData | ||
| _allMeshData.emplace(id, ptrCplData); | ||
| } else { // data is already used by another exchange of this coupling scheme, use existing CouplingData | ||
| ptrCplData = _allMeshData[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.
Any chance to try to merge _allGlobalData and _allMeshData like suggested above? I guess otherwise we will just keep it the way it is for a very long time.
| PRECICE_TRACE(_timeWindows); | ||
| for (auto &data : _allData | boost::adaptors::map_values) { | ||
| for (auto &data : _allMeshData | boost::adaptors::map_values) { | ||
| data->moveToNextWindow(); | ||
| } | ||
| for (auto &data : _allGlobalData | boost::adaptors::map_values) { | ||
| data->moveToNextWindow(); | ||
| } |
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 cannot put both into _allData, maybe try to use a function allData() that returns _allMeshData + _allGlobalData? (maybe this also leads to the same bug again)
| /// All send and receive data as a map "data ID -> data" | ||
| DataMap _allData; | ||
| /// All send and receive mesh-associated data as a map "data ID -> data" | ||
| DataMap _allMeshData; | ||
| /// All send and receive global data as a map "data ID -> data" | ||
| DataMap _allGlobalData; |
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 would suggest to add the comment TODO ... here instead.
| * @param[in] mappingContext Context of the mapping | ||
| * @param[in] meshContext Context of mesh this mapping is mapping from or to | ||
| */ | ||
| virtual void appendMappingConfiguration(MappingContext &mappingContext, const MeshContext &meshContext) = 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.
But then you have to declare this function in ReadDataContext and WriteDataContext. We could, of course, introduce an intermediate layer LocalDataContext just for this purpose, but this looks overengineered. You can also just implement it in Read/WriteGlobalDataContext and trigger an assertion, if somebody tries to call the function.
In the end this is a hint for some problem with the class design, but I think we can live with it.
fsimonis
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.
I would prefer to refactor this PR before we merge it as I see the risk of introducing a lot of preventable duplication, which could easily diverge.
We definitely still need:
- Tests for Multi Coupling schemes
- Tests for Compositional schemes
Refactoring on my list:
- Simplify the implementation of the configuration
- Merge data and global data containers
- Simplify DataContexts
- Investigate if we can make Data self-aware if it is global or not.
| } | ||
|
|
||
| PtrCouplingData BaseCouplingScheme::addCouplingData(const mesh::PtrData &data, mesh::PtrMesh mesh, bool requiresInitialization, bool communicateSubsteps) | ||
| PtrCouplingData BaseCouplingScheme::addCouplingData(const mesh::PtrData &data, mesh::PtrMesh mesh, bool requiresInitialization, bool communicateSubsteps, bool isGlobal) |
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 would become way simpler if Data would know if it is global or attached to a mesh.
Multi coupling is not yet supported in this PR, see #1716 |
|
In #1742, we moved the So At this point, we can either make the vectorial dimension explicit, <global-data:scalar />
<global-data:vector2d />
<global-data:vector3d />or we make the entire dimensionality explicit, allowing global data of any dimensions pretty naturally and requiring only a single tag. <global-data dimensions="1" />
<global-data dimensions="2" />
<global-data dimensions="3" /> |
|
Good point. Alternatively, if we want to keep things simple here and extend later, we could restrict the feature to scalar first. <global-data:scalar />In principle, <global-data dimensions="n" />sounds good, but might lead to (much?) additional work if we allow any |
Sounds inconsistent with the
Sounds more natural.
I like the "let's try things slowly" approach.
Why the too much additional work (compared to |
Just had a look again: It should actually be easier than I originally expected. Might only need changes in the |
|
This PR is on hold until we figure out how to implement this without the current amount of tech-debt due to duplication. The workaround is documented and pretty trivial. I'll unassign myself and turn this into a draft PR. |
We are closing this PR as the diff has grown too big. We need to start again with the lessons learned. |
Adds functionality to exchange data that is not associated with any mesh. So far the name is "global-data".
Motivation and additional information
Closes #202
Main changes of this PR
API
Configuration
global-dataAllow implicit coupling to configure convergence measures for global data without specifying any mesh name.(Open TODO for a future PR)Data
Add aGlobalDataclass (meshless equivalent ofData).DataConfiguration:global-datatag._globalDatainDataConfigurationto store global data here asDataobjects.Participants
GlobalRead/WriteDataContextsclass (meshless and mappingless equivalents ofRead/WriteDataContext) which inherit fromDataContext.ParticipantStateandParticipantConfiguration: Configure and store global read/write contexts.Coupling
Add aAdd anGlobalCouplingDataclass, analogous toCouplingDatafor mesh data.isGlobalattribute toCouplingDataand use it for global coupling as well.CouplingSchemeConfiguration: Add a struct to store global exchanges and functions for global data (analogous to mesh-associated data).Com
M2N: always use intracom in case of global data.Open Questions and TODOs:
Documented in #1716
Author's checklist
pre-commithook to prevent dirty commits and usedpre-commit run --allto format old commits.make changelogif there are user-observable changes since the last release.Reviewers' checklist