def impedance_single_parts(self, Z, s, part_o, part_s=None): """Calculate a self or mutual impedance matrix at a given complex frequency Parameters ---------- s : complex Complex frequency at which to calculate impedance part_o : SinglePart The observing part, which must be a single part, not a composite part_s : SinglePart, optional The source part, if not specified will default to observing part """ # if source part is not given, default to observer part part_s = part_s or part_o basis_o = self.basis_container[part_o] basis_s = self.basis_container[part_s] eps = self.background_material.epsilon_r(s) mu = self.background_material.epsilon_r(s) normals = basis_o.mesh.surface_normals if not (basis_o.mesh.closed_surface and basis_s.mesh.closed_surface): raise ValueError("CFIE can only be solved for closed objects") if isinstance(basis_o, LinearTriangleBasis): L, S = rwg.impedance_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, part_o == part_s, eps, mu, self.num_singular_terms, self.singularity_accuracy) M, _ = rwg.impedance_curl_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, part_o == part_s, eps, mu, self.num_singular_terms, self.singularity_accuracy, tangential_form=False) else: raise NotImplementedError Z.matrices['L'][part_o, part_s] = L * (mu * mu_0) Z.matrices['S'][part_o, part_s] = S / (eps * epsilon_0) Z.matrices['M'][part_o, part_s] = M
def impedance_single_parts(self, Z, s, part_o, part_s=None): """Calculate a self or mutual impedance matrix at a given complex frequency Parameters ---------- s : complex Complex frequency at which to calculate impedance part_o : SinglePart The observing part, which must be a single part, not a composite part_s : SinglePart, optional The source part, if not specified will default to observing part """ # if source part is not given, default to observer part part_s = part_s or part_o basis_o = self.basis_container[part_o] basis_s = self.basis_container[part_s] eps = self.background_material.epsilon_r(s) mu = self.background_material.epsilon_r(s) normals = basis_o.mesh.surface_normals if not (basis_o.mesh.closed_surface and basis_s.mesh.closed_surface): raise ValueError("CFIE can only be solved for closed objects") if isinstance(basis_o, LinearTriangleBasis): L, S = rwg.impedance_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, part_o == part_s, eps, mu, self.num_singular_terms, self.singularity_accuracy) M, _ = rwg.impedance_curl_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, part_o == part_s, eps, mu, self.num_singular_terms, self.singularity_accuracy, tangential_form=False) else: raise NotImplementedError Z.matrices['L'][part_o, part_s] = L*(mu*mu_0) Z.matrices['S'][part_o, part_s] = S/(eps*epsilon_0) Z.matrices['M'][part_o, part_s] = M
def impedance_single_parts(self, Z, s, part_o, part_s): """Calculate a self or mutual impedance matrix at a given complex frequency Parameters ---------- s : complex Complex frequency at which to calculate impedance part_o : SinglePart The observing part, which must be a single part, not a composite part_s : SinglePart, optional The source part, if not specified will default to observing part """ basis_o = self.basis_container[part_o] basis_s = self.basis_container[part_s] eps = self.background_material.epsilon_r(s) mu = self.background_material.epsilon_r(s) normals = basis_o.mesh.surface_normals if isinstance(basis_o, LinearTriangleBasis): res = rwg.impedance_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, part_o == part_s, eps, mu, self.num_singular_terms, self.singularity_accuracy, True) else: raise NotImplementedError L, S, dL_ds, dS_ds = res Z.matrices['L'][part_o, part_s] = L * (mu * mu_0) Z.matrices['S'][part_o, part_s] = S / (eps * epsilon_0) Z.der['L'][part_o, part_s] = dL_ds * (mu * mu_0) Z.der['S'][part_o, part_s] = dS_ds / (eps * epsilon_0)
def impedance_single_parts(self, Z, s, part_o, part_s): """Calculate a self or mutual impedance matrix at a given complex frequency Parameters ---------- s : complex Complex frequency at which to calculate impedance part_o : SinglePart The observing part, which must be a single part, not a composite part_s : SinglePart, optional The source part, if not specified will default to observing part """ basis_o = self.basis_container[part_o] basis_s = self.basis_container[part_s] eps = self.background_material.epsilon_r(s) mu = self.background_material.epsilon_r(s) normals = basis_o.mesh.surface_normals if isinstance(basis_o, LinearTriangleBasis): res = rwg.impedance_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, part_o == part_s, eps, mu, self.num_singular_terms, self.singularity_accuracy, True) else: raise NotImplementedError L, S, dL_ds, dS_ds = res Z.matrices['L'][part_o, part_s] = L*(mu*mu_0) Z.matrices['S'][part_o, part_s] = S/(eps*epsilon_0) Z.der['L'][part_o, part_s] = dL_ds*(mu*mu_0) Z.der['S'][part_o, part_s] = dS_ds/(eps*epsilon_0)
def impedance_single_parts(self, Z, s, part_o, part_s=None): """Calculate a self or mutual impedance matrix at a given complex frequency. Note that this abstract function should be called by sub-classes, not by the user. Parameters ---------- s : complex Complex frequency at which to calculate impedance part_o : SinglePart The observing part, which must be a single part, not a composite part_s : SinglePart, optional The source part, if not specified will default to observing part """ # TODO: Handle the mutual impedance case # if source part is not given, default to observer part part_s = part_s or part_o basis_o = self.basis_container[part_o] basis_s = self.basis_container[part_s] normals = basis_o.mesh.surface_normals if not (basis_o.mesh.closed_surface and basis_s.mesh.closed_surface): raise ValueError("Penetrable objects must be closed") # TODO: fix this for mutual impedance terms eps_i = part_s.material.epsilon_r(s) eps_o = self.background_material.epsilon_r(s) mu_i = part_s.material.mu_r(s) mu_o = self.background_material.mu_r(s) c_i = c/np.sqrt(eps_i*mu_i) c_o = c/np.sqrt(eps_o*mu_o) is_self_term = part_o == part_s matrix_names = ('L_o', 'S_o', 'K_o') if isinstance(basis_o, LinearTriangleBasis): if is_self_term: res = rwg.impedance_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, -normals, is_self_term, eps_i, mu_i, self.num_singular_terms, self.singularity_accuracy) L_i = res[0]/c_i*eta_0 S_i = res[1]*c_i*eta_0 # note opposite sign of normals for interior problem res = rwg.impedance_curl_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, -normals, is_self_term, eps_i, mu_i, self.num_singular_terms, self.singularity_accuracy, tangential_form=True) K_i = res[0]*eta_0 matrix_names += ('L_i', 'S_i', 'K_i') res = rwg.impedance_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, is_self_term, eps_o, mu_o, self.num_singular_terms, self.singularity_accuracy) # This scaling ensures that this operator has the same definition # as cursive D defined by Yla-Oijala, Radio Science 2005. L_o = res[0]/c_o*eta_0 S_o = res[1]*c_o*eta_0 res = rwg.impedance_curl_G(s, self.integration_rule, basis_o, part_o.nodes, basis_s, part_s.nodes, normals, is_self_term, eps_o, mu_o, self.num_singular_terms, self.singularity_accuracy, tangential_form=True) K_o = res[0]*eta_0 else: raise NotImplementedError # Build the matrices and metadata for creating the impedance matrix # object from the locally defined variables. This relies on them having # the correct name in this function. loc = locals() for name in matrix_names: Z.matrices[name][part_o, part_s] = loc[name]