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

Unclear documentation for GetFieldsOnGrid method #94

Open
JamesWhitehead5 opened this issue Dec 10, 2020 · 1 comment
Open

Unclear documentation for GetFieldsOnGrid method #94

JamesWhitehead5 opened this issue Dec 10, 2020 · 1 comment

Comments

@JamesWhitehead5
Copy link

Issue

When testing a simulation with a non-zero polar angle of the excitation planewave of a single "vacuum" layer, the returned field from calling the GetFieldsOnGrid is spatially uniform in magnitude and phase.
(Tested on the current OSX lua binary and an old python api compiled from source)

However, sampling the field on a grid (that is normal to the z axis) using the GetFields method yields the expected results for a plane wave incident at an angle.

A possible explanation is that GetFieldsOnGrid returns the field parallel to the incident plane wave.
If this were the case, then the documentation does not reflect this.

Replication of issue (Python2.7)

import S4
import matplotlib.pyplot as plt
import numpy as np


def setup_simulation(period, wavelength, layer_thickness):
    simulation = S4.New(Lattice=((period, 0.), (0., period)), NumBasis=100) #setup lattice
    simulation.SetMaterial(Name='vacuum', Epsilon=complex(1.)) # create material
    simulation.AddLayer(Name='buffer_top', Thickness=layer_thickness, Material='vacuum') #add layer
        
    simulation.SetExcitationPlanewave(
        IncidenceAngles=(30., 0.), # polar angle is non-normal
        sAmplitude=0.,
        pAmplitude=1.,
        Order = 0,
    )
    simulation.SetFrequency(1./wavelength)
    return simulation

def get_fields_on_grid_default_method(simulation, n_samples):
    """Uses the GetFieldsOnGrid method to get the grid"""
    electric_field, _ = simulation.GetFieldsOnGrid(z=0., NumSamples=(n_samples, n_samples), Format='Array')
    electric_field = np.array(electric_field)
    electric_field_x_component = electric_field[:, :, 0]
    return electric_field_x_component

def get_fields_on_grid_sample_method(simulation, n_samples, period):
    """Uses the GetFields method to get the grid"""
    x = np.linspace(-period/2, period/2, n_samples)
    X, Y = np.meshgrid(x, x)
    
    def getExField(x, y, z):
        """
        x, y, z are floats where the field should be measured
        Returns the x componenet of the electric field at point (x, y, z)
        """
        electric_field, _ = simulation.GetFields(x, y, z)
        electric_field_x_component, _, _ = electric_field
        return electric_field_x_component
    
    # allows us to pass a numpy.array as argument so we don't have to loop over each element
    get_electric_field_x_component = np.vectorize(getExField) 
    
    electric_field_x_component = get_electric_field_x_component(X, Y, z=0)
    return electric_field_x_component
    
def plot_mag_phase(scalar_field, title):
    fig, (ax1, ax2) = plt.subplots(1, 2)
    fig.suptitle(title)
    
    plot1 = ax1.imshow(np.abs(scalar_field))
    ax1.set_title("Mag")
    fig.colorbar(plot1, ax=ax1)
    
    plot2 = ax2.imshow(np.angle(scalar_field))
    ax2.set_title("Phase")
    fig.colorbar(plot2, ax=ax2)
    
    plt.show()
    
if __name__ == '__main__':
    n_samples = 50
    period = 1.
    simulation = setup_simulation(period, wavelength=1., layer_thickness=1.)
    
    fields_on_grid_default_method = get_fields_on_grid_default_method(simulation, n_samples)
    fields_on_grid_sample_method = get_fields_on_grid_sample_method(simulation, n_samples, period)

    plot_mag_phase(fields_on_grid_default_method,"fields_on_grid_default_method")
    plot_mag_phase(fields_on_grid_sample_method,"fields_on_grid_sample_method")

Solution

If this behavior is intended, then adding documentation to the API entry GetFieldsOnGrid would fix this issue.

@kwrobert
Copy link

Hi there!

Unfortunately, I think this is actually a bug in the GetFieldsOnGrid method. Long ago, during my masters degree, I recall running into the same issue you're seeing here (a symptom of which is, the z-components of the field come out wrong for anything not normally incident). I fixed it while I was using this code. Nowadays, I think this fork of S4 is the most actively maintained fork by brilliant scientists who share their work openly.

I recommend using that fork. It's been modernized and cleaned up a lot.

Hope that helps!

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

No branches or pull requests

2 participants