-
-
Notifications
You must be signed in to change notification settings - Fork 182
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
Allow specifying attribute name when reading meshtag #3257
Conversation
python/dolfinx/io/utils.py
Outdated
return MeshTags(mt) | ||
|
||
def read_meshtags(self, mesh, name, xpath="/Xdmf/Domain"): |
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.
Needs docs.
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.
Done
python/dolfinx/io/utils.py
Outdated
@@ -276,10 +276,13 @@ def read_mesh( | |||
) | |||
return Mesh(msh, domain) | |||
|
|||
def read_meshtags(self, mesh, name, attribute_name="", xpath="/Xdmf/Domain"): | |||
mt = super().read_meshtags(mesh._cpp_object, name, attribute_name, xpath) | |||
def read_meshtags_by_name(self, mesh, name, attribute_name, xpath="/Xdmf/Domain"): |
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.
Would it be better as one function and using default arg attribute_name=None
?
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 remember that you don't like having two default arguments in one function but I'm guessing that's only for C++, right?
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.
Not good for C++, fine with Python if it's simple (which this is) and doesn't introduce complicated conditional handling.
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.
Done
cpp/dolfinx/io/XDMFFile.cpp
Outdated
const mesh::Mesh<double>& mesh, const std::string name, | ||
const std::string attribute_name, const std::string xpath) | ||
mesh::MeshTags<std::int32_t> | ||
XDMFFile::read_meshtags_by_name(const mesh::Mesh<double>& mesh, |
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.
Let's change name
-> label
in the function name. 'name' is ambiguous.
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.
Done
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.
The code is XDMFFile.cpp
looks to me more complicated than it needs to be. I've left some suggestions as a first pass. I can look again once it's been simplified some more.
cpp/dolfinx/io/XDMFFile.h
Outdated
@@ -164,9 +164,21 @@ class XDMFFile | |||
const mesh::Geometry<T>& x, std::string geometry_xpath, | |||
std::string xpath = "/Xdmf/Domain"); | |||
|
|||
/// Read MeshTags by name |
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 is a bit confusing - the docstring says "Read MeshTags by name" but the function name is "read_meshtags_by_label". Is it by name or by label?
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.
The issue comes from the following fact: mesh tags are identified by "a word", so it is natural that this word be called the "name" of the mesh tag. The problem is that there is already another name
parameter which refers to the name of the mesh node in the same file. I picked the word "label" to distinguish the two internally, in the code implementation, but a user should not be concerned with this implementation detail: a user saved a mesh tag giving it a "name" and wants to read it back by the same "name".
The fact remains that the user still needs to call a function whose name includes the word "label", not "name", which is indeed a bit confusing. I will change everything to be called more consistently, the code shouldn't become too unintelligible on the development side.
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.
By the way, re-reading this conversation I noticed that in the first review, four months ago, you asked me to change the method name to avoid the word "name" in favour of "label". I had forgotten about that and, based on your comment, I reverted the change. Which one should I keep? To a user, a mesh tag's "label" means presumably very little...
@garth-wells |
cpp/dolfinx/io/XDMFFile.cpp
Outdated
@@ -334,8 +334,9 @@ template void XDMFFile::write_meshtags(const mesh::MeshTags<std::int32_t>&, | |||
/// @endcond | |||
//----------------------------------------------------------------------------- | |||
mesh::MeshTags<std::int32_t> | |||
XDMFFile::read_meshtags(const mesh::Mesh<double>& mesh, std::string name, | |||
std::string xpath) | |||
XDMFFile::read_meshtags_by_name(const mesh::Mesh<double>& mesh, |
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 really want a separate function for this in C++? Couldn't we just put the attribute name as a fourth argument (optional) argument.
I don't see the added value of a constructor for handling one optional value to have a backwards compatible C++ interface. @garth-wells
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, one function would be better. Would is make sense to use std::optional
for attribute_name
?
Related to this, we should not pass empty strings as 'null' - use std::optional
.
cpp/dolfinx/io/XDMFFile.cpp
Outdated
@@ -334,8 +334,9 @@ template void XDMFFile::write_meshtags(const mesh::MeshTags<std::int32_t>&, | |||
/// @endcond | |||
//----------------------------------------------------------------------------- | |||
mesh::MeshTags<std::int32_t> | |||
XDMFFile::read_meshtags(const mesh::Mesh<double>& mesh, std::string name, | |||
std::string xpath) | |||
XDMFFile::read_meshtags_by_name(const mesh::Mesh<double>& mesh, |
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, one function would be better. Would is make sense to use std::optional
for attribute_name
?
Related to this, we should not pass empty strings as 'null' - use std::optional
.
std::iota(std::begin(indices), std::end(indices), 0); | ||
|
||
std::vector<std::int32_t> domain_values(n_cells); | ||
std::ranges::fill(domain_values, domain_value); |
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.
Just use std::vector<std::int32_t> domain_values(n_cells, domain_value);
std::vector<std::int32_t> domain_values(n_cells); | ||
std::ranges::fill(domain_values, domain_value); | ||
|
||
std::vector<std::int32_t> material_values(n_cells); |
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 above comment.
python/dolfinx/io/utils.py
Outdated
@@ -276,8 +276,15 @@ def read_mesh( | |||
) | |||
return Mesh(msh, domain) | |||
|
|||
def read_meshtags(self, mesh, name, xpath="/Xdmf/Domain"): | |||
mt = super().read_meshtags(mesh._cpp_object, name, xpath) | |||
def read_meshtags(self, mesh, name, attribute_label=None, xpath="/Xdmf/Domain"): |
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.
Follow the Google docs style with Arguments
, etc. There are quite a few examples in the code.
Nice - looking good. |
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.
LGTM!
Co-authored-by: Jørgen Schartum Dokken <[email protected]>
64ad359
to
d348efa
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.
I've pushed some fixes to the code. Last things that is missing is a Python test. @massimiliano-leoni can you add a Python test?
@garth-wells Python test added! |
If no
attribute_name
is provided, read the first attribute. Otherwise, read the attribute with the provided name or throw an error if it couldn't be found.