Inferring box dimensionality

Issue #185 resolved
Vyas Ramasubramani created an issue

The discussion of when and how to infer box dimensionality has been had many times and is still not quite 100% resolved in the code. I'd like to have consensus on this, so I've summarized the possible cases here. @mspells @harperic @csadorf @joaander since all of you have been involved with this, I would appreciate any feedback where the decisions I've proposed don't make sense.

From matrix

Current behavior

Lz=0 Lz!=0
Dims=2 2d Warn, but assume 2d
Dims=3 3d, but causes erroneous behavior 3d
Dims=None 2d 3d

Proposed behavior

Lz=0 Lz!=0
Dims=2 2d Warn, but assume 2d
Dims=3 Error 3d
Dims=None 2d 3d

We may also want to eventually make that warning an error, unless there is a good reason to continue permitting it beyond backwards compatibility. Thoughts? I would not propose making that change until >v1.0.0.

Explicit construction

Current behavior

The main difference between explicit construction and using from_matrix is that no dimensionality inference occurs because instead of an integer dims argument, there is only a boolean is2D flag. In particular, this means that if Lz == 0 and is2D is False, the constructor assumes that the dimensionality is 3, which leads to the same erroneous behavior as specifying dims=3 explicitly in the from_matrix case.

Proposed behavior

Same as for from_matrix.

From namedtuple or dict

Current behavior

Same as above, except in this case in addition to the dimensionality argument of the constructor the namedtuple object can also have a dimensionality key. Currently, dimensionality is resolved by the following order of precedence: (1) the dimensionality argument (if given), (2) the dimensionality key of the tuple (if present), and finally (3) is Lz == 0?

Proposed behavior

All previously proposed rules apply. Maintain current resolution order described above, but error if the dimensionality function argument and the dimensionality key of the namedtuple conflict.

From list-like (includes tuple)

Current behavior

Lists of length 2, 3, or 6 are acceptable. If length 2, it's 2d. If length 3, it's 3d. Entries 4-6 are tilt factors if the length of the list is at least 6.

Proposed behavior

No change, except that an error should be raised if len(list) not in [2, 3, 6].

From freud.box.Box

Trivial case, freud.box.Box should always be well-defined within freud's own standards.

Comments (13)

  1. Carl Simon Adorf

    So the proposed changes in summary are (correct me if I'm wrong):

    1. Raise exception when Lz is set to 0, but the is2D flag is not set.
    2. Raise an error when the dimensionality function argument and key/attribute conflict.
    3. Raise error for lists that are not of length 2, 3, or 6.

    Concerning 1: What is the reason to change this? I would argue that a 3D box with one, two, or all of the dimensinos equal to zero, is a special case of a 3D box. Maybe any of the freud analysis methods that fail in those case should explicitly account for "folded" dimensions?

    Concerning 2 and 3: I see no issue with that.

    I'm not sure I like the idea of promoting the warning to an error for the dims=2, Lz!=0 case, just because afaik 2D HOOMD-blue boxes are Lz=1.0. But maybe it is a good idea, and we can resolve issues with HOOMD-blue boxes in some other way. That's something we would need to look into before applying that change.

  2. Bradley Dice

    @csadorf 1: Many freud methods fail when they try to divide by Lz when it is zero.

    Also I don't think this is suggesting that we promote the warning to an error when Lz != 0 and is2D=True in my understanding. It will remain a warning.

  3. Eric Harper
    1. How would you end up with Lz != 0 and only 2 dimensions? (I haven't used Freud daily in a while, so I'm a bit out of practice)
    2. I could see equally valid arguments that Lz=0 for 3 dimensions could/should be interpreted as being 2D. Could we use a utility function, much like the auto-casting of numpy arrays, to have the behaviour be correct on a per-module basis ie give an error when 2D vs. 3D matters. For example, this would matter in the RDF function, so perhaps you even need to allow for a flag to forcibly allow for either a 2D or a 3D interpretation?
  4. Matthew Spellings

    I would say that the proposed changes are fine with the exception of an error when Lz!=0 for a 2D box. This is how many (all?) things that you'll get that have touched hoomd will be formatted, so I don't even think that should necessarily print an error. Since we're taking the box dimensionality as an argument, I think we should follow that when possible. If Lz==0 and the box is supposed to be 3D, I think that should still be an error.

  5. Vyas Ramasubramani reporter

    @csadorf Not quite. What I am advocating for regarding case 1 is the following. Instead of is2D defaulting to False, it should default to None. If not specified, the dimensionality should be inferred from Lz, which is what the from_matrix method does.

    Regarding your broader point, I agree in principle that having other dimensions be zero is a special case of a 3D. In practice, however, nothing in freud supports Lx or Ly being 0, including the current box implementation, and I don't think there's any value-add in supporting lower dimensional boxes or a 2d box with a dimension other than z being 0. The only API-level change this would cause is preventing users from specifying that a box is 3D but passing Lz=0.

    @harperic For your first question, that's what you get from HOOMD: 2D simulations in HOOMD set Lz=1 but have the boxdim.dimensions variable set to 2. Regarding your second point, I'm not quite sure I follow. In the table above, the only case I want to explicitly disallow is specifying dimensions=3 but having Lz=0, which leads to dividing by zero everywhere. Aside from that, the box knows its dimensionality so other modules can access that. Also FYI, we now have a utility function freud.util.convert_box that is analogous to freud.util.convert_array for boxes.

    @mspells @csadorf @bdice it sounds like the general consensus is that we should support HOOMD boxes as is. I'm fine with not changing that warning to an error. I'd like to keep the warning in place, however, in case non-HOOMD users come to this and actually provide bad inputs.

  6. Eric Harper

    @vramasub I think that answers my questions. Historically Freud has always followed/been related to HOOMD-Blue, so when I doubt I usually defer to following/supporting HOOMD conventions, and in this case, I would make sure that Freud handles the HOOMD-Blue defaults as gracefully as possible.

    To my second point, having thought about it more, I was in general asking about quasi-3D systems (for example spheres trapped between two walls for example), and being able to treat such as system as either explicitly 2D or 3D may be important. However, the ndims=3, Lz=0 really doesn't make sense in such a case. TL;DR ignore the question.

    Finally, I agree that a warning definitely makes sense w/r/t the ndim=2, Lz != 0. @vramasub @mspells @csadorf @bdice Is there some way we could potentially check for a HOOMD metadata flag to more gracefully avoid the warning for HOOMD-Blue users? Does that make sense?

  7. Bradley Dice

    @harperic I don't think a HOOMD metadata flag is possible. Leaving a warning in place is a good safety check.

  8. Log in to comment