class Component2(object): """ Base class for Wing, Body, and Junction components. """ def __init__(self): self.Ps = [] self.Ks = [] self.oml0 = [] 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 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 def translatePoints(self, dx, dy, dz): for k in range(len(self.Ps)): self.Ps[k][:, :, 0] += dx self.Ps[k][:, :, 1] += dy self.Ps[k][:, :, 2] += dz 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) def initializeDOFs(self): oml0 = self.oml0 Ks = self.Ks Qs = [] Ns = [] for f in range(len(Ks)): ni = self.getni(f, 0) nj = self.getni(f, 1) Qs.append(numpy.zeros((sum(ni) + 1, sum(nj) + 1, 3), complex)) Ns.append(numpy.zeros((sum(ni) + 1, sum(nj) + 1, 5), int)) Ns[f][:, :, :] = -1 for j in range(Ks[f].shape[1]): for i in range(Ks[f].shape[0]): surf = Ks[f][i, j] if surf != -1: for v in range(nj[j] + 1): jj = sum(nj[:j]) + v for u in range(ni[i] + 1): ii = sum(ni[:i]) + u uType = self.classifyC(u, ii, ni[i] + 1, Ns[f].shape[0]) vType = self.classifyC(v, jj, nj[j] + 1, Ns[f].shape[1]) isInteriorDOF = uType == 2 and vType == 2 if isInteriorDOF or self.isExteriorDOF(f, uType, vType, i, j): Ns[f][ii, jj, 0] = oml0.getIndex(surf, u, v, 2) Ns[f][ii, jj, 1] = i Ns[f][ii, jj, 2] = u Ns[f][ii, jj, 3] = j Ns[f][ii, jj, 4] = v self.Qs = Qs self.Ns = Ns def classifyC(self, u, i, lenu, leni): if i == 0: return 0 elif i == leni - 1: return -1 elif u == 0: return 1 elif u == lenu - 1: return 1 else: return 2 def computeDims(self, aircraft): ndims = int(numpy.max(abs(self.faces))) oml0 = self.oml0 Ks = self.Ks dims = [] for d in range(ndims): dims.append([]) for f in range(self.faces.shape[0]): for k in range(2): d = abs(self.faces[f, k]) - 1 dims[d] = numpy.zeros(Ks[f].shape[k], int) for f in range(self.faces.shape[0]): for i in range(Ks[f].shape[0]): for j in range(Ks[f].shape[1]): surf = Ks[f][i, j] if not surf == -1: for k in range(2): edge = oml0.surf_edge[surf, k, 0] group = oml0.edge_group[abs(edge) - 1] - 1 m = oml0.group_m[group] - 1 d = abs(self.faces[f, k]) - 1 if k == 0: index = i else: index = j if self.faces[f, k] > 0: dims[d][index] = int(m) else: dims[d][-index - 1] = int(m) self.dims = dims def getni(self, f, a): d = abs(self.faces[f, a]) - 1 if self.faces[f, a] > 0: return self.dims[d] else: return self.dims[d][::-1] def setC1(self, t, f, i=None, j=None, u=None, v=None, d=None, val=True): """ Set C1 continuity t: {string} surface or edge C1 f: face index i,j: surface index both given: only consider [i,j] surface one given: loop through and apply to all of the other index none given: apply to all surfaces u,v: edge/vert index (for surfC1) both given: only consider [u,v] corner/side one given: loop through and apply to all of the other index none given: apply to all corners/sides u,v,d: side index (for edgeC1) """ if t == "surf": func = self.setSurfC1 elif t == "edge": func = self.setEdgeC1 if (not i == None) and (not j == None): func(f, i, j, u, v, d, val) elif not i == None: for j in range(self.Ks[f].shape[1]): func(f, i, j, u, v, d, val) elif not j == None: for i in range(self.Ks[f].shape[0]): func(f, i, j, u, v, d, val) else: for j in range(self.Ks[f].shape[1]): for i in range(self.Ks[f].shape[0]): func(f, i, j, u, v, d, val) def setSurfC1(self, f, i, j, u, v, d, val): oml0 = self.oml0 surf = self.Ks[f][i, j] if not surf == -1: if u == None and v == None: oml0.surf_c1[surf, :, :] = val elif u == None: oml0.surf_c1[surf, :, v] = val elif v == None: oml0.surf_c1[surf, u, :] = val else: oml0.surf_c1[surf, u, v] = val def setEdgeC1(self, f, i, j, u, v, d, val): oml0 = self.oml0 surf = self.Ks[f][i, j] if not surf == -1: if u == None: edge = oml0.surf_edge[surf, 0, v] else: edge = oml0.surf_edge[surf, 1, u] if d == None: oml0.edge_c1[abs(edge) - 1, :] = val elif edge > 0: oml0.edge_c1[abs(edge) - 1, d] = val else: oml0.edge_c1[abs(edge) - 1, 1 - abs(d)] = val def setCornerC1(self, f, i=0, j=0, val=True): self.setC1("edge", f, i=i, j=j, u=i, d=j, val=val) self.setC1("edge", f, i=i, j=j, v=j, d=i, val=val) def check(self, uType, vType, u=None, v=None): if u == None: uVal = uType == 2 else: uVal = uType == u if v == None: vVal = vType == 2 else: vVal = vType == v return uVal and vVal def computeMs(self): oml0 = self.oml0 Ks = self.Ks Ms = [] for f in range(len(Ks)): ni = self.getni(f, 0) nj = self.getni(f, 1) Ms.append(numpy.zeros((sum(ni) + 1, sum(nj) + 1), int)) Ms[f][:, :] = -1 for j in range(Ks[f].shape[1]): for i in range(Ks[f].shape[0]): surf = Ks[f][i, j] if surf != -1: for v in range(nj[j] + 1): jj = sum(nj[:j]) + v for u in range(ni[i] + 1): ii = sum(ni[:i]) + u Ms[f][ii, jj] = oml0.getIndex(surf, u, v, 1) self.Ms = Ms def findJunctions(self): oml0 = self.oml0 Ks = self.Ks Js = [] for f in range(len(Ks)): ni = self.getni(f, 0) nj = self.getni(f, 1) k0 = Ks[f].shape[0] k1 = Ks[f].shape[1] SPs = [] EPs = [] for j in range(k1): for i in range(k0): if Ks[f][i, j] == -1: SPs.append([i, j]) EPs.append([i, j]) if (i > 0 and Ks[f][i - 1, j] == -1) or (j > 0 and Ks[f][i, j - 1] == -1): SPs.pop() if (i < k0 - 1 and Ks[f][i + 1, j] == -1) or (j < k1 - 1 and Ks[f][i, j + 1] == -1): EPs.pop() J = numpy.zeros((len(SPs), 4), int) for s in range(len(SPs)): SP = SPs[s] for e in range(len(EPs)): EP = EPs[e] if SP[0] <= EP[0] and SP[1] <= EP[1]: if numpy.linalg.norm(1 + Ks[f][SP[0] : EP[0] + 1, SP[1] : EP[1] + 1]) < 1e-14: J[s, :] = [sum(ni[: SP[0]]), sum(nj[: SP[1]]), sum(ni[: EP[0] + 1]), sum(nj[: EP[1] + 1])] Js.append(J) self.Js = Js def flattenGeometry(self): oml0 = self.oml0 Ms = self.Ms for f in range(len(Ms)): ni = Ms[f].shape[0] nj = Ms[f].shape[1] for i in range(ni): for j in range(nj): oml0.C[Ms[f][i, j], :] = self.getFlattenedC(f, i, j, ni, nj) oml0.computePointsC() def initializeLayout(self): def getv(r, v1, v2): return numpy.array(v1) * (1 - r) + numpy.array(v2) * r oml0 = self.oml0 Ms = self.Ms Js = self.Js edges = [] edges.append([0, 0, 0, 1]) edges.append([0, 0, 1, 0]) edges.append([0, 1, 1, 1]) edges.append([1, 0, 1, 1]) skinIndices = self.getSkinIndices() for s in range(len(skinIndices)): for f in skinIndices[s]: for k in range(Js[f].shape[0]): C11 = oml0.C[Ms[f][Js[f][k, 0], Js[f][k, 1]], :2] C12 = oml0.C[Ms[f][Js[f][k, 0], Js[f][k, 3]], :2] C21 = oml0.C[Ms[f][Js[f][k, 2], Js[f][k, 1]], :2] C22 = oml0.C[Ms[f][Js[f][k, 2], Js[f][k, 3]], :2] edges.append([C11[0], C11[1], C12[0], C12[1]]) edges.append([C11[0], C11[1], C21[0], C21[1]]) edges.append([C12[0], C12[1], C22[0], C22[1]]) edges.append([C21[0], C21[1], C22[0], C22[1]]) for m in self.keys: member = self.members[m] for i in range(member.nmem): if member.nmem == 1: ii = 0 else: ii = i / (member.nmem - 1) A = getv(ii, member.A1, member.A2) B = getv(ii, member.B1, member.B2) C = getv(ii, member.C1, member.C2) D = getv(ii, member.D1, member.D2) for j in range(member.ndiv): if (B[2] == 0 and C[2] == 0) or (B[2] == 1 and C[2] == 1): V0 = getv(j / member.ndiv, B, C) V1 = getv((j + 1) / member.ndiv, B, C) edges.append([V0[0], V0[1], V1[0], V1[1]]) if (A[2] == 0 and D[2] == 0) or (A[2] == 1 and D[2] == 1): V0 = getv(j / member.ndiv, A, D) V1 = getv((j + 1) / member.ndiv, A, D) edges.append([V0[0], V0[1], V1[0], V1[1]]) self.layout = Layout(6, self.getAR(), 1, numpy.array(edges)) def findJunctionQuadsAndEdges(self): oml0 = self.oml0 Ms = self.Ms Js = self.Js C = numpy.zeros((4, 2)) ctd = numpy.zeros(2) nquad = self.layout.nquad nedge = self.layout.nedge edges = self.layout.edges verts = self.layout.verts poly_vert = self.layout.poly_vert skinIndices = self.getSkinIndices() JQs = [] JEs = [] quad_indices = [] for s in range(len(skinIndices)): JQ = [] for f in skinIndices[s]: for q in range(nquad): ctd[:] = 0 for k in range(4): ctd[:] += 0.25 * verts[poly_vert[q, k] - 1, :] 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] if ( min(C[:, 0]) < ctd[0] and ctd[0] < max(C[:, 0]) and min(C[:, 1]) < ctd[1] and ctd[1] < max(C[:, 1]) ): JQ.append(q + 1) if JQ == []: JQ.append(-1) JQs.append(JQ) JE = [] for f in skinIndices[s]: for e in range(nedge): ctd[:] = 0 for k in range(2): ctd[:] += 0.5 * verts[edges[e, k] - 1, :] 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] if ( min(C[:, 0]) < ctd[0] and ctd[0] < max(C[:, 0]) and min(C[:, 1]) < ctd[1] and ctd[1] < max(C[:, 1]) ): JEs.append(e + 1) JEs.append(JE) quad_indices.append(self.layout.getQuadIndices(JQ)) if len(quad_indices) == 1: quad_indices.append(quad_indices[0]) self.JQs = JQs self.JEs = JEs self.quad_indices = numpy.array(quad_indices, order="F").T def projectSkins(self): oml0 = self.oml0 Ms = self.Ms Js = self.Js skinIndices = self.getSkinIndices() C = numpy.zeros((4, 2), order="F") Bs = [] Ss = [] quad_indices = [] for s in range(len(skinIndices)): Ps = [] P, S = self.layout.extractFlattened(self.JQs[s], max(self.quad_indices[:, s])) Ps.append(P) Ss.append(S) 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] P = self.layout.extractEdges(self.JQs[s], min(C[:, 0]), max(C[:, 0]), min(C[:, 1]), max(C[:, 1])) Ps.append(P) P = numpy.vstack(Ps) surfindices = [] for f in skinIndices[s]: surfindices.append(self.Ks[f].flatten()) surfs = numpy.unique(numpy.hstack(surfindices)) if surfs[0] == -1: surfs = numpy.delete(surfs, 0) Q = numpy.zeros((P.shape[0], 3)) Q[:, 2] = 1.0 ss, u, v = oml0.computeProjection(P, surfs=surfs, Q=Q) Bs.append(oml0.computeBases(ss, u, v)) B = oml0.vstackSparse(Bs) BM = B.dot(oml0.M) P = BM.dot(oml0.Q) As, S = self.computeStructure(P) Ss.append(S) A = oml0.vstackSparse(As) ABM = A.dot(BM) S = numpy.vstack(Ss) self.strABM = ABM self.strS = S 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 def buildStructure(self): self.computeMs() self.findJunctions() self.flattenGeometry() self.initializeLayout() self.findJunctionQuadsAndEdges() self.projectSkins() def addMembers( self, name, domain, shape, nmem, ndiv, A1=None, B1=None, C1=None, D1=None, A2=None, B2=None, C2=None, D2=None, tx=0.5, ty=0.5, rx=1.0, ry=1.0, n1=5, n2=5, ): if A2 == None: A2 = [-1, -1, -1] B2 = [-1, -1, -1] C2 = [-1, -1, -1] D2 = [-1, -1, -1] if B1 == None: B1 = [-1, -1, -1] B1[:2] = A1[:2] B1[2] = C1[2] if D1 == None: D1 = [-1, -1, -1] D1[:2] = C1[:2] D1[2] = A1[2] if B2 == None: B2 = [-1, -1, -1] B2[:2] = A2[:2] B2[2] = C2[2] if D2 == None: D2 = [-1, -1, -1] D2[:2] = C2[:2] D2[2] = A2[2] self.members[name] = Member(domain, shape, nmem, ndiv, A1, B1, C1, D1, A2, B2, C2, D2, tx, ty, rx, ry, n1, n2) self.keys.append(name)
class Component2(object): """ Base class for Wing, Body, and Junction components. """ def __init__(self): self.Ps = [] self.Ks = [] self.oml0 = [] 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 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 def translatePoints(self, dx, dy, dz): for k in range(len(self.Ps)): self.Ps[k][:, :, 0] += dx self.Ps[k][:, :, 1] += dy self.Ps[k][:, :, 2] += dz 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) def initializeDOFs(self): oml0 = self.oml0 Ks = self.Ks Qs = [] Ns = [] for f in range(len(Ks)): ni = self.getni(f, 0) nj = self.getni(f, 1) Qs.append(numpy.zeros((sum(ni) + 1, sum(nj) + 1, 3), complex)) Ns.append(numpy.zeros((sum(ni) + 1, sum(nj) + 1, 5), int)) Ns[f][:, :, :] = -1 for j in range(Ks[f].shape[1]): for i in range(Ks[f].shape[0]): surf = Ks[f][i, j] if surf != -1: for v in range(nj[j] + 1): jj = sum(nj[:j]) + v for u in range(ni[i] + 1): ii = sum(ni[:i]) + u uType = self.classifyC(u, ii, ni[i] + 1, Ns[f].shape[0]) vType = self.classifyC(v, jj, nj[j] + 1, Ns[f].shape[1]) isInteriorDOF = (uType == 2 and vType == 2) if isInteriorDOF or self.isExteriorDOF( f, uType, vType, i, j): Ns[f][ii, jj, 0] = oml0.getIndex(surf, u, v, 2) Ns[f][ii, jj, 1] = i Ns[f][ii, jj, 2] = u Ns[f][ii, jj, 3] = j Ns[f][ii, jj, 4] = v self.Qs = Qs self.Ns = Ns def classifyC(self, u, i, lenu, leni): if i == 0: return 0 elif i == leni - 1: return -1 elif u == 0: return 1 elif u == lenu - 1: return 1 else: return 2 def computeDims(self, aircraft): ndims = int(numpy.max(abs(self.faces))) oml0 = self.oml0 Ks = self.Ks dims = [] for d in range(ndims): dims.append([]) for f in range(self.faces.shape[0]): for k in range(2): d = abs(self.faces[f, k]) - 1 dims[d] = numpy.zeros(Ks[f].shape[k], int) for f in range(self.faces.shape[0]): for i in range(Ks[f].shape[0]): for j in range(Ks[f].shape[1]): surf = Ks[f][i, j] if not surf == -1: for k in range(2): edge = oml0.surf_edge[surf, k, 0] group = oml0.edge_group[abs(edge) - 1] - 1 m = oml0.group_m[group] - 1 d = abs(self.faces[f, k]) - 1 if k == 0: index = i else: index = j if self.faces[f, k] > 0: dims[d][index] = int(m) else: dims[d][-index - 1] = int(m) self.dims = dims def getni(self, f, a): d = abs(self.faces[f, a]) - 1 if self.faces[f, a] > 0: return self.dims[d] else: return self.dims[d][::-1] def setC1(self, t, f, i=None, j=None, u=None, v=None, d=None, val=True): """ Set C1 continuity t: {string} surface or edge C1 f: face index i,j: surface index both given: only consider [i,j] surface one given: loop through and apply to all of the other index none given: apply to all surfaces u,v: edge/vert index (for surfC1) both given: only consider [u,v] corner/side one given: loop through and apply to all of the other index none given: apply to all corners/sides u,v,d: side index (for edgeC1) """ if t == 'surf': func = self.setSurfC1 elif t == 'edge': func = self.setEdgeC1 if (not i == None) and (not j == None): func(f, i, j, u, v, d, val) elif not i == None: for j in range(self.Ks[f].shape[1]): func(f, i, j, u, v, d, val) elif not j == None: for i in range(self.Ks[f].shape[0]): func(f, i, j, u, v, d, val) else: for j in range(self.Ks[f].shape[1]): for i in range(self.Ks[f].shape[0]): func(f, i, j, u, v, d, val) def setSurfC1(self, f, i, j, u, v, d, val): oml0 = self.oml0 surf = self.Ks[f][i, j] if not surf == -1: if u == None and v == None: oml0.surf_c1[surf, :, :] = val elif u == None: oml0.surf_c1[surf, :, v] = val elif v == None: oml0.surf_c1[surf, u, :] = val else: oml0.surf_c1[surf, u, v] = val def setEdgeC1(self, f, i, j, u, v, d, val): oml0 = self.oml0 surf = self.Ks[f][i, j] if not surf == -1: if u == None: edge = oml0.surf_edge[surf, 0, v] else: edge = oml0.surf_edge[surf, 1, u] if d == None: oml0.edge_c1[abs(edge) - 1, :] = val elif edge > 0: oml0.edge_c1[abs(edge) - 1, d] = val else: oml0.edge_c1[abs(edge) - 1, 1 - abs(d)] = val def setCornerC1(self, f, i=0, j=0, val=True): self.setC1('edge', f, i=i, j=j, u=i, d=j, val=val) self.setC1('edge', f, i=i, j=j, v=j, d=i, val=val) def check(self, uType, vType, u=None, v=None): if u == None: uVal = uType == 2 else: uVal = uType == u if v == None: vVal = vType == 2 else: vVal = vType == v return uVal and vVal def computeMs(self): oml0 = self.oml0 Ks = self.Ks Ms = [] for f in range(len(Ks)): ni = self.getni(f, 0) nj = self.getni(f, 1) Ms.append(numpy.zeros((sum(ni) + 1, sum(nj) + 1), int)) Ms[f][:, :] = -1 for j in range(Ks[f].shape[1]): for i in range(Ks[f].shape[0]): surf = Ks[f][i, j] if surf != -1: for v in range(nj[j] + 1): jj = sum(nj[:j]) + v for u in range(ni[i] + 1): ii = sum(ni[:i]) + u Ms[f][ii, jj] = oml0.getIndex(surf, u, v, 1) self.Ms = Ms def findJunctions(self): oml0 = self.oml0 Ks = self.Ks Js = [] for f in range(len(Ks)): ni = self.getni(f, 0) nj = self.getni(f, 1) k0 = Ks[f].shape[0] k1 = Ks[f].shape[1] SPs = [] EPs = [] for j in range(k1): for i in range(k0): if Ks[f][i, j] == -1: SPs.append([i, j]) EPs.append([i, j]) if (i > 0 and Ks[f][i - 1, j] == -1) or (j > 0 and Ks[f][i, j - 1] == -1): SPs.pop() if (i < k0 - 1 and Ks[f][i + 1, j] == -1) or ( j < k1 - 1 and Ks[f][i, j + 1] == -1): EPs.pop() J = numpy.zeros((len(SPs), 4), int) for s in range(len(SPs)): SP = SPs[s] for e in range(len(EPs)): EP = EPs[e] if SP[0] <= EP[0] and SP[1] <= EP[1]: if numpy.linalg.norm(1 + Ks[f][SP[0]:EP[0] + 1, SP[1]:EP[1] + 1]) < 1e-14: J[s, :] = [ sum(ni[:SP[0]]), sum(nj[:SP[1]]), sum(ni[:EP[0] + 1]), sum(nj[:EP[1] + 1]) ] Js.append(J) self.Js = Js def flattenGeometry(self): oml0 = self.oml0 Ms = self.Ms for f in range(len(Ms)): ni = Ms[f].shape[0] nj = Ms[f].shape[1] for i in range(ni): for j in range(nj): oml0.C[Ms[f][i, j], :] = self.getFlattenedC(f, i, j, ni, nj) oml0.computePointsC() def initializeLayout(self): def getv(r, v1, v2): return numpy.array(v1) * (1 - r) + numpy.array(v2) * r oml0 = self.oml0 Ms = self.Ms Js = self.Js edges = [] edges.append([0, 0, 0, 1]) edges.append([0, 0, 1, 0]) edges.append([0, 1, 1, 1]) edges.append([1, 0, 1, 1]) skinIndices = self.getSkinIndices() for s in range(len(skinIndices)): for f in skinIndices[s]: for k in range(Js[f].shape[0]): C11 = oml0.C[Ms[f][Js[f][k, 0], Js[f][k, 1]], :2] C12 = oml0.C[Ms[f][Js[f][k, 0], Js[f][k, 3]], :2] C21 = oml0.C[Ms[f][Js[f][k, 2], Js[f][k, 1]], :2] C22 = oml0.C[Ms[f][Js[f][k, 2], Js[f][k, 3]], :2] edges.append([C11[0], C11[1], C12[0], C12[1]]) edges.append([C11[0], C11[1], C21[0], C21[1]]) edges.append([C12[0], C12[1], C22[0], C22[1]]) edges.append([C21[0], C21[1], C22[0], C22[1]]) for m in self.keys: member = self.members[m] for i in range(member.nmem): if member.nmem == 1: ii = 0 else: ii = i / (member.nmem - 1) A = getv(ii, member.A1, member.A2) B = getv(ii, member.B1, member.B2) C = getv(ii, member.C1, member.C2) D = getv(ii, member.D1, member.D2) for j in range(member.ndiv): if (B[2] == 0 and C[2] == 0) or (B[2] == 1 and C[2] == 1): V0 = getv(j / member.ndiv, B, C) V1 = getv((j + 1) / member.ndiv, B, C) edges.append([V0[0], V0[1], V1[0], V1[1]]) if (A[2] == 0 and D[2] == 0) or (A[2] == 1 and D[2] == 1): V0 = getv(j / member.ndiv, A, D) V1 = getv((j + 1) / member.ndiv, A, D) edges.append([V0[0], V0[1], V1[0], V1[1]]) self.layout = Layout(6, self.getAR(), 1, numpy.array(edges)) def findJunctionQuadsAndEdges(self): oml0 = self.oml0 Ms = self.Ms Js = self.Js C = numpy.zeros((4, 2)) ctd = numpy.zeros(2) nquad = self.layout.nquad nedge = self.layout.nedge edges = self.layout.edges verts = self.layout.verts poly_vert = self.layout.poly_vert skinIndices = self.getSkinIndices() JQs = [] JEs = [] quad_indices = [] for s in range(len(skinIndices)): JQ = [] for f in skinIndices[s]: for q in range(nquad): ctd[:] = 0 for k in range(4): ctd[:] += 0.25 * verts[poly_vert[q, k] - 1, :] 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] if min(C[:, 0]) < ctd[0] and ctd[0] < max( C[:, 0]) and min( C[:, 1]) < ctd[1] and ctd[1] < max(C[:, 1]): JQ.append(q + 1) if JQ == []: JQ.append(-1) JQs.append(JQ) JE = [] for f in skinIndices[s]: for e in range(nedge): ctd[:] = 0 for k in range(2): ctd[:] += 0.5 * verts[edges[e, k] - 1, :] 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] if min(C[:, 0]) < ctd[0] and ctd[0] < max( C[:, 0]) and min( C[:, 1]) < ctd[1] and ctd[1] < max(C[:, 1]): JEs.append(e + 1) JEs.append(JE) quad_indices.append(self.layout.getQuadIndices(JQ)) if len(quad_indices) == 1: quad_indices.append(quad_indices[0]) self.JQs = JQs self.JEs = JEs self.quad_indices = numpy.array(quad_indices, order='F').T def projectSkins(self): oml0 = self.oml0 Ms = self.Ms Js = self.Js skinIndices = self.getSkinIndices() C = numpy.zeros((4, 2), order='F') Bs = [] Ss = [] quad_indices = [] for s in range(len(skinIndices)): Ps = [] P, S = self.layout.extractFlattened(self.JQs[s], max(self.quad_indices[:, s])) Ps.append(P) Ss.append(S) 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] P = self.layout.extractEdges(self.JQs[s], min(C[:, 0]), max(C[:, 0]), min(C[:, 1]), max(C[:, 1])) Ps.append(P) P = numpy.vstack(Ps) surfindices = [] for f in skinIndices[s]: surfindices.append(self.Ks[f].flatten()) surfs = numpy.unique(numpy.hstack(surfindices)) if surfs[0] == -1: surfs = numpy.delete(surfs, 0) Q = numpy.zeros((P.shape[0], 3)) Q[:, 2] = 1.0 ss, u, v = oml0.computeProjection(P, surfs=surfs, Q=Q) Bs.append(oml0.computeBases(ss, u, v)) B = oml0.vstackSparse(Bs) BM = B.dot(oml0.M) P = BM.dot(oml0.Q) As, S = self.computeStructure(P) Ss.append(S) A = oml0.vstackSparse(As) ABM = A.dot(BM) S = numpy.vstack(Ss) self.strABM = ABM self.strS = S 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 def buildStructure(self): self.computeMs() self.findJunctions() self.flattenGeometry() self.initializeLayout() self.findJunctionQuadsAndEdges() self.projectSkins() def addMembers(self, name, domain, shape, nmem, ndiv, A1=None, B1=None, C1=None, D1=None, A2=None, B2=None, C2=None, D2=None, tx=0.5, ty=0.5, rx=1.0, ry=1.0, n1=5, n2=5): if A2 == None: A2 = [-1, -1, -1] B2 = [-1, -1, -1] C2 = [-1, -1, -1] D2 = [-1, -1, -1] if B1 == None: B1 = [-1, -1, -1] B1[:2] = A1[:2] B1[2] = C1[2] if D1 == None: D1 = [-1, -1, -1] D1[:2] = C1[:2] D1[2] = A1[2] if B2 == None: B2 = [-1, -1, -1] B2[:2] = A2[:2] B2[2] = C2[2] if D2 == None: D2 = [-1, -1, -1] D2[:2] = C2[:2] D2[2] = A2[2] self.members[name] = Member(domain, shape, nmem, ndiv, A1, B1, C1, D1, A2, B2, C2, D2, tx, ty, rx, ry, n1, n2) self.keys.append(name)