Exemplo n.º 1
0
    def updateQs(self):
        Qs = self.Qs
        Ns = self.Ns
        oml0 = self.oml0

        for f in range(len(Ns)):
            PAMlib.updateqs(oml0.nQ, Ns[f].shape[0], Ns[f].shape[1], Ns[f], Qs[f], oml0.Q)
Exemplo n.º 2
0
    def computeSections(self, nQ, shapes, radii=None):
        nf = len(self.Qs)
        n = self.Qs[0].shape[1]
        v = self.variables

        rot0, Da, Di, Dj = PAMlib.computerotations(self.ax1, self.ax2, n,
                                                   9 * (n * 3 - 2), v['pos'],
                                                   v['nor'])
        rot = v['rot'] * numpy.pi / 180.0 + rot0
        dv_dpos0 = scipy.sparse.csc_matrix((Da, (Di + 6 * n, Dj + 3 * n)),
                                           shape=(nQ, nQ))

        self.dQs_dv = range(nf)
        counter = 0
        for f in range(nf):
            if radii == None:
                scale = v['scl']
            else:
                scale = radii[f]
            ni, nj = self.Qs[f].shape[:2]
            self.Qs[f][:, :, :], Da, Di, Dj = PAMlib.computesections(
                self.ax1, self.ax2, ni, nj, ni * nj * 27, counter, v['ogn'],
                scale, v['pos'], rot, shapes[f])
            self.dQs_dv[f] = scipy.sparse.csc_matrix((Da, (Di, Dj)),
                                                     shape=(3 * ni * nj, nQ))
            self.dQs_dv[f] = self.dQs_dv[f] + self.dQs_dv[f].dot(dv_dpos0)
            counter += 3 * ni * nj
Exemplo n.º 3
0
 def addConnectors(self):
     ncon, quadrants = PAMlib.countconnectors(self.nvert, self.nedge, self.Lx, self.Ly, self.verts, self.edges)
     self.verts, self.edges = PAMlib.addconnectors(
         self.nvert + ncon, self.nedge + ncon, self.nvert, self.nedge, self.verts, self.edges, quadrants
     )
     self.nvert = self.verts.shape[0]
     self.nedge = self.edges.shape[0]
Exemplo n.º 4
0
 def splitPolygons(self):
     self.computePolygons()
     self.edges = PAMlib.splitpentagons(self.nedge + self.npent, self.nvert,
                                        self.nedge, self.npoly, self.Lx,
                                        self.Ly, self.verts, self.edges,
                                        self.poly_vert)
     self.nedge = self.edges.shape[0]
     self.computePolygons()
     self.edge_group = PAMlib.computegroups(self.nedge, self.npoly,
                                            self.poly_edge)
     self.ngroup = max(self.edge_group)
     group_split = PAMlib.computetrisplits(self.nedge, self.ngroup,
                                           self.npoly, self.edge_group,
                                           self.poly_edge)
     nsplit = PAMlib.countquadsplits(self.nedge, self.ngroup, self.npoly,
                                     self.poly_edge, self.edge_group,
                                     group_split)
     self.verts, self.edges = PAMlib.addpolysplits(
         self.nvert + 4 * self.ntri + 2 * nsplit,
         self.nedge + 3 * self.ntri + nsplit, self.nvert, self.nedge,
         self.ngroup, self.npoly, self.verts, self.edges, self.edge_group,
         self.poly_vert, self.poly_edge, group_split)
     self.nvert = self.verts.shape[0]
     self.nedge = self.edges.shape[0]
     self.computeIntersections()
     self.computePolygons()
Exemplo n.º 5
0
 def setDerivatives(self, var, dV0):
     nf = len(self.Qs)
     nv = self.dQs_dv[0].shape[1]
     n = self.Qs[0].shape[1]
     dV = numpy.zeros(nv)
     if var == 'scl':
         dV[:3 * n] = dV0.T.flatten()
         for f in range(nf):
             ni, nj = self.Qs[f].shape[:2]
             self.Qs[f][:, :, :] += PAMlib.inflatevector(
                 ni, nj, 3 * ni * nj, self.dQs_dv[f].dot(dV))
     elif var == 'pos':
         dV[3 * n:6 * n] = dV0.T.flatten()
         for f in range(nf):
             ni, nj = self.Qs[f].shape[:2]
             for i in range(ni):
                 self.Qs[f][i, :, :] += dV0
             self.Qs[f][:, :, :] += PAMlib.inflatevector(
                 ni, nj, 3 * ni * nj, self.dQs_dv[f].dot(dV))
     elif var == 'rot':
         dV[6 * n:9 * n] = dV0.T.flatten()
         for f in range(nf):
             ni, nj = self.Qs[f].shape[:2]
             self.Qs[f][:, :, :] += PAMlib.inflatevector(
                 ni, nj, 3 * ni * nj,
                 self.dQs_dv[f].dot(dV) * numpy.pi / 180.0)
     else:
         self.variables[var] += dV0
         self.computeQs()
         self.variables[var] -= dV0
Exemplo n.º 6
0
 def propagateQs(self):
     Qs = self.Qs
     Ns = self.Ns
     oml0 = self.oml0
     for f in range(len(Ns)):
         PAMlib.updateqs(oml0.nQ, Ns[f].shape[0], Ns[f].shape[1], oml0.nvar,
                         Ns[f], Qs[f], oml0.Q)
Exemplo n.º 7
0
 def setDerivatives(self, var, dV0):
     nf = len(self.Qs)
     nv = self.dQs_dv[0].shape[1]
     n = self.Qs[0].shape[1]
     dV = numpy.zeros(nv)
     if var=='scl':
         dV[:3*n] = dV0.T.flatten()
         for f in range(nf):
             ni, nj = self.Qs[f].shape[:2]
             self.Qs[f][:,:,:] += PAMlib.inflatevector(ni, nj, 3*ni*nj, self.dQs_dv[f].dot(dV))
     elif var=='pos':
         dV[3*n:6*n] = dV0.T.flatten()
         for f in range(nf):
             ni, nj = self.Qs[f].shape[:2]
             for i in range(ni):
                 self.Qs[f][i,:,:] += dV0
             self.Qs[f][:,:,:] += PAMlib.inflatevector(ni, nj, 3*ni*nj, self.dQs_dv[f].dot(dV))
     elif var=='rot':
         dV[6*n:9*n] = dV0.T.flatten()
         for f in range(nf):
             ni, nj = self.Qs[f].shape[:2]
             self.Qs[f][:,:,:] += PAMlib.inflatevector(ni, nj, 3*ni*nj, self.dQs_dv[f].dot(dV)*numpy.pi/180.0)
     else:
         self.variables[var] += dV0
         self.computeQs()
         self.variables[var] -= dV0
Exemplo n.º 8
0
    def computeStructure(self, P):
        oml0 = self.oml0
        Ms = self.Ms
        Js = self.Js
        layout = self.layout
        skinIndices = self.getSkinIndices()

        C = numpy.zeros((4,2),order='F')
        As = []
        Jns = []
        Jus = []
        col = 0
        for s in range(len(skinIndices)):
            n = max(self.quad_indices[:,s])*self.layout.n**2
            Aa = numpy.ones(n)
            Ai = numpy.linspace(0, n-1, n)
            Aj = numpy.linspace(0, n-1, n) + col
            As.append(scipy.sparse.csr_matrix((Aa,(Ai,Aj)), shape=(n,P.shape[0])))
            Jn = []
            Ju = []
            col += n
            for f in skinIndices[s]:
                for k in range(Js[f].shape[0]):
                    C[0,:] = oml0.C[Ms[f][Js[f][k,0],Js[f][k,1]],:2]
                    C[1,:] = oml0.C[Ms[f][Js[f][k,0],Js[f][k,3]],:2]
                    C[2,:] = oml0.C[Ms[f][Js[f][k,2],Js[f][k,1]],:2]
                    C[3,:] = oml0.C[Ms[f][Js[f][k,2],Js[f][k,3]],:2]
                    nu1, nu2, nv1, nv2 = layout.countJunctionEdges(self.JQs[s], min(C[:,0]), max(C[:,0]), min(C[:,1]), max(C[:,1]))
                    Jn.append([nu1, nu2, nv1, nv2])
                    Ju.append([min(C[:,0]), max(C[:,0]), min(C[:,1]), max(C[:,1])])
                    nP = layout.n*(nu1 + nu2 + nv1 + nv2)
                    col += nP
            if Jn==[]:
                Jn.append([-1,-1,-1,-1])
                Ju.append([-1,-1,-1,-1])
            Jns.append(numpy.array(Jn, int, order='F'))
            Jus.append(numpy.array(Ju, order='F'))
            
        nM = len(self.keys)
        members = numpy.zeros((nM,34),order='F')
        for i in range(nM):
            member = self.members[self.keys[i]]
            members[i,:4] = [member.domain, member.shape, member.nmem, member.ndiv]
            members[i, 4:16] = member.A1 + member.B1 + member.C1 + member.D1
            members[i,16:28] = member.A2 + member.B2 + member.C2 + member.D2
            members[i,28:] = [member.tx, member.ty, member.rx, member.ry, member.n1, member.n2]

        nP, nS = PAMlib.countinternalnodes(self.layout.n, nM, members)
        P2, M, S = PAMlib.computeinternalnodes(nP, nS, self.layout.n, nM, members)
        nA = PAMlib.countannz(nP, layout.nvert, layout.nquad, layout.verts, layout.poly_vert, self.quad_indices, P2, M)
        if len(skinIndices)==1:
            Aa, Ai, Aj = PAMlib.assembleamtx(nA, self.layout.n, nP, Jns[0].shape[0], Jns[0].shape[0], self.layout.nvert, self.layout.nquad, Jns[0], Jns[0], Jus[0], Jus[0], self.quad_indices, self.layout.verts, self.layout.poly_vert, P2, M)
        else:
            Aa, Ai, Aj = PAMlib.assembleamtx(nA, self.layout.n, nP, Jns[0].shape[0], Jns[1].shape[0], self.layout.nvert, self.layout.nquad, Jns[0], Jns[1], Jus[0], Jus[1], self.quad_indices, self.layout.verts, self.layout.poly_vert, P2, M)
        As.append(scipy.sparse.csr_matrix((Aa,(Ai,Aj)), shape=(max(Ai)+1,P.shape[0])))
            
        return As, S
Exemplo n.º 9
0
 def computePolygons(self):
     self.npent, self.nquad, self.ntri = PAMlib.countpolygons(
         self.nvert, self.nedge, self.Lx, self.Ly, self.verts, self.edges
     )
     npoly = 5 * self.npent + 4 * self.nquad + 3 * self.ntri
     poly_vert, poly_edge = PAMlib.computepolygons(
         npoly, self.nvert, self.nedge, self.Lx, self.Ly, self.verts, self.edges
     )
     self.npoly = self.npent + self.nquad + self.ntri
     self.poly_vert, self.poly_edge = PAMlib.deleteduplicatepolygons(self.npoly, npoly, poly_vert, poly_edge)
Exemplo n.º 10
0
 def addConnectors(self):
     ncon, quadrants = PAMlib.countconnectors(self.nvert, self.nedge,
                                              self.Lx, self.Ly, self.verts,
                                              self.edges)
     self.verts, self.edges = PAMlib.addconnectors(self.nvert + ncon,
                                                   self.nedge + ncon,
                                                   self.nvert, self.nedge,
                                                   self.verts, self.edges,
                                                   quadrants)
     self.nvert = self.verts.shape[0]
     self.nedge = self.edges.shape[0]
Exemplo n.º 11
0
 def computePolygons(self):
     self.npent, self.nquad, self.ntri = PAMlib.countpolygons(
         self.nvert, self.nedge, self.Lx, self.Ly, self.verts, self.edges)
     npoly = 5 * self.npent + 4 * self.nquad + 3 * self.ntri
     poly_vert, poly_edge = PAMlib.computepolygons(npoly, self.nvert,
                                                   self.nedge, self.Lx,
                                                   self.Ly, self.verts,
                                                   self.edges)
     self.npoly = self.npent + self.nquad + self.ntri
     self.poly_vert, self.poly_edge = PAMlib.deleteduplicatepolygons(
         self.npoly, npoly, poly_vert, poly_edge)
Exemplo n.º 12
0
    def computeQs(self):
        getEdge = self.getEdge
        Qs = self.comp.Qs
        zeros = numpy.zeros((1,3),order='F')
        if self.face==0:
            W = getEdge(Qs[0], j=1, d=-1)
            N = getEdge(Qs[1], j=1, d=1)
            E = getEdge(Qs[2], j=1, d=1)
            if self.comp.bottom==2:
                S = getEdge(Qs[3], j=1, d=-1)
            else:
                S = getEdge(Qs[1], j=1, d=1)
        else:
            E = getEdge(Qs[0], j=-2, d=-1)
            N = getEdge(Qs[1], j=-2, d=-1)
            W = getEdge(Qs[2], j=-2, d=1)
            if self.comp.bottom==2:
                S = getEdge(Qs[3], j=-2, d=1)
            else:
                S = getEdge(Qs[1], j=-2, d=-1)

        mu = self.getms(0,0)
        mv = self.getms(0,1)
        nu = range(3)
        nv = range(3)
        for k in range(3):
            nu[k] = sum(mu[self.si[k]:self.si[k+1]])
            nv[k] = sum(mv[self.sj[k]:self.sj[k+1]])

        v = self.variables
        self.Qs[0] = PAMlib.computecone(sum(nu)+1, sum(nv)+1, nu[0], nu[1], nu[2], nv[0], nv[1], nv[2], v['scl']*self.comp.Qs[0].shape[1], v['fC1'], v['mC1'], W, E, N, S, v['shp'])
Exemplo n.º 13
0
    def addFace(self, du, dv, d, ru=0.5, rv=0.5):
        """ Creates a set of rectangular surfaces, their IDs, and face dims.
        nu,nv: number of surfaces in the u and v directions
        du,dv: {1,2,3} maps to {x,y,z}; negative sign means reverse order
        d: position of the surfaces in the remaining coordinate axis
        ru,rv: surfaces span -ru to +ru in u dir. and -rv to +rv in v dir.

        Adds to self.Ps and self.Ks
        """
        self.faces.append([du, dv])
        nP = 10
        ni = self.ms[abs(du) - 1].shape[0]
        nj = self.ms[abs(dv) - 1].shape[0]
        verts = numpy.zeros((2, 2, 3), order='F')
        verts[:, :, :] = d
        verts[0, :, abs(du) - 1] = -ru * numpy.sign(du)
        verts[1, :, abs(du) - 1] = ru * numpy.sign(du)
        verts[:, 0, abs(dv) - 1] = -rv * numpy.sign(dv)
        verts[:, 1, abs(dv) - 1] = rv * numpy.sign(dv)
        for j in range(nj):
            for i in range(ni):
                self.Ps.append(
                    PAMlib.bilinearinterp(nP, ni, nj, i + 1, j + 1, verts))

        if len(self.Ks) > 0:
            counter = numpy.max(self.Ks[-1]) + 1
        else:
            counter = 0
        K = numpy.zeros((ni, nj), int)
        for j in range(nj):
            for i in range(ni):
                K[i, j] = counter
                counter += 1
        self.Ks.append(K)
Exemplo n.º 14
0
    def computeQs(self):
        getEdge = self.getEdge
        Qs = self.comp.Qs
        zeros = numpy.zeros((1, 3), order='F')
        if self.face == 0:
            W = getEdge(Qs[0], j=1, d=-1)
            N = getEdge(Qs[1], j=1, d=1)
            E = getEdge(Qs[2], j=1, d=1)
            if self.comp.bottom == 2:
                S = getEdge(Qs[3], j=1, d=-1)
            else:
                S = getEdge(Qs[1], j=1, d=1)
        else:
            E = getEdge(Qs[0], j=-2, d=-1)
            N = getEdge(Qs[1], j=-2, d=-1)
            W = getEdge(Qs[2], j=-2, d=1)
            if self.comp.bottom == 2:
                S = getEdge(Qs[3], j=-2, d=1)
            else:
                S = getEdge(Qs[1], j=-2, d=-1)

        mu = self.getms(0, 0)
        mv = self.getms(0, 1)
        nu = range(3)
        nv = range(3)
        for k in range(3):
            nu[k] = sum(mu[self.si[k]:self.si[k + 1]])
            nv[k] = sum(mv[self.sj[k]:self.sj[k + 1]])

        v = self.variables
        self.Qs[0] = PAMlib.computecone(
            sum(nu) + 1,
            sum(nv) + 1, nu[0], nu[1], nu[2], nv[0], nv[1], nv[2],
            v['scl'] * self.comp.Qs[0].shape[1], v['fC1'], v['mC1'], W, E, N,
            S, v['shp'])
Exemplo n.º 15
0
    def addFace(self, du, dv, d, ru=0.5, rv=0.5):
        """ Creates a set of rectangular surfaces, their IDs, and face dims.
        nu,nv: number of surfaces in the u and v directions
        du,dv: {1,2,3} maps to {x,y,z}; negative sign means reverse order
        d: position of the surfaces in the remaining coordinate axis
        ru,rv: surfaces span -ru to +ru in u dir. and -rv to +rv in v dir.

        Adds to self.Ps and self.Ks
        """
        self.faces.append([du, dv])
        nP = 10
        ni = self.ms[abs(du) - 1].shape[0]
        nj = self.ms[abs(dv) - 1].shape[0]
        verts = numpy.zeros((2, 2, 3), order="F")
        verts[:, :, :] = d
        verts[0, :, abs(du) - 1] = -ru * numpy.sign(du)
        verts[1, :, abs(du) - 1] = ru * numpy.sign(du)
        verts[:, 0, abs(dv) - 1] = -rv * numpy.sign(dv)
        verts[:, 1, abs(dv) - 1] = rv * numpy.sign(dv)
        for j in range(nj):
            for i in range(ni):
                self.Ps.append(PAMlib.bilinearinterp(nP, ni, nj, i + 1, j + 1, verts))

        if len(self.Ks) > 0:
            counter = numpy.max(self.Ks[-1]) + 1
        else:
            counter = 0
        K = numpy.zeros((ni, nj), int)
        for j in range(nj):
            for i in range(ni):
                K[i, j] = counter
                counter += 1
        self.Ks.append(K)
Exemplo n.º 16
0
 def extractFlattened(self, JQ, npoly):
     return (
         PAMlib.extractflattened(
             self.n, len(JQ), npoly * self.n ** 2, self.nvert, self.npoly, JQ, self.verts, self.poly_vert
         ),
         self.n * numpy.ones((npoly, 2), order="F"),
     )
Exemplo n.º 17
0
    def computeQs(self):
        nx = self.Qs[0].shape[1]
        ny = self.Qs[0].shape[0]
        nz = self.Qs[1].shape[0]
        v = self.variables
        b = self.bottom==2

        #v['pos'][0] = 2*v['pos'][1] - v['pos'][2]
        #v['pos'][-1] = 2*v['pos'][-2] - v['pos'][-3]

        shapes = range(4)
        shapes[0] = PAMlib.computeshape(ny, nx,-b/4.0, 1/4.0, v['flt'], v['shR'])
        shapes[1] = PAMlib.computeshape(nz, nx, 1/4.0, 3/4.0, v['flt'], v['shT'])
        shapes[2] = PAMlib.computeshape(ny, nx, 3/4.0, (4+b)/4.0, v['flt'], v['shL'])
        shapes[3] = PAMlib.computeshape(nz, nx, 5/4.0, 7/4.0, v['flt'], v['shB'])

        nQ = nx*(9+6*ny+6*nz) if self.bottom==2 else nx*(9+6*ny+3*nz)
        self.computeSections(nQ, shapes)
Exemplo n.º 18
0
    def computeSections(self, nQ, shapes, radii=None):
        nf = len(self.Qs)
        n = self.Qs[0].shape[1]
        v = self.variables

        rot0, Da, Di, Dj = PAMlib.computerotations(self.ax1, self.ax2, n, 9*(n*3-2), v['pos'], v['nor'])
        rot = v['rot']*numpy.pi/180.0 + rot0
        dv_dpos0 = scipy.sparse.csc_matrix((Da,(Di+6*n,Dj+3*n)),shape=(nQ,nQ))

        self.dQs_dv = range(nf)
        counter = 0
        for f in range(nf):
            if radii==None:
                scale = v['scl']
            else:
                scale = radii[f]
            ni, nj = self.Qs[f].shape[:2]
            self.Qs[f][:,:,:], Da, Di, Dj = PAMlib.computesections(self.ax1, self.ax2, ni, nj, ni*nj*27, counter, v['ogn'], scale, v['pos'], rot, shapes[f])
            self.dQs_dv[f] = scipy.sparse.csc_matrix((Da,(Di,Dj)),shape=(3*ni*nj,nQ))
            self.dQs_dv[f] = self.dQs_dv[f] + self.dQs_dv[f].dot(dv_dpos0)
            counter += 3*ni*nj
Exemplo n.º 19
0
 def splitPolygons(self):
     self.computePolygons()
     self.edges = PAMlib.splitpentagons(
         self.nedge + self.npent,
         self.nvert,
         self.nedge,
         self.npoly,
         self.Lx,
         self.Ly,
         self.verts,
         self.edges,
         self.poly_vert,
     )
     self.nedge = self.edges.shape[0]
     self.computePolygons()
     self.edge_group = PAMlib.computegroups(self.nedge, self.npoly, self.poly_edge)
     self.ngroup = max(self.edge_group)
     group_split = PAMlib.computetrisplits(self.nedge, self.ngroup, self.npoly, self.edge_group, self.poly_edge)
     nsplit = PAMlib.countquadsplits(
         self.nedge, self.ngroup, self.npoly, self.poly_edge, self.edge_group, group_split
     )
     self.verts, self.edges = PAMlib.addpolysplits(
         self.nvert + 4 * self.ntri + 2 * nsplit,
         self.nedge + 3 * self.ntri + nsplit,
         self.nvert,
         self.nedge,
         self.ngroup,
         self.npoly,
         self.verts,
         self.edges,
         self.edge_group,
         self.poly_vert,
         self.poly_edge,
         group_split,
     )
     self.nvert = self.verts.shape[0]
     self.nedge = self.edges.shape[0]
     self.computeIntersections()
     self.computePolygons()
Exemplo n.º 20
0
    def computeQs(self):
        nx = self.Qs[0].shape[1]
        ny = self.Qs[0].shape[0]
        nz = self.Qs[1].shape[0]
        v = self.variables
        b = self.bottom == 2

        #v['pos'][0] = 2*v['pos'][1] - v['pos'][2]
        #v['pos'][-1] = 2*v['pos'][-2] - v['pos'][-3]

        shapes = range(4)
        shapes[0] = PAMlib.computeshape(ny, nx, -b / 4.0, 1 / 4.0, v['flt'],
                                        v['shR'])
        shapes[1] = PAMlib.computeshape(nz, nx, 1 / 4.0, 3 / 4.0, v['flt'],
                                        v['shT'])
        shapes[2] = PAMlib.computeshape(ny, nx, 3 / 4.0, (4 + b) / 4.0,
                                        v['flt'], v['shL'])
        shapes[3] = PAMlib.computeshape(nz, nx, 5 / 4.0, 7 / 4.0, v['flt'],
                                        v['shB'])

        nQ = nx * (9 + 6 * ny +
                   6 * nz) if self.bottom == 2 else nx * (9 + 6 * ny + 3 * nz)
        self.computeSections(nQ, shapes)
Exemplo n.º 21
0
    def computeIntersections(self):
        nint = PAMlib.numintersections(self.nvert, self.nedge, self.verts, self.edges)
        self.verts = PAMlib.addintersections(self.nvert + nint, self.nvert, self.nedge, self.verts, self.edges)
        self.nvert = self.verts.shape[0]

        ndup = PAMlib.countduplicateverts(self.nvert, self.verts)
        self.verts, self.edges = PAMlib.deleteduplicateverts(
            self.nvert - ndup, self.nvert, self.nedge, self.verts, self.edges
        )
        self.nvert = self.verts.shape[0]
        self.nedge = self.edges.shape[0]

        nsplit = PAMlib.countedgesplits(self.nvert, self.nedge, self.verts, self.edges)
        self.edges = PAMlib.splitedges(self.nedge + nsplit, self.nvert, self.nedge, self.verts, self.edges)
        self.nedge = self.edges.shape[0]

        ndup = PAMlib.countduplicateedges(self.nedge, self.edges)
        self.edges = PAMlib.deleteduplicateedges(self.nedge - ndup, self.nedge, self.edges)
        self.nedge = self.edges.shape[0]
Exemplo n.º 22
0
    def createSurfaces(self, Ks, nu, nv, du, dv, d):
        Ps = []
        for j in range(len(nv)):
            for i in range(len(nu)):
                u1 = (sum(nu[:i]) - i) / (sum(nu) - len(nu))
                u2 = (sum(nu[: i + 1]) - i - 1) / (sum(nu) - len(nu))
                v1 = (sum(nv[:j]) - j) / (sum(nv) - len(nv))
                v2 = (sum(nv[: j + 1]) - j - 1) / (sum(nv) - len(nv))
                P = PAMlib.createsurfaces(nu[i], nv[j], du, dv, d, u1, u2, v1, v2)
                Ps.append(P)

        K = numpy.zeros((len(nu), len(nv)), int)
        counter = 0
        if len(Ks) > 0:
            counter = numpy.max(Ks[-1]) + 1
        for j in range(len(nv)):
            for i in range(len(nu)):
                K[i, j] = counter
                counter += 1
        return Ps, K
Exemplo n.º 23
0
    def computeQs(self):
        fu = self.fComp.getms(self.fFace, 0)
        fv = self.fComp.getms(self.fFace, 1)
        fu, fv = self.flip(fu, fv)
        fu1 = sum(fu[:self.fNW[0]])
        fu2 = sum(fu[:self.fNW[0] + self.si[3]])
        fv1 = sum(fv[:self.fNW[1]])
        fv2 = sum(fv[:self.fNW[1] + self.sj[3]])
        fQ = self.rotate(self.fComp.Qs[self.fFace])[fu1:fu2 + 1,
                                                    fv1:fv2 + 1, :]

        getEdge = self.getEdge
        if self.mSide == -1:
            W = getEdge(self.mComp.Qs[2], i=-1, d=1)
            E = getEdge(self.mComp.Qs[0], i=0, d=1)
            N = getEdge(self.mComp0.Qs[0], i=-1, d=-1)
            S = getEdge(self.mComp1.Qs[0], i=-1, d=1)
        elif self.mSide == 0:
            W = numpy.zeros((1, 2, 3), order='F')
            E = numpy.zeros((1, 2, 3), order='F')
            N = getEdge(self.mComp.Qs[0], j=0, d=-1)
            S = getEdge(self.mComp.Qs[1], j=0, d=1)
        elif self.mSide == 1:
            W = numpy.zeros((1, 2, 3), order='F')
            E = numpy.zeros((1, 2, 3), order='F')
            N = getEdge(self.mComp.Qs[0], j=-1, d=1)
            S = getEdge(self.mComp.Qs[1], j=-1, d=-1)

        mu = self.getms(0, 0)
        mv = self.getms(0, 1)
        nu = range(3)
        nv = range(3)
        for k in range(3):
            nu[k] = sum(mu[self.si[k]:self.si[k + 1]]) + 1
            nv[k] = sum(mv[self.sj[k]:self.sj[k + 1]]) + 1

        v = self.variables
        self.Qs[0] = PAMlib.computejunction(
            sum(nu) - 2,
            sum(nv) - 2, nu[0], nu[1], nu[2], nv[0], nv[1], nv[2], v['fC1'],
            v['mC1'], W, E, N, S, fQ, v['shp'])
Exemplo n.º 24
0
    def createSurfaces(self, Ks, nu, nv, du, dv, d):
        Ps = []
        for j in range(len(nv)):
            for i in range(len(nu)):
                u1 = (sum(nu[:i]) - i) / (sum(nu) - len(nu))
                u2 = (sum(nu[:i + 1]) - i - 1) / (sum(nu) - len(nu))
                v1 = (sum(nv[:j]) - j) / (sum(nv) - len(nv))
                v2 = (sum(nv[:j + 1]) - j - 1) / (sum(nv) - len(nv))
                P = PAMlib.createsurfaces(nu[i], nv[j], du, dv, d, u1, u2, v1,
                                          v2)
                Ps.append(P)

        K = numpy.zeros((len(nu), len(nv)), int)
        counter = 0
        if len(Ks) > 0:
            counter = numpy.max(Ks[-1]) + 1
        for j in range(len(nv)):
            for i in range(len(nu)):
                K[i, j] = counter
                counter += 1
        return Ps, K
Exemplo n.º 25
0
    def computeQs(self):
        nx = self.Qs[0].shape[1]
        ny = self.Qs[0].shape[0]
        nz = self.Qs[1].shape[0]
        v = self.variables
        b = self.bottom==2

        r0 = v['scl'] + v['thk']/2.0
        r1 = v['scl'] - v['thk']/2.0

        shapes = range(8)
        shapes[0] = PAMlib.computeshape(ny, nx,-b/4.0, 1/4.0, v['flt'], v['sR0'])
        shapes[1] = PAMlib.computeshape(nz, nx, 1/4.0, 3/4.0, v['flt'], v['sT0'])
        shapes[2] = PAMlib.computeshape(ny, nx, 3/4.0, (4+b)/4.0, v['flt'], v['sL0'])
        shapes[6] = PAMlib.computeshape(nz, nx, 5/4.0, 7/4.0, v['flt'], v['sB0'])
        shapes[5] = PAMlib.computeshape(ny, nx, 1/4.0,-b/4.0, v['flt'], v['sR1'])
        shapes[4] = PAMlib.computeshape(nz, nx, 3/4.0, 1/4.0, v['flt'], v['sT1'])
        shapes[3] = PAMlib.computeshape(ny, nx, (4+b)/4.0, 3/4.0, v['flt'], v['sL1'])
        shapes[7] = PAMlib.computeshape(nz, nx, 7/4.0, 5/4.0, v['flt'], v['sB1'])
        
        nQ = nx*(9+12*ny+12*nz) if self.bottom==2 else nx*(9+12*ny+6*nz)
        radii = [r0,r0,r0,r1,r1,r1,r0,r1]
        self.computeSections(nQ, shapes, radii=radii)
Exemplo n.º 26
0
    def initializeSurfaces(self):
        vtx = lambda f, i, j: self.comp.Ps[self.comp.Ks[f][i,j]][i,j,:]
        verts = numpy.zeros((2,2,3),order='F')
        if self.face==0:
            verts[0,0,:] = vtx(0, -1, 0)
            verts[1,0,:] = vtx(0, 0, 0)
            verts[0,1,:] = vtx(2, 0, 0)
            verts[1,1,:] = vtx(2, -1, 0)
        else:
            verts[0,0,:] = vtx(2, 0, -1)
            verts[1,0,:] = vtx(2, -1, -1)
            verts[0,1,:] = vtx(0, -1, -1)
            verts[1,1,:] = vtx(0, 0, -1)
        ni = sum(self.ni)
        nj = sum(self.nj)

        self.Ps = []
        self.Ks = [-numpy.ones((ni,nj),int)]
        for j in range(nj):
            for i in range(ni):
                self.Ps.append(PAMlib.bilinearinterp(self.nP, ni, nj, i+1, j+1, verts))
                self.Ks[0][i,j] = j*ni + i
Exemplo n.º 27
0
    def computeIntersections(self):
        nint = PAMlib.numintersections(self.nvert, self.nedge, self.verts,
                                       self.edges)
        self.verts = PAMlib.addintersections(self.nvert + nint, self.nvert,
                                             self.nedge, self.verts,
                                             self.edges)
        self.nvert = self.verts.shape[0]

        ndup = PAMlib.countduplicateverts(self.nvert, self.verts)
        self.verts, self.edges = PAMlib.deleteduplicateverts(
            self.nvert - ndup, self.nvert, self.nedge, self.verts, self.edges)
        self.nvert = self.verts.shape[0]
        self.nedge = self.edges.shape[0]

        nsplit = PAMlib.countedgesplits(self.nvert, self.nedge, self.verts,
                                        self.edges)
        self.edges = PAMlib.splitedges(self.nedge + nsplit, self.nvert,
                                       self.nedge, self.verts, self.edges)
        self.nedge = self.edges.shape[0]

        ndup = PAMlib.countduplicateedges(self.nedge, self.edges)
        self.edges = PAMlib.deleteduplicateedges(self.nedge - ndup, self.nedge,
                                                 self.edges)
        self.nedge = self.edges.shape[0]
Exemplo n.º 28
0
    def computeQs(self):
        fu = self.fComp.getms(self.fFace,0)
        fv = self.fComp.getms(self.fFace,1)
        fu,fv = self.flip(fu,fv)
        fu1 = sum(fu[:self.fNW[0]])
        fu2 = sum(fu[:self.fNW[0]+self.si[3]])
        fv1 = sum(fv[:self.fNW[1]])
        fv2 = sum(fv[:self.fNW[1]+self.sj[3]])
        fQ = self.rotate(self.fComp.Qs[self.fFace])[fu1:fu2+1,fv1:fv2+1,:]

        getEdge = self.getEdge
        if self.mSide==-1:
            W = getEdge(self.mComp.Qs[2], i=-1, d=1)
            E = getEdge(self.mComp.Qs[0], i=0, d=1)
            N = getEdge(self.mComp0.Qs[0], i=-1, d=-1)
            S = getEdge(self.mComp1.Qs[0], i=-1, d=1)
        elif self.mSide==0:
            W = numpy.zeros((1,2,3),order='F')
            E = numpy.zeros((1,2,3),order='F')
            N = getEdge(self.mComp.Qs[0], j=0, d=-1)
            S = getEdge(self.mComp.Qs[1], j=0, d=1)
        elif self.mSide==1:
            W = numpy.zeros((1,2,3),order='F')
            E = numpy.zeros((1,2,3),order='F')
            N = getEdge(self.mComp.Qs[0], j=-1, d=1)
            S = getEdge(self.mComp.Qs[1], j=-1, d=-1)

        mu = self.getms(0,0)
        mv = self.getms(0,1)
        nu = range(3)
        nv = range(3)
        for k in range(3):
            nu[k] = sum(mu[self.si[k]:self.si[k+1]]) + 1
            nv[k] = sum(mv[self.sj[k]:self.sj[k+1]]) + 1

        v = self.variables
        self.Qs[0] = PAMlib.computejunction(sum(nu)-2, sum(nv)-2, nu[0], nu[1], nu[2], nv[0], nv[1], nv[2], v['fC1'], v['mC1'], W, E, N, S, fQ, v['shp'])
Exemplo n.º 29
0
    def initializeSurfaces(self):
        vtx = lambda f, i, j: self.comp.Ps[self.comp.Ks[f][i, j]][i, j, :]
        verts = numpy.zeros((2, 2, 3), order='F')
        if self.face == 0:
            verts[0, 0, :] = vtx(0, -1, 0)
            verts[1, 0, :] = vtx(0, 0, 0)
            verts[0, 1, :] = vtx(2, 0, 0)
            verts[1, 1, :] = vtx(2, -1, 0)
        else:
            verts[0, 0, :] = vtx(2, 0, -1)
            verts[1, 0, :] = vtx(2, -1, -1)
            verts[0, 1, :] = vtx(0, -1, -1)
            verts[1, 1, :] = vtx(0, 0, -1)
        ni = sum(self.ni)
        nj = sum(self.nj)

        self.Ps = []
        self.Ks = [-numpy.ones((ni, nj), int)]
        for j in range(nj):
            for i in range(ni):
                self.Ps.append(
                    PAMlib.bilinearinterp(self.nP, ni, nj, i + 1, j + 1,
                                          verts))
                self.Ks[0][i, j] = j * ni + i
Exemplo n.º 30
0
 def importEdges(self, edges):
     self.edges = PAMlib.getedges(edges.shape[0], edges)
     self.verts = PAMlib.getverts(numpy.max(self.edges[:, :2]),
                                  edges.shape[0], edges, self.edges)
     self.nedge = self.edges.shape[0]
     self.nvert = self.verts.shape[0]
Exemplo n.º 31
0
 def getQuadIndices(self, JQ):
     if len(JQ) == 0:
         return PAMlib.getquadindices(1, self.npoly, [-1])
     else:
         return PAMlib.getquadindices(len(JQ), self.npoly, JQ)
Exemplo n.º 32
0
 def extractEdges(self, JQ, u1, u2, v1, v2):
     nu1, nu2, nv1, nv2 = self.countJunctionEdges(JQ, u1, u2, v1, v2)
     nP = self.n * (nu1 + nu2 + nv1 + nv2)
     return PAMlib.extractedges(nP, self.n, nu1, nu2, nv1, nv2, self.nvert,
                                u1, u2, v1, v2, self.verts)
Exemplo n.º 33
0
 def countJunctionEdges(self, JQ, u1, u2, v1, v2):
     return PAMlib.countjunctionedges(len(JQ), self.nvert, self.nquad, u1,
                                      u2, v1, v2, JQ, self.verts,
                                      self.poly_vert)
Exemplo n.º 34
0
 def extractFlattened(self, JQ, npoly):
     return PAMlib.extractflattened(self.n, len(JQ), npoly * self.n**2,
                                    self.nvert, self.npoly, JQ, self.verts,
                                    self.poly_vert), self.n * numpy.ones(
                                        (npoly, 2), order='F')
Exemplo n.º 35
0
 def extractSurfaces(self):
     self.P = []
     for p in range(self.npoly):
         self.P.append(
             PAMlib.extractsurface(p + 1, 10, self.nvert, self.npoly,
                                   self.verts, self.poly_vert))
Exemplo n.º 36
0
 def extractSurfaces(self):
     self.P = []
     for p in range(self.npoly):
         self.P.append(PAMlib.extractsurface(p + 1, 10, self.nvert, self.npoly, self.verts, self.poly_vert))
Exemplo n.º 37
0
 def extractEdges(self, JQ, u1, u2, v1, v2):
     nu1, nu2, nv1, nv2 = self.countJunctionEdges(JQ, u1, u2, v1, v2)
     nP = self.n * (nu1 + nu2 + nv1 + nv2)
     return PAMlib.extractedges(nP, self.n, nu1, nu2, nv1, nv2, self.nvert, u1, u2, v1, v2, self.verts)
Exemplo n.º 38
0
 def createInterface(self, n, edge1, edge2, swap=False):
     P = PAMlib.createinterface(n, edge1.shape[0], edge1, edge2)
     if swap:
         P = numpy.swapaxes(P, 0, 1)
     return P
Exemplo n.º 39
0
 def createInterface(self, n, edge1, edge2, swap=False):
     P = PAMlib.createinterface(n, edge1.shape[0], edge1, edge2)
     if swap:
         P = numpy.swapaxes(P, 0, 1)
     return P
Exemplo n.º 40
0
 def getQuadIndices(self, JQ):
     if len(JQ) == 0:
         return PAMlib.getquadindices(1, self.npoly, [-1])
     else:
         return PAMlib.getquadindices(len(JQ), self.npoly, JQ)
Exemplo n.º 41
0
 def compute(self):
     mu,mv = self.P.shape[:2]
     nu,nv = self.shp0
     P = self.P
     Tu,Tv = self.T
     return PAMlib.computeparameter(mu, mv, nu, nv, P, Tu, Tv)
Exemplo n.º 42
0
 def countJunctionEdges(self, JQ, u1, u2, v1, v2):
     return PAMlib.countjunctionedges(
         len(JQ), self.nvert, self.nquad, u1, u2, v1, v2, JQ, self.verts, self.poly_vert
     )
Exemplo n.º 43
0
 def importEdges(self, edges):
     self.edges = PAMlib.getedges(edges.shape[0], edges)
     self.verts = PAMlib.getverts(numpy.max(self.edges[:, :2]), edges.shape[0], edges, self.edges)
     self.nedge = self.edges.shape[0]
     self.nvert = self.verts.shape[0]
Exemplo n.º 44
0
    def computeStructure(self, P):
        oml0 = self.oml0
        Ms = self.Ms
        Js = self.Js
        layout = self.layout
        skinIndices = self.getSkinIndices()

        C = numpy.zeros((4, 2), order='F')
        As = []
        Jns = []
        Jus = []
        col = 0
        for s in range(len(skinIndices)):
            n = max(self.quad_indices[:, s]) * self.layout.n**2
            Aa = numpy.ones(n)
            Ai = numpy.linspace(0, n - 1, n)
            Aj = numpy.linspace(0, n - 1, n) + col
            As.append(
                scipy.sparse.csr_matrix((Aa, (Ai, Aj)), shape=(n, P.shape[0])))
            Jn = []
            Ju = []
            col += n
            for f in skinIndices[s]:
                for k in range(Js[f].shape[0]):
                    C[0, :] = oml0.C[Ms[f][Js[f][k, 0], Js[f][k, 1]], :2]
                    C[1, :] = oml0.C[Ms[f][Js[f][k, 0], Js[f][k, 3]], :2]
                    C[2, :] = oml0.C[Ms[f][Js[f][k, 2], Js[f][k, 1]], :2]
                    C[3, :] = oml0.C[Ms[f][Js[f][k, 2], Js[f][k, 3]], :2]
                    nu1, nu2, nv1, nv2 = layout.countJunctionEdges(
                        self.JQs[s], min(C[:, 0]), max(C[:, 0]), min(C[:, 1]),
                        max(C[:, 1]))
                    Jn.append([nu1, nu2, nv1, nv2])
                    Ju.append([
                        min(C[:, 0]),
                        max(C[:, 0]),
                        min(C[:, 1]),
                        max(C[:, 1])
                    ])
                    nP = layout.n * (nu1 + nu2 + nv1 + nv2)
                    col += nP
            if Jn == []:
                Jn.append([-1, -1, -1, -1])
                Ju.append([-1, -1, -1, -1])
            Jns.append(numpy.array(Jn, int, order='F'))
            Jus.append(numpy.array(Ju, order='F'))

        nM = len(self.keys)
        members = numpy.zeros((nM, 34), order='F')
        for i in range(nM):
            member = self.members[self.keys[i]]
            members[i, :4] = [
                member.domain, member.shape, member.nmem, member.ndiv
            ]
            members[i, 4:16] = member.A1 + member.B1 + member.C1 + member.D1
            members[i, 16:28] = member.A2 + member.B2 + member.C2 + member.D2
            members[i, 28:] = [
                member.tx, member.ty, member.rx, member.ry, member.n1,
                member.n2
            ]

        nP, nS = PAMlib.countinternalnodes(self.layout.n, nM, members)
        P2, M, S = PAMlib.computeinternalnodes(nP, nS, self.layout.n, nM,
                                               members)
        nA = PAMlib.countannz(nP, layout.nvert, layout.nquad, layout.verts,
                              layout.poly_vert, self.quad_indices, P2, M)
        if len(skinIndices) == 1:
            Aa, Ai, Aj = PAMlib.assembleamtx(
                nA, self.layout.n, nP, Jns[0].shape[0], Jns[0].shape[0],
                self.layout.nvert, self.layout.nquad, Jns[0], Jns[0], Jus[0],
                Jus[0], self.quad_indices, self.layout.verts,
                self.layout.poly_vert, P2, M)
        else:
            Aa, Ai, Aj = PAMlib.assembleamtx(
                nA, self.layout.n, nP, Jns[0].shape[0], Jns[1].shape[0],
                self.layout.nvert, self.layout.nquad, Jns[0], Jns[1], Jus[0],
                Jus[1], self.quad_indices, self.layout.verts,
                self.layout.poly_vert, P2, M)
        As.append(
            scipy.sparse.csr_matrix((Aa, (Ai, Aj)),
                                    shape=(max(Ai) + 1, P.shape[0])))

        return As, S
Exemplo n.º 45
0
    def initializeSurfaces(self):
        def get(P, u, v, d):
            edge = P[u,:,:] if not u==None else P[:,v,:]
            return edge if d==1 else edge[::-1,:]

        getM = lambda f, i, j: self.mComp.Ps[self.mComp.Ks[f][i,j]]
        getI = lambda i, j: self.Ps[self.Ks[0][i,j]]
        getF = lambda i, j: self.rotate(self.fComp.Ps[self.fK[i,j]])

        def copy(iI, jI, fM, iM, jM, uI=None, vI=None, uM=None, vM=None, d=1):
            edgeI = get(getI(iI, jI), uI, vI, 1)
            edgeM = get(getM(fM, iM, jM), uM, vM, d)
            edgeI[:,:] = edgeM[:,:]

        def copy2(i, j, u=None, v=None):
            edgeI = get(getI(i, j), u, v, 1)
            edgeF = get(getF(i, j), u, v, 1)
            edgeI[:,:] = edgeF[:,:]

        verts = self.initializeVerts()
        
        nP = self.nP
        ni = self.ni
        nj = self.nj
        si = self.si
        sj = self.sj

        self.Ps = []
        self.Ks = [-numpy.ones((si[3],sj[3]),int)]
        counter = 0
        for j in range(sj[3]):
            for i in range(si[3]):
                if i<si[1] or j<sj[1] or i>=si[2] or j>=sj[2]:
                    self.Ps.append(numpy.zeros((nP,nP,3),order='F'))
                    self.Ks[0][i,j] = counter
                    counter += 1

        for b in range(3):
            for a in range(3):
                for j in range(nj[b]):
                    jj = sj[b] + j
                    for i in range(ni[a]):
                        ii = si[a] + i
                        if not self.Ks[0][ii,jj]==-1:
                            self.Ps[self.Ks[0][ii,jj]][:,:,:] = PAMlib.bilinearinterp(nP, ni[a], nj[b], i+1, j+1, verts[a:a+2,b:b+2,:])

        for i in [0,-1]:
            for j in range(self.Ks[0].shape[1]):
                copy2(i, j, u=i)
        for j in [0,-1]:
            for i in range(self.Ks[0].shape[0]):
                copy2(i, j, v=j)

        if not self.mSide==-1:
            mComp = self.mComp
            ii = si[1] - 1
            for j in range(nj[1]):
                jj = sj[1] + j
                if self.mSide==0:
                    copy(ii, jj, 0, -1-j, 0, uI=-1, vM=0, d=-1)
                else:
                    copy(ii, jj, 0, j, -1, uI=-1, vM=-1, d=1)
            ii = si[2]
            for j in range(nj[1]):
                jj = sj[1] + j
                if self.mSide==0:
                    copy(ii, jj, 1, j, 0, uI=0, vM=0, d=1)
                else:
                    copy(ii, jj, 1, -1-j, -1, uI=0, vM=-1, d=-1)
Exemplo n.º 46
0
    def initializeSurfaces(self):
        def get(P, u, v, d):
            edge = P[u, :, :] if not u == None else P[:, v, :]
            return edge if d == 1 else edge[::-1, :]

        getM = lambda f, i, j: self.mComp.Ps[self.mComp.Ks[f][i, j]]
        getI = lambda i, j: self.Ps[self.Ks[0][i, j]]
        getF = lambda i, j: self.rotate(self.fComp.Ps[self.fK[i, j]])

        def copy(iI, jI, fM, iM, jM, uI=None, vI=None, uM=None, vM=None, d=1):
            edgeI = get(getI(iI, jI), uI, vI, 1)
            edgeM = get(getM(fM, iM, jM), uM, vM, d)
            edgeI[:, :] = edgeM[:, :]

        def copy2(i, j, u=None, v=None):
            edgeI = get(getI(i, j), u, v, 1)
            edgeF = get(getF(i, j), u, v, 1)
            edgeI[:, :] = edgeF[:, :]

        verts = self.initializeVerts()

        nP = self.nP
        ni = self.ni
        nj = self.nj
        si = self.si
        sj = self.sj

        self.Ps = []
        self.Ks = [-numpy.ones((si[3], sj[3]), int)]
        counter = 0
        for j in range(sj[3]):
            for i in range(si[3]):
                if i < si[1] or j < sj[1] or i >= si[2] or j >= sj[2]:
                    self.Ps.append(numpy.zeros((nP, nP, 3), order='F'))
                    self.Ks[0][i, j] = counter
                    counter += 1

        for b in range(3):
            for a in range(3):
                for j in range(nj[b]):
                    jj = sj[b] + j
                    for i in range(ni[a]):
                        ii = si[a] + i
                        if not self.Ks[0][ii, jj] == -1:
                            self.Ps[self.Ks[0][
                                ii, jj]][:, :, :] = PAMlib.bilinearinterp(
                                    nP, ni[a], nj[b], i + 1, j + 1,
                                    verts[a:a + 2, b:b + 2, :])

        for i in [0, -1]:
            for j in range(self.Ks[0].shape[1]):
                copy2(i, j, u=i)
        for j in [0, -1]:
            for i in range(self.Ks[0].shape[0]):
                copy2(i, j, v=j)

        if not self.mSide == -1:
            mComp = self.mComp
            ii = si[1] - 1
            for j in range(nj[1]):
                jj = sj[1] + j
                if self.mSide == 0:
                    copy(ii, jj, 0, -1 - j, 0, uI=-1, vM=0, d=-1)
                else:
                    copy(ii, jj, 0, j, -1, uI=-1, vM=-1, d=1)
            ii = si[2]
            for j in range(nj[1]):
                jj = sj[1] + j
                if self.mSide == 0:
                    copy(ii, jj, 1, j, 0, uI=0, vM=0, d=1)
                else:
                    copy(ii, jj, 1, -1 - j, -1, uI=0, vM=-1, d=-1)
Exemplo n.º 47
0
 def compute(self):
     mu, mv = self.P.shape[:2]
     nu, nv = self.shp0
     P = self.P
     Tu, Tv = self.T
     return PAMlib.computeparameter(mu, mv, nu, nv, P, Tu, Tv)