class NTFF(object): def __init__(self, function_space, testing_space=None): self.function_space = function_space if testing_space is None: testing_space = function_space self.testing_space = testing_space self.functional = CalcEMFunctional(function_space, testing_space) self.testing_interpolator = SurfaceInterpolant(testing_space) self.cell_domains = dolfin.CellFunction('uint', self.function_space.mesh()) self.cell_domains.set_all(0) self.cell_region = 1 boundary_cells = Geometry.BoundaryEdgeCells(self.function_space.mesh()) boundary_cells.mark(self.cell_domains, self.cell_region) self.surface_forms = SurfaceNTFFForms(self.function_space) self.testing_expression_gen = TransformTestingExpression() self.functional.set_cell_domains(self.cell_domains, self.cell_region) def set_k0(self, k0): self.k0 = k0 self.functional.set_k0(k0) def set_frequency(self, frequency): self.frequency = frequency self.set_k0(self.frequency * 2 * np.pi / c0) def set_dofs(self, dofs): self.functional.set_E_dofs(dofs) self.surface_forms.set_dofs(dofs) def calc_pt(self, theta_deg, phi_deg): # H-field contribution using variational calculation E_H_theta, E_H_phi = self.calc_pt_E_H(theta_deg, phi_deg) theta = np.deg2rad(theta_deg) phi = np.deg2rad(phi_deg) self.surface_forms.set_parms(theta, phi, self.k0) L_theta, L_phi = self.surface_forms.assemble_L() #------------------------------ # Calculate the far fields normalised to radius 1. r_fac = 1j * self.k0 * np.exp(-1j * self.k0) / (4 * np.pi) E_theta = r_fac * (-L_phi + E_H_theta) E_phi = r_fac * (L_theta + E_H_phi) return (E_theta, E_phi) def calc_pt_E_H(self, theta_deg, phi_deg): theta = np.deg2rad(theta_deg) phi = np.deg2rad(phi_deg) rhat = np.array([ np.sin(theta) * np.cos(phi), np.sin(theta) * np.sin(phi), np.cos(theta) ], dtype=np.float64) theta_hat = np.array([ np.cos(theta) * np.cos(phi), np.cos(theta) * np.sin(phi), -np.sin(theta) ], dtype=np.float64) phi_hat = np.array([-np.sin(phi), np.cos(phi), 0.], dtype=np.float64) E_H_theta = self.calc_ff_func(rhat, theta_hat) E_H_phi = self.calc_ff_func(rhat, phi_hat) return E_H_theta, E_H_phi def calc_ff_func(self, rhat, ahat): self.testing_expression_gen.set_parms(rhat, ahat, self.k0) fit_expr_r, fit_expr_i = self.testing_expression_gen.get_expression() self.testing_interpolator.set_interpolant_expression( fit_expr_r, fit_expr_i) g_dofs = self.testing_interpolator.calculate_interpolation() self.functional.set_g_dofs(g_dofs) return self.functional.calc_functional()
class VariationalSurfaceFlux(object): def __init__(self, function_space): self.function_space = V = function_space self.E_r = dolfin.Function(V) self.E_i = dolfin.Function(V) self.mur_function = None self.epsr_function = None ## Set CalcEMCalcEMFunctional to only integrate along a skin ## of elements connected to the boundary boundary_cells = Geometry.BoundaryEdgeCells(V.mesh()) cell_domains = dolfin.CellFunction('uint', V.mesh()) cell_domains.set_all(0) cell_region = 1 boundary_cells.mark(cell_domains, cell_region) self.functional = CalcEMFunctional(V) self.functional.set_cell_domains(cell_domains, cell_region) self.k0_dirty = True def set_dofs(self, dofs): x_r = np.real(dofs).copy() x_i = np.imag(dofs).copy() self.E_r.vector()[:] = x_r self.E_i.vector()[:] = x_i self.dofs = dofs boundary = dolfin.DomainBoundary() E_r_dirich = dolfin.DirichletBC(self.function_space, self.E_r, boundary) E_i_dirich = dolfin.DirichletBC(self.function_space, self.E_i, boundary) x_r_dirich = as_dolfin_vector(np.zeros(len(x_r))) x_i_dirich = as_dolfin_vector(np.zeros(len(x_r))) E_r_dirich.apply(x_r_dirich) E_i_dirich.apply(x_i_dirich) self.dirich_dofs = x_r_dirich.array() + 1j * x_i_dirich.array() self.functional.set_E_dofs(dofs) def set_k0(self, k0): self.k0 = k0 self.functional.set_k0(k0) self.k0_dirty = True def set_epsr_function(self, epsr_function): self.epsr_function = epsr_function self.functional.set_epsr_function(epsr_function) def set_mur_function(self, mur_function): self.mur_function = mur_function self.functional.set_mur_function(mur_function) def calc_flux(self): if self.k0_dirty: self.functional.set_g_dofs(1j * self.dirich_dofs.conjugate() / self.k0 / Z0) self.k0_dirty = False return self.functional.calc_functional().conjugate() def _get_mur_function(self): if self.epsr_function is not None: mur_func = self.mur_function else: mur_func = dolfin.Constant(1) return mur_func def _get_epsr_function(self): if self.epsr_function is not None: epsr_func = self.epsr_function else: epsr_func = dolfin.Constant(1) return epsr_func
def calcs(fname): data = pickle.load(open(fname+'.pickle')) mesh = dolfin.Mesh(data['meshfile']) elen = np.array([e.length() for e in dolfin.edges(mesh)]) ave_elen = np.average(elen) material_meshfn = dolfin.MeshFunction('uint', mesh, data['materialsfile']) V = dolfin.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", data['order']) x = data['x'] x_r = as_dolfin_vector(x.real) x_i = as_dolfin_vector(x.imag) E_r = dolfin.Function(V, x_r) E_i = dolfin.Function(V, x_i) k0 = 2*np.pi*data['freq']/c0 n = V.cell().n ReS = (1/k0/Z0)*dolfin.dot(n, (dolfin.cross(E_r, -dolfin.curl(E_i)) + dolfin.cross(E_i, dolfin.curl(E_r))))*dolfin.ds energy_flux = dolfin.assemble(ReS) surface_flux = SurfaceFlux(V) surface_flux.set_dofs(x) surface_flux.set_k0(k0) energy_flux2 = surface_flux.calc_flux() assert(np.allclose(energy_flux, energy_flux2, rtol=1e-8, atol=1e-8)) def boundary(x, on_boundary): return on_boundary E_r_dirich = dolfin.DirichletBC(V, E_r, boundary) x_r_dirich = as_dolfin_vector(np.zeros(len(x))) E_r_dirich.apply(x_r_dirich) E_i_dirich = dolfin.DirichletBC(V, E_i, boundary) x_i_dirich = as_dolfin_vector(np.zeros(len(x))) E_i_dirich.apply(x_i_dirich) x_dirich = x_r_dirich.array() + 1j*x_i_dirich.array() emfunc = CalcEMFunctional(V) emfunc.set_k0(k0) cell_domains = dolfin.CellFunction('uint', mesh) cell_domains.set_all(0) cell_region = 1 boundary_cells = Geometry.BoundaryEdgeCells(mesh) boundary_cells.mark(cell_domains, cell_region) emfunc.set_cell_domains(cell_domains, cell_region) emfunc.set_E_dofs(x) emfunc.set_g_dofs(1j*x_dirich.conjugate()/k0/Z0) var_energy_flux = emfunc.calc_functional().conjugate() var_surf_flux = VariationalSurfaceFlux(V) var_surf_flux.set_dofs(x) var_surf_flux.set_k0(k0) var_energy_flux2 = var_surf_flux.calc_flux() assert(np.allclose(var_energy_flux, var_energy_flux2, rtol=1e-8, atol=1e-8)) complex_voltage = ComplexVoltageAlongLine(V) complex_voltage.set_dofs(x) volts = complex_voltage.calculate_voltage(*data['source_endpoints']) result = dict(h=ave_elen, order=order, volts=volts, sflux=energy_flux, vflux=var_energy_flux) print 'source power: ', volts*data['I'] print 'energy flux: ', energy_flux print 'var energy flux: ', var_energy_flux # print '|'.join(str(s) for s in ('', volts*data['I'], energy_flux, # var_energy_flux, '')) return result
class VariationalSurfaceFlux(object): def __init__(self, function_space): self.function_space = V = function_space self.E_r = dolfin.Function(V) self.E_i = dolfin.Function(V) self.mur_function = None self.epsr_function = None ## Set CalcEMCalcEMFunctional to only integrate along a skin ## of elements connected to the boundary boundary_cells = Geometry.BoundaryEdgeCells(V.mesh()) cell_domains = dolfin.CellFunction('uint', V.mesh()) cell_domains.set_all(0) cell_region = 1 boundary_cells.mark(cell_domains, cell_region) self.functional = CalcEMFunctional(V) self.functional.set_cell_domains(cell_domains, cell_region) self.k0_dirty = True def set_dofs(self, dofs): x_r = np.real(dofs).copy() x_i = np.imag(dofs).copy() self.E_r.vector()[:] = x_r self.E_i.vector()[:] = x_i self.dofs = dofs boundary = dolfin.DomainBoundary() E_r_dirich = dolfin.DirichletBC( self.function_space, self.E_r, boundary) E_i_dirich = dolfin.DirichletBC( self.function_space, self.E_i, boundary) x_r_dirich = as_dolfin_vector(np.zeros(len(x_r))) x_i_dirich = as_dolfin_vector(np.zeros(len(x_r))) E_r_dirich.apply(x_r_dirich) E_i_dirich.apply(x_i_dirich) self.dirich_dofs = x_r_dirich.array() + 1j*x_i_dirich.array() self.functional.set_E_dofs(dofs) def set_k0(self,k0): self.k0 = k0 self.functional.set_k0(k0) self.k0_dirty = True def set_epsr_function(self, epsr_function): self.epsr_function = epsr_function self.functional.set_epsr_function(epsr_function) def set_mur_function(self, mur_function): self.mur_function = mur_function self.functional.set_mur_function(mur_function) def calc_flux(self): if self.k0_dirty: self.functional.set_g_dofs(1j*self.dirich_dofs.conjugate()/self.k0/Z0) self.k0_dirty = False return self.functional.calc_functional().conjugate() def _get_mur_function(self): if self.epsr_function is not None: mur_func = self.mur_function else: mur_func = dolfin.Constant(1) return mur_func def _get_epsr_function(self): if self.epsr_function is not None: epsr_func = self.epsr_function else: epsr_func = dolfin.Constant(1) return epsr_func
class NTFF(object): def __init__(self, function_space, testing_space=None): self.function_space = function_space if testing_space is None: testing_space = function_space self.testing_space = testing_space self.functional = CalcEMFunctional(function_space, testing_space) self.testing_interpolator = SurfaceInterpolant(testing_space) self.cell_domains = dolfin.CellFunction('uint', self.function_space.mesh()) self.cell_domains.set_all(0) self.cell_region = 1 boundary_cells = Geometry.BoundaryEdgeCells(self.function_space.mesh()) boundary_cells.mark(self.cell_domains, self.cell_region) self.surface_forms = SurfaceNTFFForms(self.function_space) self.testing_expression_gen = TransformTestingExpression() self.functional.set_cell_domains(self.cell_domains, self.cell_region) def set_k0(self, k0): self.k0 = k0 self.functional.set_k0(k0) def set_frequency(self, frequency): self.frequency = frequency self.set_k0(self.frequency*2*np.pi/c0) def set_dofs(self, dofs): self.functional.set_E_dofs(dofs) self.surface_forms.set_dofs(dofs) def calc_pt(self, theta_deg, phi_deg): # H-field contribution using variational calculation E_H_theta, E_H_phi = self.calc_pt_E_H(theta_deg, phi_deg) theta = np.deg2rad(theta_deg) phi = np.deg2rad(phi_deg) self.surface_forms.set_parms(theta, phi, self.k0) L_theta, L_phi = self.surface_forms.assemble_L() #------------------------------ # Calculate the far fields normalised to radius 1. r_fac = 1j*self.k0*np.exp(-1j*self.k0)/(4*np.pi) E_theta = r_fac*(-L_phi + E_H_theta) E_phi = r_fac*(L_theta + E_H_phi) return (E_theta, E_phi) def calc_pt_E_H(self, theta_deg, phi_deg): theta = np.deg2rad(theta_deg) phi = np.deg2rad(phi_deg) rhat = np.array([np.sin(theta)*np.cos(phi), np.sin(theta)*np.sin(phi), np.cos(theta)], dtype=np.float64) theta_hat = np.array([np.cos(theta)*np.cos(phi), np.cos(theta)*np.sin(phi), -np.sin(theta)], dtype=np.float64) phi_hat = np.array([-np.sin(phi), np.cos(phi), 0.], dtype=np.float64) E_H_theta = self.calc_ff_func(rhat, theta_hat) E_H_phi = self.calc_ff_func(rhat, phi_hat) return E_H_theta, E_H_phi def calc_ff_func(self, rhat, ahat): self.testing_expression_gen.set_parms(rhat, ahat, self.k0) fit_expr_r, fit_expr_i = self.testing_expression_gen.get_expression() self.testing_interpolator.set_interpolant_expression(fit_expr_r, fit_expr_i) g_dofs = self.testing_interpolator.calculate_interpolation() self.functional.set_g_dofs(g_dofs) return self.functional.calc_functional()