Example #1
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

        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
Example #2
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

        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
Example #3
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)
Example #4
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)
Example #5
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]