Exemplo n.º 1
0
def test_indexing():
    "Basic test for array indexing"

    sim = openmodes.Simulation()
    mesh = sim.load_mesh(osp.join(openmodes.geometry_dir, "SRR.geo"))

    group1 = sim.place_part()
    group2 = sim.place_part()

    srr1 = sim.place_part(mesh, parent=group1)
    srr2 = sim.place_part(mesh, parent=group1)
    srr3 = sim.place_part(mesh, parent=group2)

    basis = sim.basis_container[srr1]
    basis_len = len(basis)

    A = LookupArray(
        ((group1, sim.basis_container), (group2, sim.basis_container), 5, 3))

    assert (A.shape == (2 * basis_len, basis_len, 5, 3))

    A[group1, srr3] = 22.5
    assert (np.all(A[srr1, :] == 22.5))
    assert (np.all(A[srr2] == 22.5))

    V = LookupArray((("E", "H"), (sim.parts, sim.basis_container)),
                    dtype=np.complex128)

    V["E", group1] = -4.7 + 22j
    V["H", srr1] = 5.2
    V["H", srr2] = 6.7

    assert (np.all(V["E", group1] == V["E"][group1]))
    assert (np.all(V["E", srr1] == -4.7 + 22j))
    assert (np.all(V["E", srr2].imag == 22))
Exemplo n.º 2
0
 def val(self):
     "The value of the impedance matrix"
     Z = LookupArray(
         (self.sources, (self.part_o, self.basis_container), self.unknowns,
          (self.part_s, self.basis_container)),
         dtype=np.complex128)
     Z.simple_view()[:] = self.matrices['Z']
     return Z
Exemplo n.º 3
0
 def val(self):
     "The value of the impedance matrix"
     s = self.md['s']
     Z = LookupArray((self.sources, (self.part_o, self.basis_container),
                      self.unknowns, (self.part_s, self.basis_container)),
                     dtype=np.complex128)
     Z.simple_view()[:] = self.matrices['S']/s + s*self.matrices['L']
     return Z
Exemplo n.º 4
0
 def val(self):
     "The value of the impedance matrix"
     s = self.md['s']
     alpha = self.md['alpha']
     Z = LookupArray(
         (self.sources, (self.part_o, self.basis_container), self.unknowns,
          (self.part_s, self.basis_container)),
         dtype=np.complex128)
     Z.simple_view()[:] = (
         alpha * (self.matrices['S'] / s + s * self.matrices['L']) +
         (1.0 - alpha) * self.matrices['M'])
     return Z
Exemplo n.º 5
0
 def s(self):
     res = LookupArray(
         (('modes', ), (self.parent_part, self.macro_container)),
         dtype=np.complex128)
     for part in self.parts:
         res[:, part] = self.modes_of_parts[part.unique_id]['s']
     return res
Exemplo n.º 6
0
    def solve(self, vec):
        """Solve the impedance matrix for a source vector. Caches the
        factorised matrix for efficiently solving multiple vectors"""
        if self.part_o != self.part_s:
            raise ValueError("Can only invert a self-impedance matrix")

        Z_lu = self.factored()
        if isinstance(vec, LookupArray):
            vec = vec.simple_view()

        lookup = (self.unknowns, (self.part_s, self.basis_container))

        if len(vec.shape) > 1:
            lookup = lookup + (vec.shape[1], )

        I = LookupArray(lookup, dtype=np.complex128)
        I_simp = I.simple_view()
        I_simp[:] = la.lu_solve(Z_lu, vec)
        return I
Exemplo n.º 7
0
    def solve(self, vec):
        """Solve the impedance matrix for a source vector. Caches the
        factorised matrix for efficiently solving multiple vectors"""
        if self.part_o != self.part_s:
            raise ValueError("Can only invert a self-impedance matrix")

        Z_lu = self.factored()
        if isinstance(vec, LookupArray):
            vec = vec.simple_view()

        lookup = (self.unknowns, (self.part_s, self.basis_container))

        if len(vec.shape) > 1:
            lookup = lookup+(vec.shape[1],)

        I = LookupArray(lookup, dtype=np.complex128)
        I_simp = I.simple_view()
        I_simp[:] = la.lu_solve(Z_lu, vec)
        return I
Exemplo n.º 8
0
    def __init__(self,
                 part_o,
                 part_s,
                 basis_container,
                 sources,
                 unknowns,
                 metadata=None,
                 matrices=None,
                 derivatives=None):
        self.md = metadata or dict()
        self.part_o = part_o
        self.part_s = part_s
        self.basis_container = basis_container
        self.sources = sources
        self.unknowns = unknowns

        # Note that the internal LookupArray format is different from the
        # final format as it excludes the quantity lookup.
        self.matrices = {
            name: LookupArray(
                ((part_o, basis_container), (part_s, basis_container)),
                dtype=np.complex128)
            for name in self.matrix_names
        }

        if matrices is not None:
            # fill out any matrices which are supplied
            for name, mat in list(matrices.items()):
                self.matrices[name][:] = mat

        # create the frequency derivatives of the matrices
        if derivatives is None:
            self.der = {
                name: LookupArray(((
                    part_o,
                    basis_container,
                ), (part_s, basis_container)),
                                  dtype=np.complex128)
                for name in self.matrix_names
            }
        else:
            self.der = derivatives
Exemplo n.º 9
0
    def source_vector(self, source_field, s, parent, extinction_field):
        "Calculate the relevant source vector for this operator"

        V = LookupArray((("E"), (parent, self.basis_container)),
                        dtype=np.complex128)

        for part in parent.iter_single():
            V["E", part] = self.source_single_part(source_field, s, part,
                                                   extinction_field)

        return V
Exemplo n.º 10
0
 def gram_matrix(self, part):
     """Create a Gram matrix as a LookupArray"""
     G = self.basis_container[part].gram_matrix
     Gp = LookupArray(
         (self.unknowns, (part, self.basis_container), self.sources,
          (part, self.basis_container)),
         dtype=G.dtype)
     Gp[:] = 0.0
     for unknown, source in zip(self.unknowns, self.sources):
         Gp[unknown, :, source, :] = G
     return Gp
Exemplo n.º 11
0
    def source_vector(self, source_field, s, parent, extinction_field=False):
        "Calculate the relevant source vector for this operator"

        if extinction_field:
            return super(CfieOperator,
                         self).source_vector(source_field, s, parent, True)

        fields = ("E", "nxH")

        V = LookupArray((fields, (parent, self.basis_container)),
                        dtype=np.complex128)

        # define the functions to interpolate over the mesh
        def elec_func(r):
            return source_field.electric_field(s, r)

        def mag_func(r):
            return source_field.magnetic_field(s, r)

        for field in fields:
            if field == "E":
                field_func = elec_func
                source_cross = False
            elif field == "nxH":
                field_func = mag_func
                source_cross = True

            for part in parent.iter_single():
                basis = self.basis_container[part]
                V[field,
                  part] = basis.weight_function(field_func,
                                                self.integration_rule,
                                                part.nodes, source_cross)

        V_final = LookupArray((self.sources, (parent, self.basis_container)),
                              dtype=np.complex128)
        V_final[:] = self.alpha * V["E"] + (1.0 - self.alpha) * V["nxH"]

        return V_final
Exemplo n.º 12
0
    def vr(self):
        "The right eigenvectors"

        res = LookupArray(
            (self.operator.unknowns, (self.parent_part, self.orig_container),
             ('modes', ), (self.parent_part, self.macro_container)),
            dtype=np.complex128)
        res[:] = 0.0

        for part in self.parts:
            res[:, part, :,
                part] = self.modes_of_parts[part.unique_id]['vr'].reshape(
                    res[:, part, :, part].shape)
        return res
Exemplo n.º 13
0
def test_list_indexing():
    "List mucks up LookupArrays, which is now warned about"

    sim = openmodes.Simulation()
    mesh = sim.load_mesh(osp.join(openmodes.geometry_dir, "SRR.geo"))
    srr1 = sim.place_part(mesh)
    srr2 = sim.place_part(mesh)

    res = LookupArray((sim.operator.unknowns, (sim.parts, sim.basis_container),
                       ('modes', ), (srr2, sim.basis_container)),
                      dtype=np.complex128)

    with pytest.warns(UserWarning):
        res[0, :, 0, [2]]
Exemplo n.º 14
0
    def empty_array(self, part=None, extra_dims=()):
        """
        Create an empty array of the appropriate size to contain solutions for
        all of the parts, or a single part and its sub-parts

        Parameters
        ----------
        part : Part, optional
            The part for which to create the vector. If not specified, all
            parts in the full simulation
        extra_dims : tuple, optional
            This can give the sizes of additional dimensions
        """

        part = part or self.parts

        return LookupArray((self.operator.unknowns,
                            (part, self.basis_container)) + extra_dims,
                           dtype=np.complex128)
Exemplo n.º 15
0
    def val(self):
        "The value of the impedance matrix"
        s = self.md['s']
        D_i = s * self.matrices['L_i'] + self.matrices['S_i'] / s
        D_o = s * self.matrices['L_o'] + self.matrices['S_o'] / s
        K_i = self.matrices['K_i']
        K_o = self.matrices['K_o']
        eta_o = self.md['eta_o']
        eta_i = self.md['eta_i']
        w_EFIE_i = self.md['w_EFIE_i']
        w_EFIE_o = self.md['w_EFIE_o']
        w_MFIE_i = self.md['w_MFIE_i']
        w_MFIE_o = self.md['w_MFIE_o']

        Z = LookupArray((("E", "H"), (self.part_o, self.basis_container),
                         ("J", "M"), (self.part_s, self.basis_container)),
                        dtype=np.complex128)

        # first calculate the external problem contributions
        Z["E", :, "J"] = eta_o * D_o * w_EFIE_o
        Z["E", :, "M"] = -K_o * w_EFIE_o
        Z["H", :, "J"] = K_o * w_MFIE_o
        Z["H", :, "M"] = D_o / eta_o * w_MFIE_o

        # The internal contributions are only for self-terms
        for part_o in self.part_o.iter_single():
            for part_s in self.part_s.iter_single():
                if part_o == part_s:
                    Z["E", :, "J"][part_o, part_s] += eta_i[part_s] * D_i[
                        part_o, part_s] * w_EFIE_i[part_s]
                    Z["E", :,
                      "M"][part_o,
                           part_s] -= K_i[part_o, part_s] * w_EFIE_i[part_s]
                    Z["H", :,
                      "J"][part_o,
                           part_s] += K_i[part_o, part_s] * w_MFIE_i[part_s]
                    Z["H", :, "M"][part_o, part_s] += D_i[
                        part_o, part_s] / eta_i[part_s] * w_MFIE_i[part_s]

        return Z
Exemplo n.º 16
0
    def source_vector(self, source_field, s, parent, extinction_field=False):
        "Calculate the relevant source vector for this operator"

        if extinction_field:
            fields = self.extinction_fields
        else:
            fields = self.sources

        V = LookupArray((fields, (parent, self.basis_container)),
                        dtype=np.complex128)

        # define the functions to interpolate over the mesh
        def elec_func(r):
            return source_field.electric_field(s, r)

        def mag_func(r):
            return source_field.magnetic_field(s, r)

        for field in fields:
            if field in ("E", "nxE"):
                field_func = elec_func
                source_cross = field == "nxE"
            elif field in ("H", "nxH"):
                field_func = mag_func
                source_cross = field == "nxH"
            else:
                raise ValueError(field)

            for part in parent.iter_single():
                basis = self.basis_container[part]
                V[field,
                  part] = basis.weight_function(field_func,
                                                self.integration_rule,
                                                part.nodes, source_cross)

        return V