Skip to content

Conversation

momchil-flex
Copy link
Collaborator

Symmetries specified in a ModeSpec now generally work, but there are a lot of possible edge cases...

Also, I have built release-22.1.4 on the server with all the changes from last week, and set it as default here.

# Truncate according to symmetries
solver_coords = [coords.copy() for coords in plane_coords]
plane_shape = list(eps_wg_xx.shape)
for ic, coords in enumerate(solver_coords):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did pylint let you get away with this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, no, it does complain

if mode_spec.symmetries[0] != 0:
sym_val = mode_spec.symmetries[0]
# Pad symmetry-tangential E fields
e_full[[1, 2], 1:Nx//2, :, :] = sym_val * e_full[[1, 2], :Nx//2:-1, :, :]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should think about generalizing these a bit in a symmetry padding function, it's a bit unwieldy


# Rotate back to original coordinates
(Ex, Ey, Ez), (Hx, Hy, Hz) = rotate_field_coords(E, H)
(Ex, Ey, Ez), (Hx, Hy, Hz) = rotate_field_coords(e_full, h_full)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems rotate_field_coords does the same thing to e_full and h_gull
Should we make this a function of a single argument and call it twice?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

Copy link
Collaborator

@tylerflex tylerflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if these are pedantic comments. I feel like this is probably good enough. But, if we have time, we could refactor a little bit more to help ourselves as we build upon this (or replicate similar things in other places (near2far most notably).)

@momchil-flex
Copy link
Collaborator Author

I completely agree about the reorganization. I just wanted to get it done before leaving in case it's needed (by a user). I guess it wasn't. I guess since it doesn't seem urgent I can work on the symmetries further. I like your idea of potentially incorporating the unfolding in the FieldData, will be useful for monitors in simulations with symmetries too.

Also symmetries are always really annoying and edge case-y, e.g. like we discussed for example what happens if someone has put the mode plane in a way such that its center doesn't match a simulation cell, or the discretization has an odd number of cells (the symmetry implementation currently assumes even). And these things are even more problematic if they're using non-uniform mesh. Basically we need to ensure that the discretized gird itself has the required symmetry. Last we talked about this I think we decided to just remove the option for symmetries in the ModeSolver unless e.g. the plane center matches the simulation center in that direction, and the simulation is defined with having the same symmetry. This should ensure that the discretized grid is then also symmetric. It feels a bit restrictive, but I think it covers many use cases.

P.S. Actually I think even this doesn't ensure that the discretized grid would be symmetric because of numerical precision issues when the plane size is "exactly" multiple of the grid step. But we could modify the discretize function for simulations to take symmetries into account and always return an even number of cells.

@tylerflex
Copy link
Collaborator

One other thing to consider is that the symmetries are specified in both the ModeSpec but also in ModeSolver.simulation.symmetry. So either we need to enforce that these match (and the mode plane is centered on the symmetry plane if specified). Or we should remove the symmetries in the mode spec and just have the symmetries come directly from the Simulation, if applicable.

@tylerflex
Copy link
Collaborator

I think we should be as restrictive as we need to be to ensure it works properly if only for the most simple cases.

@momchil-flex
Copy link
Collaborator Author

Yeah good point they can just be removed from the ModeSpec. I think this means substantial changes to this PR before it can be merged, as I'll need to re-enable the simulation symmetry and set up at least some of the infrastructure to handle it. I guess no rush to merge?

@tylerflex
Copy link
Collaborator

No rush to merge, except that one commit I made to fix the monitor data size computation. Maybe should have done that on another branch. Do you know how to incorporate that in a different PR or just add it to develop?

@momchil-flex
Copy link
Collaborator Author

git checkout develop
git cherry-pick a1532b031ed294d3ce9510984bcdc702097ab03f

@tylerflex
Copy link
Collaborator

Alright, I just did this in #211. Feel free to merge and then remove my commit in this PR.

@tylerflex
Copy link
Collaborator

I didnt cherry pick, didnt see your message in time, just made a new branch off develop and checked out that file.

@momchil-flex
Copy link
Collaborator Author

That also works for a single file.

@momchil-flex momchil-flex force-pushed the momchil/mode_solver branch 3 times, most recently from f3741ea to 8c7e76e Compare February 22, 2022 00:48
@momchil-flex
Copy link
Collaborator Author

  • Symmetries in mode solver now taken from simulation symmetries, if the mode plane lies on the simulation center.
  • Validator that mode objects with symmetries are either entirely in the main quadrant, or lie on the symmetry axis.
  • Setting up some infrastructure for handling symmetries in general.
  • AbstractFieldData now has an apply_syms method which uses interpolation and symmetries to create a new field data on a global grid. This may be refactored a little bit more in the future. What I am considering doing is storing the ScalarFieldData on the smallest main quadrant grid that can fully cover the global (symmetry-unwraped) FieldData dict. In FieldData, I could also store the symmetry properties that the fields were computed with, as well as the unwrapped grid. Then, e.g. FieldData.Ex could return the unwrapped field directly. This can have the advantage for example of always storing the minimum needed data to file.

"""
return Box(center=self.center, size=self.size)

def pop_axis(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I like this.. feel like it clutters things up a bit because it's for such a specific application. How many times is the called and does it make sense to just create the normal_index = size.index(0) and feed to regular pop axis?

Copy link
Collaborator Author

@momchil-flex momchil-flex Feb 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used a few times in the frontend and a few times in the backend. It seems to me that almost every time I need to use this, I have a plane that I'm working with, so it seemed weird I have to specifically supply the normal index every time. I almost don't understand why this would be a geometry method if not for some simplifications it can provide for geometries that have a natural normal axis...

Copy link
Collaborator

@tylerflex tylerflex Feb 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, like you say, it's used in situations where there is a natural normal axis, like cylinders and poly slabs. But note these are not toggled via size. It's also used to compute intersections and polygons in various planes (where the plane axis is specified). So my point is that these functions are pretty generically used and I would prefer to not hardcode something for a special case if we dont have to. If it were me I'd just construct and feed it the normal axis. Or, I might try to handle it a bit differently (like define a normal_axis property in each Geometry that returns a value used as a default in pop / unpop axis.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I can partly understand your resistance to this, but firstly note that the change I made doesn't brake anything as the size selection is only triggered if axis is not supplied. There are two things that feel kinda strange to me: the first is that you have to manually define the normal axis every time even for geometries that have a natural normal axis. The second one is that it's not really clear why the method as such (staticmethod) belongs in the Geometry class (perhaps the best justification is that we don't really have hanging functions in something like a utils module). But I actually like your idea about defining a normal_axis property! This can be set to the smallest size for a Box and the extrusion direction for Cylinders and Polyslabs. Then we only need to change the Geometry pop/unpop methods to allow axis=None, and raise an error if axis == None and self.normal_aixs == None (e.g. for a sphere). What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To your first point, it's because you dont always supply a normal axis to the pop_axis function, it could be anything, like the plot axis or whatever. Point is that it's generic and doesn't care about the context it's being called in.

It might not belong in the Geometry class, it only does because I feel like it's better tied to some class rather than just hanging out in a utils file, and 2nd is that it's really only used for Geometry objects (things that can be plotted, intersected, etc.). Other than that it's an arbitrary choice.

Normal axis property would work like you describe yea, but I still am a bit opposed to it unless we can define what a normal axis is and why pop_axis should have it as a default? Is it just going to be a property defining "one of these axes is not like the other 2"? for a specific geometry? I'm probably being OCD but just want to think through whether we add this if it's just to avoid a few lines in other places where normal_axis is fed. A nice thing about feeding normal axis is it's more explicit and readable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it just going to be a property defining "one of these axes is not like the other 2"? for a specific geometry?

Pretty much, yeah. It seems you already have something like that actually: Planar, where pop_axis is called several times with self.axis.

I'm probably being OCD but just want to think through whether we add this if it's just to avoid a few lines in other places where normal_axis is fed. A nice thing about feeding normal axis is it's more explicit and readable.

This is not a hill I want to have a long discussion on. I can revert the change. It seems that in my usage it was always tied to a plane so it felt weird to have to supply the normal every time, but I see how it's used in the plotting functions. I mean, I didn't get your point to my first point - what I was saying is that everywhere in the code up to now the axis is specifically supplied, so my change doesn't break anything. But I also see that it's not great the way it is now. So between making a normal_axis property for all geometry and just reverting the change, I'm fine with reverting.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, yea if you dont mind reverting that would make me most happy :). But we can revisit this issue. What makes me feel a bit icky is adding specific behavior (like checking size) to this more generic, core function that is used in a bunch of other ways. It wouldn't break anything, but I also have been trying to avoid this out of principle in the code design (similar idea to how the components should not depend on the plugins).

Copy link
Collaborator

@tylerflex tylerflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few comments. Looks overall good

""" Validating setup """

@pydantic.validator("symmetry", always=True)
def not_supported_yet(cls, val):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so as of this PR symmetry is only supported for mode computation? Or am I missing something?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we should edit the docstring for Simulation.symmetry temporarily?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I am still hoping to get the main symmetries done in the next couple days... Sooo no need?

"is completely outside of simulation domain."
)

if geometric_object.type in ["ModeSource", "ModeMonitor"]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this should be a separate validator?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it can be yeah

@tylerflex tylerflex merged commit 60bdb9a into develop Feb 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants