-
Notifications
You must be signed in to change notification settings - Fork 248
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
[MedApplication] Add support for reading SubModelParts #11605
Conversation
@matekelemen this is a draft/skeleton so far. I have not tested it, but this is basically how it works. Feel free to give it a try with a simple case, otherwise I will continue in the next days |
thanks, I'm a bit short on time atm, but I'll definitely have a look next week! |
well, you are a phd student after all xD jokes aside, I did some more testing, and pushed a basic working version. Probably there are still some bugs to iron out, but in general it is working. Lets see if I have time in the next days to continue testing |
Ping @matekelemen @sunethwarna |
applications/MedApplication/tests/med_files/cube_sub_subgroups/create_mesh.py
Outdated
Show resolved
Hide resolved
I'll take a closer look this Saturday. I promise! |
all good ^^ |
{ | ||
KRATOS_TRY | ||
|
||
std::unordered_map<int, std::vector<std::string>> groups_by_family; |
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.
How are family numbers generated in MED? If they're sequentially assigned (meaning that the highest family number is lower than the number of families) it might make sense to use an std::vector
instead of an std::unordered_map
, with the indices of entries representing the family number.
The reason why I'm bringing this up is because this map is in the hottest loop of reading: it's accessed for each node and geometry, so it would make sense to make it as efficient as possible.
med_entity_type::MED_NODE); | ||
} | ||
|
||
std::unordered_map<std::string, std::vector<IndexType>> smp_nodes; |
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.
Following along the lines of efficiency, it might make sense to refer to sub model parts by locally assigned IDs rather than their names, to avoid hashing a string for every node/geometry read.
This would involve a bit more work tho (the code below is just an example, I haven't tested it)
+ std::set<std::string> smp_names;
// create SubModelPart hierarchy
for (const auto& r_map : groups_by_fam) {
for (const auto& r_smp_name : r_map.second) {
if (!rThisModelPart.HasSubModelPart(r_smp_name)) {
rThisModelPart.CreateSubModelPart(r_smp_name);
+ smp_names.insert(r_smp_name);
}
}
}
std::vector<std::pair<
std::string, // <== smp name
std::size_t // <== locally assigned ID to the smp
>> smp_name_id_map;
std::size_t smp_counter = 0ul;
std::transform(smp_names.begin(),
smp_names.end(),
std::back_inserter(smp_name_id_map),
[&smp_counter](const std::string& r_smp_name){
return std::make_pair(r_smp_name, smp_counter++);
});
smp_names.clear(); // <== no longer need smp names
std::vector<std::vector<std::size_t>> group_ids_by_fam(highest_family_num + 1); // <== assuming that family numbers are small (assigned sequentially)
for (int i_fam=0; i_fam<group_ids_by_fam.size(); ++i_fam) {
const auto it_group_by_fam = groups_by_fam.find(i_fam);
if (it_group_by_fam != groups_by_fam.end()) {
const std::string& r_group_name = it_group_by_fam->second;
// Find the local id of the smp whose name is r_group_name
auto it_group_id_by_fam = std::find_if(group_ids_by_fam.begin(),
group_ids_by_fam.end(),
[&r_group_name](const auto& r_name_id_pair){
return r_name_id_pair.first == r_group_name;
});
if (it_group_id_by_fam != group_ids_by_fam.end()) [[likely]] {
group_ids_by_fam[i_fam].push_back(it_group_id_by_fam->second);
} else {
KRATOS_ERROR << "Missing local ID for sub model part << r_group_name;
}
}
}
std::vector<std::vector<IndexType>> smp_nodes(smp_counter);
And then use the local IDs in the hot loop:
if (groups_by_fam.empty()) {continue;} // file does not contain families
const int fam_num = node_family_numbers[i];
if (fam_num == 0) {continue;} // node does not belong to a SubModelPart
- const auto it_groups = groups_by_fam.find(fam_num);
- KRATOS_ERROR_IF(it_groups == groups_by_fam.end()) << "Missing node family with number " << fam_num << "!" << std::endl;
- for (const auto& r_smp_name : it_groups->second) {
- smp_nodes[r_smp_name].push_back(new_node_id);
- }
+ KRATOS_ERROR_IF_NOT(fam_num < group_ids_by_fam.size()) << "Missing node family with number " << fam_num << "!" << std::endl;
+ const auto& r_group_ids = group_ids_by_fam[fam_num];
+ for (std::size_t smp_id : group_ids_by_fam[fam_num]) {
+ smp_nodes[smp_id].push_back(new_node_id);
+ }
int num_geometries_total = 0; | ||
IndexType num_geometries_total = 0; | ||
|
||
std::unordered_map<std::string, std::vector<IndexType>> smp_geoms; |
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.
same as smp_nodes
Co-authored-by: Máté Kelemen <[email protected]>
Co-authored-by: Máté Kelemen <[email protected]>
thanks for the review @matekelemen Regarding the optimizations, lets do them in a follow-up PR so that this feature can already be used. I would like to spend some time on it and not rush 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.
Sure, thanks for the hard work!
This PR adds support for reading SubMeshes from med into SubModelPart.