-
Notifications
You must be signed in to change notification settings - Fork 8
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 support for non-diagonal supercells #320
Add support for non-diagonal supercells #320
Conversation
We'll need to figure out how this fits with #307. If that's merged, supercell would be be a tuple ( |
In that case, we could go for the other option of having two different options, |
I'm not set on anything too specific, but yes given that the approach consistent with the current main would be I'm hesitant to change If you can find alternatives that let us neatly unify them (maybe with a custom type - I've seen that as a suggestion for click Unions, which typer is based on) that would also be welcome. |
It isn't only unwieldy; it's nonsensical! In the diagonal case we can "multiply" to describe the overall cell volume, but it doesn't work for matrix elements. How about It looks like Typer is also rubbish at mutually-exclusive arguments 😞 |
Another option I thought of would be to have only
I had a try experimenting with this, but I can only see how that would allow us to parse the two strings, i.e. I have also tried the hack I mentioned earlier, but I'm unclear on how to make it work with typer since it's unclear where/how typer actually uses There is probably a way to use both of the above workarounds, but I reckon it will probably need much deeper understanding of how typer works under the hood. Overall, it seems to me that the |
Single responsibility principle in me is screaming at this suggestion. They're two different jobs which have two different outcomes and two different meanings. They shouldn't share a name even if they ultimately affect the same var. |
I think this might be exactly how Typer wants to do it (with a hint like |
Is your objection to using |
Also note @RastislavTuranyi you'll need to rebase to include changes from #307 |
That the meaning of You could be fooled into interpreting it is "ah, we do the computation sequentially with 3 supercells, the first diag(1, 2, 3), the second with diag(4, 5, 6) the third with diag(7, 8, 9)" Which depending on the values of 1-9 may not be reasonable. (3, 1, 1), (1, 3, 1), (1, 1, 3) supercell in x, then y, then z and get the appropriate phonon blocks out. OR supercell 3 in the cardinal directions with some off diagonal. |
I wouldn't quite describe it as being called, it's the typer way of creating lists, so [(x, y, z)] being different to [(a, b, c), (d, e, f), (g, h, i)] isn't quite so unreasonable, but yes it probably is still more confusing than alternatives, given that you might start with |
I agree that both
|
Just found this typer PR which does almost what we want, jut requiring a specific separator, but it's likely going to be a while until that gets into an official release. Also found this hack which actually pre-processes the CLI and therefore seems to be the only thing that has a chance of working with typer. EDIT: The pre-processing hack works for positive integers, but it can't deal with negative values (e.g. |
One option which I'm pretty sure works if duplicating the custom E.g. def parse_tuple_class(value: tuple):
"""
Convert string input into a tuple.
Parameters
----------
value : str
String representing tuple to be parsed.
Returns
-------
TyperTuple
Parsed string as a tuple.
"""
if isinstance(value, tuple):
return TyperTuple(value)
return TyperTuple(ast.literal_eval(value)) I think it's marginally nicer as a tuple, but the same thing could be done to parse comma separated text ( We'd just need to validate the length is either 3 or 9, and probably do type checking too. |
Since there was no additional discussion, I have implemented the |
@RastislavTuranyi this will need to be rebased, can you ask @ajjackson to help you if you never done it before? |
Thanks for this! Did you rule out the approach I suggested with building tuples similarly to how dictionaries are currently implemented? To me, it feels nicer to have the same option, Whether it's two similarly-named options, or one option that handles different lengths slightly differently, I think some ambiguity before reading the docs is unavoidable, so I don't think there's a perfect option. I don't think the customs tuples have quite the same issues as we discussed with I'm ok with |
technically there are three meaningful ways to specify a supercell, depending what you are after, single scalar n, for same repetition in all directions, most common choice, n1 n2 n3, maybe different numbers in all 3 directions, and the full matrix. given the other ones are shortcuts to the generalised version personally I will go with one --supercell, and based on the input, decide if we deal with generalised or one of the two shortcuts. I agree with @oerc0122 in using different names for things that do different things but in this case we do the same thing specify a supercell with different shortcuts. |
I would argue that because the arguments are different types (3-tuple, 9-tuple, nothing in-between) It's pretty reasonable to specify them through different cmdline args so you have to be explicit and there's less confusion in scripts. For scalar -> @ElliottKasoar 's suggestion on the tuples is fine, but would a user expect to enter "(1, 2, 3, 4, 5, 6, 7, 8, 9)" or "((1, 2, 3), (4, 5, 6), (7, 8, 9))" would they be different? How about "(1, 2, 3)" or "(3,)" or "(3)"? What about if they put in "((1,), (2, 3), (4, 5, 6, 7, 8, 9))". It's a lot more effort to define in some senses. |
I'm open to alternatives, but I assumed we'd define the input as either an integer ( I think something like We could also permit |
I'm not a fan of parentheses in the string, unless we have line breaks as well it does very little to improve legibility. Phonopy allows the user to provide 3 or 9 arguments to the same parameter, so the most "phonopy native" syntax is not really viable. String quoting with spaces in between numbers is an approximation to this. I would be fine with giving 9 values all the time but this is likely unpopular with other users... I think having separate |
I wouldn't necessarily say it's about legibility, more just familiarity with how you would define it in the Python, and convenience for parsing it into an actual tuple. Removing the parenthesis and having space/comma separated options in a string would be a similar, reasonable solution, but would maybe feels a bit more arbitrary. Again, I'm happy to go with the consensus, but when we already have a lot of options, and potentially more on the way with the refactor, splitting it into two feels a bit unnecessary. Also, while the type hint for each option's purpose may be slightly simpler, we'd probably also need to describe in at least one of them, maybe both, how they interact, which adds a bit more complication. |
Typically command-line arguments that would be mapped to a python list or tuple accept NARGS values directly; that's the familiar interface for such things. Typing Python code as a command-line argument feels a bit odd and uncomfortable; maybe because it alerts a primal fear that this string is about to get |
A legitimate fear! I agree it's very far from perfect, and unintuitive for CLI users, but I think we're stuck finding the least bad option. My point about other alternatives being more arbitrary was that if it can't be done in a way that's familiar in terms of CLIs, mirroring the Python at least adds some level familiarity, and consistency with kwarg dict inputs, so it's probably easier to remember than a more arbitrary construct, even if it does look strange. Splitting it into two options does allow nicer inputs, so the question is whether that's worth the added complication of two similar, competing options, no integer input option, and a less obvious mapping to phonopy. I think we probably do need to settle on something though, at least between one or two command line options! |
In the interest of finishing this up, and after discussing it a little more with @alinelena, I think we should go for I don't mind too much between "x y z" and "(x, y, z)", if it works. (Maybe the former is a little closer how we'd like the tuple input to be, so makes slightly more sense? I've only tried the latter though, so implementation may be tricker.) Would that be ok, @RastislavTuranyi? If how to deal with the parsing etc. is unclear, I'm happy to help more. |
Here are a couple of ideas tuple(map(int, supercell.split())) # "1 2 3"
json.loads(supercell.replace("(", "[").replace(")", "]")) # "(1, 2, 3)" Whitespace separation looks cleaner to me! |
For the latter tuple(map(int, supercell.strip("()").split(",")) |
If the parser isn't going to look at the parens, why ask for them? |
Agreed, I personally wouldn't expect to add parens to a CLI param. |
rebase |
9f6783e
to
0956286
Compare
Done! I have also reverted to the string implementation, since that appeared to be the consensus? |
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.
Looking good!
Could you please update the docs? In particular, the command line interface page of the user guide, but worth checking supercell
doesn't appear anywhere else.
My only other thought is if we can make the docstrings slightly more concise, but if in doubt I'm happy to err on the side of clarity.
I have updated the code examples to use quotes for the integers, but would you like me to add a paragraph explaining the various possible inputs for I haven't found any mentions of phonons or supercell in the rest of the .rst documents; they either don't mention it or are auto-generated. Maybe the jupyter notebook examples should be updated? |
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 have updated the code examples to use quotes for the integers, but would you like me to add a paragraph explaining the various possible inputs for
--supercell
as well? Or maybe just reuse the existing code examples by passing in the supercell using a different format in each?I haven't found any mentions of phonons or supercell in the rest of the .rst documents; they either don't mention it or are auto-generated. Maybe the jupyter notebook examples should be updated?
Thanks, @RastislavTuranyi!
It might be nice to add a quick note in the CLI docs about how supercell can be defined, if that's ok, but it's not essential.
I need to do another pass on the tutorials to make sure they're still consistent with the newest changes, so I'll handle those separately, thanks!
I can't comment on the code, but the supercell : MaybeList[int]
description for the Phonons
class parameters needs updating to match the __init__
definition.
Would be good if anyone else who uses Phonopy can confirm they're happy, but other than the minor suggestions (/typo corrections) I think this is good to go from my perspective
Everything should be updated now, though please do let me know if the CLI documentation is too verbose or not detailed enough. |
I think the section you added is a good amount, thanks! Generally I lean towards more concise wording for something like the output from Thank you everyone for the work that's gone into this! |
As discussed, and mentioned in #310, I had a try at adding support for non-diagonal supercells to phonon calculations. The Python API change is small: simply adding support for lists of length 9, which are then turned into a 3x3 matrix. The CLI API is much trickier due to the restrictions that typer/click impose (certain hacks notwithstanding); for now, I and @ajjackson decided to require the supercell input to be a whitespace-separated string, e.g.
"1 2 3"
), which would have to be passed in as a string. The other option we considered was having two different options for the two cases, e.g.--supercell-diagonal
and--supercell-nondiagonal
. However, we aren't sure what would be the best approach; what do you think?Also, I have tried adding some tests, but let me know if more/different tests are required.