Skip to content
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

WIP: Adjoint poynting flux #1398

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft

Conversation

smartalecH
Copy link
Collaborator

Closes #1307 and #1299.

@smartalecH
Copy link
Collaborator Author

I'm slightly confused by the default behavior of the get_dft_array() routine. Note that the C implementation of get_dft_array() contains two basic steps: grab the DFT fields themselves (process_dft_component()) and format the data array with collapse_array().

meep/src/dft.cpp

Lines 1082 to 1090 in d29f211

cdouble *fields::get_dft_array(dft_fields fdft, component c, int num_freq, int *rank,
size_t dims[3]) {
dft_chunk *chunklists[1];
chunklists[0] = fdft.chunks;
cdouble *array;
direction dirs[3];
process_dft_component(chunklists, 1, num_freq, c, 0, &array, rank, dims, dirs);
return collapse_array(array, rank, dims, dirs, fdft.where);
}

When the user specifies a volume other than a plane/volume (e.g. point or line) and the user is pulling the interpolated fields from the center of each voxel, there's some odd behavior.

For a simple point, process_dft_component() returns a 2x2 array. This array is then passed to collapse_array(), which seems to grab the first point and throw the rest away.

In the case of a line monitor across 10 pixels, process_dft_component() returns a 10x2 array. Again, collapse_array() grabs the first column and throws the rest away.

Is this the expected behavior?

This makes it tricky when trying to use the indices of the DFT array data values for a broadband adjoint source (for both Poynting fluxes and basic Fourier fields).

@smartalecH
Copy link
Collaborator Author

There are two options for placing the adjoint source in this case:

  1. In the C++ code, uncollapse the jacobian passed from python, combine it with all the uncollapsed dft chunk data, and add the result is an index source.
  2. In the python code, use the collapsed dft fields and the collapsed Jacobian to add a source using the amp_data functionality for any arbitrary source. The python source will automatically distribute the fields onto the correct yee grid points (assuming the interpolation is taken into account).

Option 1 is rather difficult -- I don't see a reliable way to uncollapse the Jacobian and map it to the dft fields (which are just stored as sequential indices in the C++ code). Option 2 requires some slight modifications to the amp_data routine, specifically with how the array is interpolated onto the grid.

I implemented option 2 for the broadband Poynting flux (10 frequency points) and got the following result:

Figure_1

The result isn't perfect (1%-10% error) but it's a good start. I've incorporated the interpolation weights into the adjoint scale factor (as we've discussed numerous times) but they only slightly improve the accuracy. Perhaps I still need to take into account the interpolation of the final source object and amp_array routine?

@smartalecH smartalecH marked this pull request as draft October 1, 2021 01:24
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.

Adjoint optimization through Poynting Flux
1 participant