Source code for fibermodes.field

# This file is part of FiberModes.
#
# FiberModes is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# FiberModes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FiberModes.  If not, see <http://www.gnu.org/licenses/>.


"""Electromagnetic fields computation."""

import numpy
from itertools import product
from fibermodes import Wavelength, ModeFamily, HE11
from fibermodes import constants


[docs]class Field(object): """Electromagnetic field representation. Args: fiber(Fiber): Fiber object mode(Mode): Mode wl(Wavelength): Wavelength r(float): Radius of the field to compute. np(int): Number of points (field will be np x np) """ FTYPES = ('Ex', 'Ey', 'Ez', 'Er', 'Ephi', 'Et', 'Epol', 'Emod', 'Hx', 'Hy', 'Hz', 'Hr', 'Hphi', 'Ht', 'Hpol', 'Hmod') def __init__(self, fiber, mode, wl, r, np=101): self.fiber = fiber self.mode = mode self.wl = Wavelength(wl) self.np = np self.xlim = (-r, r) self.ylim = (-r, r) p = numpy.linspace(-r, r, np) self.X, self.Y = numpy.meshgrid(p, p) self.R = numpy.sqrt(numpy.square(self.X) + numpy.square(self.Y)) self.Phi = numpy.arctan2(self.Y, self.X)
[docs] def f(self, phi0): """Azimuthal dependency function. Args: phi0(float): Phase (rotation) of the field. Returns: 2D array of values (ndarray). Values are between -1 and 1. """ return numpy.cos(self.mode.nu * self.Phi + phi0)
[docs] def g(self, phi0): """Azimuthal dependency function. Args: phi0(float): Phase (rotation) of the field. Returns: 2D array of values (ndarray). Values are between -1 and 1. """ return -numpy.sin(self.mode.nu * self.Phi + phi0)
[docs] def Ex(self, phi=0, theta=0): """x component of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: self._Ex = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Ex[j, i] = er[0] * f[j, i] return self._Ex else: return self.Et(phi, theta) * numpy.cos(self.Epol(phi, theta))
[docs] def Ey(self, phi=0, theta=0): """y component of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: self._Ey = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Ey[j, i] = er[1] * f[j, i] return self._Ey else: return self.Et(phi, theta) * numpy.sin(self.Epol(phi, theta))
[docs] def Ez(self, phi=0, theta=0): """z component of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ self._Ez = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Ez[j, i] = er[2] * f[j, i] return self._Ez
[docs] def Er(self, phi=0, theta=0): """r component of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return (self.Et(phi, theta) * numpy.cos(self.Epol(phi, theta) - self.Phi)) else: self._Er = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Er[j, i] = er[0] * f[j, i] return self._Er
[docs] def Ephi(self, phi=0, theta=0): """phi component of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return (self.Et(phi, theta) * numpy.sin(self.Epol(phi, theta) - self.Phi)) else: self._Ephi = numpy.zeros(self.X.shape) g = self.g(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Ephi[j, i] = er[1] * g[j, i] return self._Ephi
[docs] def Et(self, phi=0, theta=0): """transverse component of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return numpy.sqrt(numpy.square(self.Ex(phi, theta)) + numpy.square(self.Ey(phi, theta))) else: return numpy.sqrt(numpy.square(self.Er(phi, theta)) + numpy.square(self.Ephi(phi, theta)))
[docs] def Epol(self, phi=0, theta=0): """polarization of the transverse E field (in radians). Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return numpy.arctan2(self.Ey(phi, theta), self.Ex(phi, theta)) else: return numpy.arctan2(self.Ephi(phi, theta), self.Er(phi, theta)) + self.Phi
[docs] def Emod(self, phi=0, theta=0): """modulus of the E field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return numpy.sqrt(numpy.square(self.Ex(phi, theta)) + numpy.square(self.Ey(phi, theta)) + numpy.square(self.Ez(phi, theta))) else: return numpy.sqrt(numpy.square(self.Er(phi, theta)) + numpy.square(self.Ephi(phi, theta)) + numpy.square(self.Ez(phi, theta)))
[docs] def Hx(self, phi=0, theta=0): """x component of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: self._Hx = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Hx[j, i] = hr[0] * f[j, i] return self._Hx else: return self.Ht(phi, theta) * numpy.cos(self.Hpol(phi, theta))
[docs] def Hy(self, phi=0, theta=0): """y component of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: self._Hy = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Hy[j, i] = hr[1] * f[j, i] return self._Hy else: return self.Ht(phi, theta) * numpy.sin(self.Hpol(phi, theta))
[docs] def Hz(self, phi=0, theta=0): """z component of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ self._Hz = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Hz[j, i] = hr[2] * f[j, i] return self._Hz
[docs] def Hr(self, phi=0, theta=0): """r component of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return (self.Ht(phi, theta) * numpy.cos(self.Hpol(phi, theta) - self.Phi)) else: self._Hr = numpy.zeros(self.X.shape) f = self.f(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Hr[j, i] = hr[0] * f[j, i] return self._Hr
[docs] def Hphi(self, phi=0, theta=0): """phi component of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return (self.Ht(phi, theta) * numpy.sin(self.Hpol(phi, theta) - self.Phi)) else: self._Hphi = numpy.zeros(self.X.shape) g = self.g(phi) for i, j in product(range(self.np), repeat=2): er, hr = self.fiber._rfield(self.mode, self.wl, self.R[j, i]) self._Hphi[j, i] = hr[1] * g[j, i] return self._Hphi
[docs] def Ht(self, phi=0, theta=0): """transverse component of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return numpy.sqrt(numpy.square(self.Hx(phi, theta)) + numpy.square(self.Hy(phi, theta))) else: return numpy.sqrt(numpy.square(self.Hr(phi, theta)) + numpy.square(self.Hphi(phi, theta)))
[docs] def Hpol(self, phi=0, theta=0): """polarization of the transverse H field (in radians). Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return numpy.arctan2(self.Hy(phi, theta), self.Hx(phi, theta)) else: return numpy.arctan2(self.Hphi(phi, theta), self.Hr(phi, theta)) + self.Phi
[docs] def Hmod(self, phi=0, theta=0): """modulus of the H field. Args: phi: phase (in radians) theta: orientation (in radians) Return: (np x np) numpy array """ if self.mode.family is ModeFamily.LP: return numpy.sqrt(numpy.square(self.Hx(phi, theta)) + numpy.square(self.Hy(phi, theta)) + numpy.square(self.Hz(phi, theta))) else: return numpy.sqrt(numpy.square(self.Hr(phi, theta)) + numpy.square(self.Hphi(phi, theta)) + numpy.square(self.Hz(phi, theta)))
[docs] def Aeff(self): """Estimation of mode effective area. Suppose than r is large enough, such as \|F(r, r)\| = 0. """ modF = self.Emod() dx = (self.xlim[1] - self.xlim[0]) / (self.np - 1) dy = (self.ylim[1] - self.ylim[0]) / (self.np - 1) return (numpy.square(numpy.sum(numpy.square(modF))) / numpy.sum(numpy.power(modF, 4))) * dx * dy
def I(self): neff = self.fiber.neff(HE11, self.wl) nm = self.fiber.neff(self.mode, self.wl) dx = (self.xlim[1] - self.xlim[0]) / (self.np - 1) dy = (self.ylim[1] - self.ylim[0]) / (self.np - 1) return nm / neff * numpy.sum(numpy.square(self.Et())) * dx * dy
[docs] def N(self): """Normalization constant.""" neff = self.fiber.neff(HE11, self.wl) return 0.5 * constants.epsilon0 * neff * constants.c * self.I()
[docs] def S(self): """Pointing vector""" pass