Calculator.py
def compute_field_profile(self,freq,q,a=1.,distance_into_entrance=0,distance_into_exit=0,num_sample=1000,subtract_incident_field=True,normalized=True):
        """Calculate the numerical values of E field (z direction) profile, E field (x direction) profile, and H field (y direction) profile. 
        
        Field profile means the value of the field as a function of z position, with z axis normal to interface.
        
        Note: in order to propagate from entrance to exit, due to the formulation used in this code, we need to use
        the inverse of all the matrices.
        
        Args:
            freq (float): Frequency of incident light; in unit of cm^-1
            q (float): In-plane momentum of incident light; in unit of cm^-1
            a (float): magnitude of incident H field
            distance_into_entrance (float): distance of profile before entrance; in unit of cm
            distance_into_exit (float): distance of profile after exit; in unit of cm
            num_sample: number of position to sample fields
            
        Return:
            void
        
        """
        #Compute parameters needed for calculating fields
        self.assemble_analytical_reflection_coefficient()
        b=self.get_numerical_reflection_coefficient(freq,q)*a
        T = self.transferMatrix
        H_0 = np.matrix([[a],[b]])      #H0 is the magnetic field right before the entrance interface
        H_profile = []
        Ex_profile = []
        Ez_profile = []
        omega = 2*np.pi*freq
        
        #Compute parameters related to position of interfaces
        interface_position_list = self._get_interface_position_list_()
        thickness = interface_position_list[-1]+distance_into_entrance+distance_into_exit
        interface_index = 1    # the index of the next interface
        if len(interface_position_list)>1:
            next_interface_position = interface_position_list[interface_index]
        step_size = thickness/(num_sample-1)
        positionArray = np.linspace(-distance_into_entrance,interface_position_list[-1]+distance_into_exit,num=int(num_sample))
        
        startingIndex = int(distance_into_entrance/step_size)+1
        endingIndex = int(interface_position_list[-1]/step_size)+startingIndex
        
        #Obtain fields inside entrance
        if subtract_incident_field == True:
            H_0 = np.matrix([[0],[b]])      #to calculate only the solution that gets exponentially smaller when farther away from entrance
        for z in positionArray[0:startingIndex]:
            material = T.entrance
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            #backward propagation; note the sign change of the exponent compared to rest of the propagation_matrix in this method
            propagation_matrix = np.matrix([[np.exp(-1j*kz*abs(z)) , 0],
                                            [0 , np.exp(1j*kz*abs(z))]])
            H = propagation_matrix*H_0
            H_profile, Ex_profile, Ez_profile = self._update_fields_profile_(H_profile,Ex_profile, Ez_profile, material, H, freq, q)
        
        #Obtain interface fields
        H_0 = np.matrix([[a],[b]])
        interface_H_field_array = self._get_interface_H_field_(freq,q,H_0)
        H_at_interface = interface_H_field_array[0]
        
        #Obtain fields inside LayeredMedium
        distance_from_interface = positionArray[startingIndex]
        for z in positionArray[startingIndex:endingIndex]:
        
            floating_error = step_size/1000
            if z-floating_error > next_interface_position:
                
                #go to next interface
                H_at_interface = interface_H_field_array[interface_index]
                interface_index += 1
                distance_from_interface = z-next_interface_position
                next_interface_position = interface_position_list[interface_index]
            
            material = T.layerDictionary['L'+str(interface_index+1)].get_material()
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            propagation_matrix = np.matrix([[np.exp(1j*kz*distance_from_interface) , 0],
                                            [0 , np.exp(-1j*kz*distance_from_interface)]])
        
            H = propagation_matrix*H_at_interface
            H_profile, Ex_profile, Ez_profile = self._update_fields_profile_(H_profile,Ex_profile, Ez_profile, material, H, freq, q)
            distance_from_interface += step_size
        
        # Obtain fields inside exit
        for z in positionArray[endingIndex:]:
            material = T.exit
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            d = z-interface_position_list[-1]
            propagation_matrix = np.matrix([[np.exp(1j*kz*abs(d)) , 0],
                                            [0 , np.exp(-1j*kz*abs(d))]])
            H_exit = interface_H_field_array[-1]
            H = propagation_matrix*H_exit
            H_profile, Ex_profile, Ez_profile = self._update_fields_profile_(H_profile,Ex_profile, Ez_profile, material, H, freq, q)
        
        #Subtract incident field
        if subtract_incident_field == True:
            H_incident_profile = np.zeros(startingIndex)        #The incident field is already removed when propagating into entrance
            Ex_incident_profile = np.zeros(startingIndex)        #The incident field is already removed when propagating into entrance
            Ez_incident_profile = np.zeros(startingIndex)        #The incident field is already removed when propagating into entrance
            for z in positionArray[startingIndex:]:
                propagation_matrix = np.matrix([[np.exp(1j*kz*abs(z)) , 0],
                                                [0 , np.exp(-1j*kz*abs(z))]])
                H_0_subtracted = np.matrix([[a],[0]])
                H = propagation_matrix * H_0_subtracted
                H_incident_profile, Ex_incident_profile, Ez_incident_profile = self._update_fields_profile_(H_incident_profile,Ex_incident_profile, Ez_incident_profile, material, H, freq, q)
                
            H_profile = H_profile - H_incident_profile
            Ex_profile = Ex_profile - Ex_incident_profile
            Ez_profile = Ez_profile - Ez_incident_profile
            
            H0 = b      #omitting the incident direction H field, as subtract_incident_field == True
        
        elif subtract_incident_field == False:
            H0=a+b      #including the incident direction H field, as subtract_incident_field == False
        else:
            Logger.raiseException('Invalid input for argument \'subtract_incident_field\'. Can only be boolean value.', exception=ValueError)
        
        if normalized==True:
            material = T.entrance
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            epsilon = material.epsilon(freq,q)
            epsilon = self._extract_singleton_array_value_(epsilon)
            Ez0 = H0*29979245368*q/(omega*epsilon)
            Ez_profile = Ez_profile/Ez0*b
            Ex0 = H0*29979245368*kz/(omega*epsilon)
            Ex_profile = Ex_profile/Ex0*b
        elif (normalized!=False)&(normalized!=True):
            Logger.raiseException('Invalid input for argument \'normalized\'. Can only be boolean value.', exception=ValueError)
        
        self.Ez_field_profile = AWA(Ez_profile,axes=[positionArray*1e7],axis_names=['distance from entrance (nm)'])
        self.Ex_field_profile = AWA(Ex_profile,axes=[positionArray*1e7],axis_names=['distance from entrance (nm)'])
        self.H_field_profile = AWA(H_profile,axes=[positionArray*1e7],axis_names=['distance from entrance (nm)'])
Calculate the numerical values of E field (z direction) profile, E field (x direction) profile, and H field (y direction) profile. 
        
        Field profile means the value of the field as a function of z position, with z axis normal to interface.
        
        Note: in order to propagate from entrance to exit, due to the formulation used in this code, we need to use
        the inverse of all the matrices.
        
        Args:
            freq (float): Frequency of incident light; in unit of cm^-1
            q (float): In-plane momentum of incident light; in unit of cm^-1
            a (float): magnitude of incident H field
            distance_into_entrance (float): distance of profile before entrance; in unit of cm
            distance_into_exit (float): distance of profile after exit; in unit of cm
            num_sample: number of position to sample fields
            
        Return:
            void
        
        
Calculate the numerical values of E field (z direction) profile, E field (x direction) profile, and H field (y direction) profile.
Field profile means the value of the field as a function of z position, with z axis normal to interface.

in order to propagate from entrance to exit, due to the formulation used in this code, we need to use
the inverse of all the matrices.
Calculate the numerical values of E field ( z direction ) profile E field ( x direction ) profile and H field ( y direction ) profile . Field profile means the value of the field as a function of z position with z axis normal to interface . in order to propagate from entrance to exit due to the formulation used in this code we need to use the inverse of all the matrices .
def compute_field_profile(self,freq,q,a=1.,distance_into_entrance=0,distance_into_exit=0,num_sample=1000,subtract_incident_field=True,normalized=True):
        self.assemble_analytical_reflection_coefficient()
        b=self.get_numerical_reflection_coefficient(freq,q)*a
        T = self.transferMatrix
        H_0 = np.matrix([[a],[b]])      
        H_profile = []
        Ex_profile = []
        Ez_profile = []
        omega = 2*np.pi*freq
        interface_position_list = self._get_interface_position_list_()
        thickness = interface_position_list[-1]+distance_into_entrance+distance_into_exit
        interface_index = 1    
        if len(interface_position_list)>1:
            next_interface_position = interface_position_list[interface_index]
        step_size = thickness/(num_sample-1)
        positionArray = np.linspace(-distance_into_entrance,interface_position_list[-1]+distance_into_exit,num=int(num_sample))
        startingIndex = int(distance_into_entrance/step_size)+1
        endingIndex = int(interface_position_list[-1]/step_size)+startingIndex
        if subtract_incident_field == True:
            H_0 = np.matrix([[0],[b]])      
        for z in positionArray[0:startingIndex]:
            material = T.entrance
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            propagation_matrix = np.matrix([[np.exp(-1j*kz*abs(z)) , 0],
                                            [0 , np.exp(1j*kz*abs(z))]])
            H = propagation_matrix*H_0
            H_profile, Ex_profile, Ez_profile = self._update_fields_profile_(H_profile,Ex_profile, Ez_profile, material, H, freq, q)
        H_0 = np.matrix([[a],[b]])
        interface_H_field_array = self._get_interface_H_field_(freq,q,H_0)
        H_at_interface = interface_H_field_array[0]
        distance_from_interface = positionArray[startingIndex]
        for z in positionArray[startingIndex:endingIndex]:
            floating_error = step_size/1000
            if z-floating_error > next_interface_position:
                H_at_interface = interface_H_field_array[interface_index]
                interface_index += 1
                distance_from_interface = z-next_interface_position
                next_interface_position = interface_position_list[interface_index]
            material = T.layerDictionary['L'+str(interface_index+1)].get_material()
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            propagation_matrix = np.matrix([[np.exp(1j*kz*distance_from_interface) , 0],
                                            [0 , np.exp(-1j*kz*distance_from_interface)]])
            H = propagation_matrix*H_at_interface
            H_profile, Ex_profile, Ez_profile = self._update_fields_profile_(H_profile,Ex_profile, Ez_profile, material, H, freq, q)
            distance_from_interface += step_size
        for z in positionArray[endingIndex:]:
            material = T.exit
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            d = z-interface_position_list[-1]
            propagation_matrix = np.matrix([[np.exp(1j*kz*abs(d)) , 0],
                                            [0 , np.exp(-1j*kz*abs(d))]])
            H_exit = interface_H_field_array[-1]
            H = propagation_matrix*H_exit
            H_profile, Ex_profile, Ez_profile = self._update_fields_profile_(H_profile,Ex_profile, Ez_profile, material, H, freq, q)
        if subtract_incident_field == True:
            H_incident_profile = np.zeros(startingIndex)        
            Ex_incident_profile = np.zeros(startingIndex)        
            Ez_incident_profile = np.zeros(startingIndex)        
            for z in positionArray[startingIndex:]:
                propagation_matrix = np.matrix([[np.exp(1j*kz*abs(z)) , 0],
                                                [0 , np.exp(-1j*kz*abs(z))]])
                H_0_subtracted = np.matrix([[a],[0]])
                H = propagation_matrix * H_0_subtracted
                H_incident_profile, Ex_incident_profile, Ez_incident_profile = self._update_fields_profile_(H_incident_profile,Ex_incident_profile, Ez_incident_profile, material, H, freq, q)
            H_profile = H_profile - H_incident_profile
            Ex_profile = Ex_profile - Ex_incident_profile
            Ez_profile = Ez_profile - Ez_incident_profile
            H0 = b      
        elif subtract_incident_field == False:
            H0=a+b      
        else:
            Logger.raiseException('Invalid input for argument \'subtract_incident_field\'. Can only be boolean value.', exception=ValueError)
        if normalized==True:
            material = T.entrance
            kz = material.get_kz(freq,q)
            kz = self._extract_singleton_array_value_(kz)
            epsilon = material.epsilon(freq,q)
            epsilon = self._extract_singleton_array_value_(epsilon)
            Ez0 = H0*29979245368*q/(omega*epsilon)
            Ez_profile = Ez_profile/Ez0*b
            Ex0 = H0*29979245368*kz/(omega*epsilon)
            Ex_profile = Ex_profile/Ex0*b
        elif (normalized!=False)&(normalized!=True):
            Logger.raiseException('Invalid input for argument \'normalized\'. Can only be boolean value.', exception=ValueError)
        self.Ez_field_profile = AWA(Ez_profile,axes=[positionArray*1e7],axis_names=['distance from entrance (nm)'])
        self.Ex_field_profile = AWA(Ex_profile,axes=[positionArray*1e7],axis_names=['distance from entrance (nm)'])
        self.H_field_profile = AWA(H_profile,axes=[positionArray*1e7],axis_names=['distance from entrance (nm)'])
def compute_field_profile ( self , freq , q , a = 1. , distance_into_entrance = 0 , distance_into_exit = 0 , num_sample = 1000 , subtract_incident_field = True , normalized = True ) : self . assemble_analytical_reflection_coefficient ( ) b = self . get_numerical_reflection_coefficient ( freq , q ) * a T = self . transferMatrix H_0 = np . matrix ( [ [ a ] , [ b ] ] ) H_profile = [ ] Ex_profile = [ ] Ez_profile = [ ] omega = 2 * np . pi * freq interface_position_list = self . _get_interface_position_list_ ( ) thickness = interface_position_list [ - 1 ] + distance_into_entrance + distance_into_exit interface_index = 1 if len ( interface_position_list ) > 1 : next_interface_position = interface_position_list [ interface_index ] step_size = thickness / ( num_sample - 1 ) positionArray = np . linspace ( - distance_into_entrance , interface_position_list [ - 1 ] + distance_into_exit , num = int ( num_sample ) ) startingIndex = int ( distance_into_entrance / step_size ) + 1 endingIndex = int ( interface_position_list [ - 1 ] / step_size ) + startingIndex if subtract_incident_field == True : H_0 = np . matrix ( [ [ 0 ] , [ b ] ] ) for z in positionArray [ 0 : startingIndex ] : material = T . entrance kz = material . get_kz ( freq , q ) kz = self . _extract_singleton_array_value_ ( kz ) propagation_matrix = np . matrix ( [ [ np . exp ( - 1j * kz * abs ( z ) ) , 0 ] , [ 0 , np . exp ( 1j * kz * abs ( z ) ) ] ] ) H = propagation_matrix * H_0 H_profile , Ex_profile , Ez_profile = self . _update_fields_profile_ ( H_profile , Ex_profile , Ez_profile , material , H , freq , q ) H_0 = np . matrix ( [ [ a ] , [ b ] ] ) interface_H_field_array = self . _get_interface_H_field_ ( freq , q , H_0 ) H_at_interface = interface_H_field_array [ 0 ] distance_from_interface = positionArray [ startingIndex ] for z in positionArray [ startingIndex : endingIndex ] : floating_error = step_size / 1000 if z - floating_error > next_interface_position : H_at_interface = interface_H_field_array [ interface_index ] interface_index += 1 distance_from_interface = z - next_interface_position next_interface_position = interface_position_list [ interface_index ] material = T . layerDictionary [ 'L' + str ( interface_index + 1 ) ] . get_material ( ) kz = material . get_kz ( freq , q ) kz = self . _extract_singleton_array_value_ ( kz ) propagation_matrix = np . matrix ( [ [ np . exp ( 1j * kz * distance_from_interface ) , 0 ] , [ 0 , np . exp ( - 1j * kz * distance_from_interface ) ] ] ) H = propagation_matrix * H_at_interface H_profile , Ex_profile , Ez_profile = self . _update_fields_profile_ ( H_profile , Ex_profile , Ez_profile , material , H , freq , q ) distance_from_interface += step_size for z in positionArray [ endingIndex : ] : material = T . exit kz = material . get_kz ( freq , q ) kz = self . _extract_singleton_array_value_ ( kz ) d = z - interface_position_list [ - 1 ] propagation_matrix = np . matrix ( [ [ np . exp ( 1j * kz * abs ( d ) ) , 0 ] , [ 0 , np . exp ( - 1j * kz * abs ( d ) ) ] ] ) H_exit = interface_H_field_array [ - 1 ] H = propagation_matrix * H_exit H_profile , Ex_profile , Ez_profile = self . _update_fields_profile_ ( H_profile , Ex_profile , Ez_profile , material , H , freq , q ) if subtract_incident_field == True : H_incident_profile = np . zeros ( startingIndex ) Ex_incident_profile = np . zeros ( startingIndex ) Ez_incident_profile = np . zeros ( startingIndex ) for z in positionArray [ startingIndex : ] : propagation_matrix = np . matrix ( [ [ np . exp ( 1j * kz * abs ( z ) ) , 0 ] , [ 0 , np . exp ( - 1j * kz * abs ( z ) ) ] ] ) H_0_subtracted = np . matrix ( [ [ a ] , [ 0 ] ] ) H = propagation_matrix * H_0_subtracted H_incident_profile , Ex_incident_profile , Ez_incident_profile = self . _update_fields_profile_ ( H_incident_profile , Ex_incident_profile , Ez_incident_profile , material , H , freq , q ) H_profile = H_profile - H_incident_profile Ex_profile = Ex_profile - Ex_incident_profile Ez_profile = Ez_profile - Ez_incident_profile H0 = b elif subtract_incident_field == False : H0 = a + b else : Logger . raiseException ( 'Invalid input for argument \'subtract_incident_field\'. Can only be boolean value.' , exception = ValueError ) if normalized == True : material = T . entrance kz = material . get_kz ( freq , q ) kz = self . _extract_singleton_array_value_ ( kz ) epsilon = material . epsilon ( freq , q ) epsilon = self . _extract_singleton_array_value_ ( epsilon ) Ez0 = H0 * 29979245368 * q / ( omega * epsilon ) Ez_profile = Ez_profile / Ez0 * b Ex0 = H0 * 29979245368 * kz / ( omega * epsilon ) Ex_profile = Ex_profile / Ex0 * b elif ( normalized != False ) & ( normalized != True ) : Logger . raiseException ( 'Invalid input for argument \'normalized\'. Can only be boolean value.' , exception = ValueError ) self . Ez_field_profile = AWA ( Ez_profile , axes = [ positionArray * 1e7 ] , axis_names = [ 'distance from entrance (nm)' ] ) self . Ex_field_profile = AWA ( Ex_profile , axes = [ positionArray * 1e7 ] , axis_names = [ 'distance from entrance (nm)' ] ) self . H_field_profile = AWA ( H_profile , axes = [ positionArray * 1e7 ] , axis_names = [ 'distance from entrance (nm)' ] )
Calculate the numerical values of E field (z direction) profile, E field (x direction) profile, and H field (y direction) profile.
Calculate the numerical values of E field ( z direction ) profile E field ( x direction ) profile and H field ( y direction ) profile .
"""Calculate the numerical values of E field (z direction) profile, E field (x direction) profile, and H field (y direction) profile. 
        
        Field profile means the value of the field as a function of z position, with z axis normal to interface.
        
        Note: in order to propagate from entrance to exit, due to the formulation used in this code, we need to use
        the inverse of all the matrices.
        
        Args:
            freq (float): Frequency of incident light; in unit of cm^-1
            q (float): In-plane momentum of incident light; in unit of cm^-1
            a (float): magnitude of incident H field
            distance_into_entrance (float): distance of profile before entrance; in unit of cm
            distance_into_exit (float): distance of profile after exit; in unit of cm
            num_sample: number of position to sample fields
            
        Return:
            void
        
        """ #Compute parameters needed for calculating fields #H0 is the magnetic field right before the entrance interface #Compute parameters related to position of interfaces # the index of the next interface #Obtain fields inside entrance #to calculate only the solution that gets exponentially smaller when farther away from entrance #backward propagation; note the sign change of the exponent compared to rest of the propagation_matrix in this method #Obtain interface fields #Obtain fields inside LayeredMedium #go to next interface # Obtain fields inside exit #Subtract incident field #The incident field is already removed when propagating into entrance #The incident field is already removed when propagating into entrance #The incident field is already removed when propagating into entrance #omitting the incident direction H field, as subtract_incident_field == True #including the incident direction H field, as subtract_incident_field == False
self
freq
Frequency of incident light; in unit of cm^-1
Frequency of incident light ; in unit of cm^ - 1
q
In-plane momentum of incident light; in unit of cm^-1
In - plane momentum of incident light ; in unit of cm^ - 1
a
magnitude of incident H field
magnitude of incident H field
distance_into_entrance
distance of profile before entrance; in unit of cm
distance of profile before entrance ; in unit of cm
distance_into_exit
distance of profile after exit; in unit of cm
distance of profile after exit ; in unit of cm
num_sample
number of position to sample fields
number of position to sample fields
subtract_incident_field
normalized