def assemble_panels_full(self, time: bool=True, mach: float=0.0): if time: start = perf_counter() shp = (self.numpnl, self.numpnl) apd = zeros(shp, dtype=float) aps = zeros(shp, dtype=float) avd = zero_matrix_vector(shp, dtype=float) avs = zero_matrix_vector(shp, dtype=float) betm = betm_from_mach(mach) for pnl in self.pnls.values(): ind = pnl.ind apd[:, ind], aps[:, ind], avd[:, ind], avs[:, ind] = pnl.influence_coefficients(self.pnts, betx=betm) if self._apd is None: self._apd = {} self._apd[mach] = apd if self._aps is None: self._aps = {} self._aps[mach] = aps if self._avd is None: self._avd = {} self._avd[mach] = avd if self._avs is None: self._avs = {} self._avs[mach] = avs if time: finish = perf_counter() elapsed = finish - start print(f'Full panel assembly time is {elapsed:.3f} seconds.')
def influence_coefficients(self, pnts: MatrixVector, betx: float = 1.0): phiv = zeros(pnts.shape, float) phis = zeros(pnts.shape, float) velv = zero_matrix_vector(pnts.shape, float) vels = zero_matrix_vector(pnts.shape, float) sgnz = self.sign_local_z(pnts, betx=betx) for edg in self.edgs: ephiv, ephis, evelv, evels = edg.influence_coefficients(pnts, sgnz=sgnz, betx=betx) phiv += ephiv phis += ephis velv += evelv vels += evels return phiv, phis, velv, vels
def vel_source_matrix(Qab, rl, phid): velsl = zero_matrix_vector(Qab.shape, dtype=float) velsl.y = -Qab faco = ones(Qab.shape, dtype=float) faco[rl.z != 0.0] = -1.0 velsl.z = multiply(faco, phid) return velsl
def afs(self): if self._afs is None: num = len(self.pnls) numc = len(self.ctrls) self._afs = zero_matrix_vector((num, 2 + 4 * numc), dtype=float) for pnl in self.pnls: lpid = pnl.lpid rrel = pnl.pntc - self.rref self._afs[lpid, 0] = pnl.nrml self._afs[lpid, 1] = -rrel**pnl.nrml for srfc in self.srfcs: for sht in srfc.shts: for control in sht.ctrls: ctrl = sht.ctrls[control] ctup = self.ctrls[control] for pnl in ctrl.pnls: lpid = pnl.lpid rrel = pnl.pntc - self.rref dndlp = pnl.dndl(ctrl.posgain, ctrl.uhvec) self._afs[lpid, ctup[0]] = dndlp self._afs[lpid, ctup[1]] = rrel**dndlp dndln = pnl.dndl(ctrl.neggain, ctrl.uhvec) self._afs[lpid, ctup[2]] = dndln self._afs[lpid, ctup[3]] = rrel**dndln return self._afs
def edge_vector(self, grds: MatrixVector): vecab = zero_matrix_vector((1, self.num), dtype=float) for i in range(self.num): veca = grds[0, i-1] vecb = grds[0, i] vecab[0, i] = vecb-veca return vecab
def update(self): strpres = self.pres.strpres self.frctot = Vector(0.0, 0.0, 0.0) self.momtot = Vector(0.0, 0.0, 0.0) for i, strp in enumerate(self.strc.strps): ind = strp.ind rrel = strp.point - self.rref self.frctot += strpres.stfrc[ind, 0] self.momtot += strpres.stmom[ind, 0] + rrel**strpres.stfrc[ind, 0] self.rfrc, self.rmom = self.strc.rbdy.return_reactions(self.frctot, self.momtot) self.ptfrc = zero_matrix_vector(self.strc.pnts.shape, dtype=float) self.ptmom = zero_matrix_vector(self.strc.pnts.shape, dtype=float) ptfrcb = Vector(0.0, 0.0, 0.0) ptmomb = Vector(0.0, 0.0, 0.0) for i, strp in enumerate(self.strc.strps): ind = strp.ind inda = 2*i indb = inda + 1 ptfrca = ptfrcb ptmoma = ptmomb if inda in self.strc.pntinds: ptfrca -= self.rfrc[self.strc.pntinds[inda]] ptmoma -= self.rmom[self.strc.pntinds[inda]] ptfrcb = ptfrca - strpres.stfrc[ind, 0] ptmomb = ptmoma - strpres.stmom[ind, 0] rrel = strp.point - self.strc.pnts[indb, 0] ptmomb -= rrel**strpres.stfrc[ind, 0] rrel = self.strc.pnts[indb, 0]-self.strc.pnts[inda, 0] ptmomb -= rrel**ptfrca self.ptfrc[inda, 0] = ptfrca self.ptfrc[indb, 0] = ptfrcb self.ptmom[inda, 0] = ptmoma self.ptmom[indb, 0] = ptmomb fx = self.ptfrc.x.transpose().tolist()[0] fy = self.ptfrc.y.transpose().tolist()[0] fz = self.ptfrc.z.transpose().tolist()[0] mx = self.ptmom.x.transpose().tolist()[0] my = self.ptmom.y.transpose().tolist()[0] mz = self.ptmom.z.transpose().tolist()[0] self.frcmin = Vector(min(fx), min(fy), min(fz)) self.frcmax = Vector(max(fx), max(fy), max(fz)) self.mommin = Vector(min(mx), min(my), min(mz)) self.mommax = Vector(max(mx), max(my), max(mz))
def pnts(self): if self._pnts is None: numstrp = len(self.srfc.strps) self._pnts = zero_matrix_vector((2 * numstrp, 1), dtype=float) for i, strp in enumerate(self.srfc.strps): inda = 2 * i indb = inda + 1 self._pnts[inda, 0] = strp.prfa.point self._pnts[indb, 0] = strp.prfb.point return self._pnts
def afg(self, mach: float): if self._afg is None: self._afg = {} if mach not in self._afg: avg = self.avg(mach) afg = zero_matrix_vector(avg.shape, dtype=float) for pnl in self.pnls: if not pnl.noload: afg[pnl.lpid, :] = avg[pnl.lpid, :]**pnl.leni self._afg[mach] = afg return self._afg[mach]
def doublet_influence_coefficients(self, pnts: MatrixVector, betx: float = 1.0): phiv = zeros(pnts.shape, float) velv = zero_matrix_vector(pnts.shape, float) sgnz = self.sign_local_z(pnts, betx=betx) for edg in self.edgs: ephiv, evelv = edg.doublet_influence_coefficients(pnts, sgnz=sgnz, betx=betx) phiv += ephiv velv += evelv return phiv, velv
def vortex_line_points(self, indp: int, nump: int): nums = len(self.strps) num = nums * nump + 1 rpt = zero_matrix_vector((num, 1)) j = 0 for strp in self.strps: pnl = strp.pnls[indp] for i in range(nump): pnt = pnl.pnta + i / nump * pnl.leni rpt[j, 0] = pnt j += 1 rpt[j, 0] = pnl.pntb return rpt
def get_profile(self, offset: bool=True): num = self.cnum*2+1 profile = zero_matrix_vector((1, num), dtype=float) for i in range(self.cnum+1): n = num-i-1 j = n-num profile[0, i] = Vector(self.airfoil.xl[j], 0.0, self.airfoil.yl[j]) profile[0, n] = Vector(self.airfoil.xu[j], 0.0, self.airfoil.yu[j]) profile.z[absolute(profile.z) < tol] = 0.0 profile.z = profile.z*self.thkcor if offset: offvec = Vector(self.xoc, 0.0, self.zoc) profile = profile-offvec return profile
def doublet_influence_coefficients(self, pnts: MatrixVector, betx: float = 1.0): phid = zeros(pnts.shape, dtype=float) veld = zero_matrix_vector(pnts.shape, dtype=float) sgnz = self.sign_local_z(pnts, betx=betx) phida, velda = self.tva.doublet_influence_coefficients(pnts, sgnz=sgnz, betx=betx) phidb, veldb = self.tvb.doublet_influence_coefficients(pnts, sgnz=sgnz, betx=betx) phidab, veldab = self.bvab.doublet_influence_coefficients(pnts, sgnz=sgnz, betx=betx) phid = phida + phidb + phidab veld = velda + veldb + veldab return phid, veld
def assemble_horseshoes_full(self, time: bool=True, mach: float=0.0): if time: start = perf_counter() shp = (self.numpnl, self.numpnl) aph = zeros(shp, dtype=float) avh = zero_matrix_vector(shp, dtype=float) betm = betm_from_mach(mach) for i, hsv in enumerate(self.hsvs): aph[:, i], avh[:, i] = hsv.doublet_influence_coefficients(self.pnts, betx=betm) if self._aph is None: self._aph = {} self._aph[mach] = aph if self._avh is None: self._avh = {} self._avh[mach] = avh if time: finish = perf_counter() elapsed = finish - start print(f'Full horse shoe assembly time is {elapsed:.3f} seconds.')
def unsig(self, mach: float=0.0): if self._unsig is None: self._unsig = {} if mach not in self._unsig: unsig = zero_matrix_vector((self.numpnl, 2+4*self.numctrl), dtype=float) unsig[:, 0] = -self.nrms unsig[:, 1] = elementwise_cross_product(self.rrel, self.nrms) if self.srfcs is not None: for srfc in self.srfcs: for sht in srfc.shts: for control in sht.ctrls: ctrl = sht.ctrls[control] ctup = self.ctrls[control] for pnl in ctrl.pnls: ind = pnl.ind rrel = self.rrel[ind, 0] dndlp = pnl.dndl(ctrl.posgain, ctrl.uhvec) unsig[ind, ctup[0]] = -dndlp unsig[ind, ctup[1]] = -rrel**dndlp dndln = pnl.dndl(ctrl.neggain, ctrl.uhvec) unsig[ind, ctup[2]] = -dndln unsig[ind, ctup[3]] = -rrel**dndln self._unsig[mach] = unsig return self._unsig[mach]
def hsvnrms(self): if self._hsvnrms is None: self._hsvnrms = zero_matrix_vector((self.numhsv, 1), dtype=float) for i, hsv in enumerate(self.hsvs): self._hsvnrms[i, 0] = hsv.nrm return self._hsvnrms
def rg(self): if self._rg is None: self._rg = zero_matrix_vector((self.nump, 1), dtype=float) for pnl in self.pnls: self._rg[pnl.lpid, 0] = pnl.pnti return self._rg
def rc(self): if self._rc is None: self._rc = zero_matrix_vector((self.nump, 1), dtype=float) for pnl in self.pnls: self._rc[pnl.lpid, 0] = pnl.pntc return self._rc
def rb(self): if self._rb is None: self._rb = zero_matrix_vector((1, self.nump), dtype=float) for pnl in self.pnls: self._rb[0, pnl.lpid] = pnl.pntb return self._rb
poly = Poly(grds) #%% # Mesh Points xorg = 0.0 yorg = 0.0 zorg = -0.05 numx = 201 numy = 201 xamp = 2.0 yamp = 2.0 xint = 2*xamp/(numx-1) yint = 2*yamp/(numy-1) pnts = zero_matrix_vector((numy, numx)) for i in range(numy): for j in range(numx): x = xorg-xamp+xint*j y = yorg-yamp+yint*i pnts[i, j] = Vector(x, y, zorg) start = perf_counter() phiv, velv = hsv.doublet_influence_coefficients(pnts) phip, velp = poly.doublet_influence_coefficients(pnts) finished = perf_counter() elapsed = finished-start print(f'Time elapsed is {elapsed:.2f} seconds.') if zorg == 0.0: phiv[absolute(phiv) < 1e-12] = 0.0
def ra(self): if self._ra is None: self._ra = zero_matrix_vector((1, self.nump), dtype=float) for pnl in self.pnls: self._ra[0, pnl.lpid] = pnl.pnta return self._ra
def nrms(self): if self._nrms is None: self._nrms = zero_matrix_vector((self.numpnl, 1), dtype=float) for pnl in self.pnls.values(): self._nrms[pnl.ind, 0] = pnl.nrm return self._nrms
def grdr(self): if self._grdr is None: self._grdr = zero_matrix_vector((1, self.num), dtype=float) for i in range(self.num): self._grdr[0, i] = self.grds[i] - self.pnto return self._grdr
def influence_coefficients(self, pnts: MatrixVector, incvel: bool=True, betx: float=1.0, bety: float=1.0, betz: float=1.0, checktol: bool=False): grdm = self.mach_grids(betx=betx, bety=bety, betz=betz) vecab = self.edge_vector(grdm) vecaxb = self.edge_cross(grdm) dirxab = vecab.to_unit() dirzab = vecaxb.to_unit() diryab = elementwise_cross_product(dirzab, dirxab) nrm = vecaxb.sum().to_unit() rgcs = self.relative_mach(pnts, self.pnto, betx=betx, bety=bety, betz=betz) locz = rgcs*nrm sgnz = ones(locz.shape, dtype=float) sgnz[locz <= 0.0] = -1.0 vecgcs = [] for i in range(self.num): vecgcs.append(self.relative_mach(pnts, self.grds[i], betx=betx, bety=bety, betz=betz)) phid = zeros(pnts.shape, dtype=float) phis = zeros(pnts.shape, dtype=float) if incvel: veld = zero_matrix_vector(pnts.shape, dtype=float) vels = zero_matrix_vector(pnts.shape, dtype=float) for i in range(self.num): # Edge Length dab = vecab[0, i].return_magnitude() # Local Coordinate System dirx = dirxab[0, i] diry = diryab[0, i] dirz = dirzab[0, i] # Vector A in Local Coordinate System veca = vecgcs[i-1] alcs = MatrixVector(veca*dirx, veca*diry, veca*dirz) if checktol: alcs.x[absolute(alcs.x) < tol] = 0.0 alcs.y[absolute(alcs.y) < tol] = 0.0 alcs.z[absolute(alcs.z) < tol] = 0.0 # Vector A Doublet Velocity Potentials phida, amag = phi_doublet_matrix(alcs, sgnz) # Vector B in Local Coordinate System vecb = vecgcs[i] blcs = MatrixVector(vecb*dirx, vecb*diry, vecb*dirz) if checktol: blcs.x[absolute(blcs.x) < tol] = 0.0 blcs.y[absolute(blcs.y) < tol] = 0.0 blcs.z[absolute(blcs.z) < tol] = 0.0 # Vector B Doublet Velocity Potentials phidb, bmag = phi_doublet_matrix(blcs, sgnz) # Edge Doublet Velocity Potentials phidi = phida - phidb # Edge Source Velocity Potentials phisi, Qab = phi_source_matrix(amag, bmag, dab, alcs, phidi) # Add Edge Velocity Potentials phid += phidi phis += phisi # Calculate Edge Velocities if incvel: # Velocities in Local Coordinate System veldi = vel_doublet_matrix(alcs, amag, blcs, bmag) velsi = vel_source_matrix(Qab, alcs, phidi) # Transform to Global Coordinate System and Add dirxi = Vector(dirx.x, diry.x, dirz.x) diryi = Vector(dirx.y, diry.y, dirz.y) dirzi = Vector(dirx.z, diry.z, dirz.z) veld += MatrixVector(veldi*dirxi, veldi*diryi, veldi*dirzi) vels += MatrixVector(velsi*dirxi, velsi*diryi, velsi*dirzi) phid = phid/fourPi phis = phis/fourPi if incvel: veld = veld/fourPi vels = vels/fourPi output = phid, phis, veld, vels else: output = phid, phis return output
def doublet_influence_coefficients(self, pnts: MatrixVector, incvel: bool = True, betx: float = 1.0, bety: float = 1.0, betz: float = 1.0, checktol: bool = False): vecab = Vector(self.vecab.x / betx, self.vecab.y / bety, self.vecab.z / betz) dirxab = vecab.to_unit() dirzab = Vector(self.nrm.x, self.nrm.y, self.nrm.z) diryab = dirzab**dirxab agcs = self.relative_mach(pnts, self.grda, betx=betx, bety=bety, betz=betz) bgcs = self.relative_mach(pnts, self.grdb, betx=betx, bety=bety, betz=betz) locz = agcs * self.nrm sgnz = ones(locz.shape, dtype=float) sgnz[locz <= 0.0] = -1.0 phid = zeros(pnts.shape, dtype=float) if incvel: veld = zero_matrix_vector(pnts.shape, dtype=float) # Vector A in Local Coordinate System alcs = MatrixVector(agcs * dirxab, agcs * diryab, agcs * dirzab) if checktol: alcs.x[absolute(alcs.x) < tol] = 0.0 alcs.y[absolute(alcs.y) < tol] = 0.0 alcs.z[absolute(alcs.z) < tol] = 0.0 # Vector A Doublet Velocity Potentials phida, amag = phi_doublet_matrix(alcs, sgnz) # Vector B in Local Coordinate System blcs = MatrixVector(bgcs * dirxab, bgcs * diryab, bgcs * dirzab) if checktol: blcs.x[absolute(blcs.x) < tol] = 0.0 blcs.y[absolute(blcs.y) < tol] = 0.0 blcs.z[absolute(blcs.z) < tol] = 0.0 # Vector B Doublet Velocity Potentials phidb, bmag = phi_doublet_matrix(blcs, sgnz) # Edge Doublet Velocity Potentials phidi = phida - phidb # Add Edge Velocity Potentials phid += phidi if incvel: # Bound Edge Velocities in Local Coordinate System veldi = vel_doublet_matrix(alcs, amag, blcs, bmag) # Transform to Global Coordinate System and Add dirxi = Vector(dirxab.x, diryab.x, dirzab.x) diryi = Vector(dirxab.y, diryab.y, dirzab.y) dirzi = Vector(dirxab.z, diryab.z, dirzab.z) veld += MatrixVector(veldi * dirxi, veldi * diryi, veldi * dirzi) # Trailing Edge A Coordinate Transformation dirxa = self.diro dirza = self.nrm dirya = -dirza**dirxa alcs = MatrixVector(agcs * dirxa, agcs * dirya, agcs * dirza) # Trailing Edge A Velocity Potential phida, amag = phi_doublet_matrix(alcs, sgnz) phidt = phi_trailing_doublet_matrix(alcs, sgnz) phidi = phida + phidt # Add Trailing Edge A Velocity Potentials phid += phidi # Trailing Edge B Coordinate Transformation if incvel: # Trailing Edge A Velocities in Local Coordinate System veldi = vel_trailing_doublet_matrix(alcs, amag, 1.0) # Transform to Global Coordinate System and Add dirxi = Vector(dirxa.x, dirya.x, dirza.x) diryi = Vector(dirxa.y, dirya.y, dirza.y) dirzi = Vector(dirxa.z, dirya.z, dirza.z) veld += MatrixVector(veldi * dirxi, veldi * diryi, veldi * dirzi) # Trailing Edge B Coordinate Transformation dirxb = self.diro dirzb = self.nrm diryb = dirzb**dirxb blcs = MatrixVector(bgcs * dirxb, bgcs * diryb, bgcs * dirzb) # Trailing Edge B Velocity Potential phidb, bmag = phi_doublet_matrix(blcs, sgnz) phidt = phi_trailing_doublet_matrix(blcs, sgnz) phidi = phidb + phidt # Add Trailing Edge B Velocity Potentials phid += phidi if incvel: # Trailing Edge B Velocities in Local Coordinate System veldi = vel_trailing_doublet_matrix(blcs, bmag, 1.0) # Transform to Global Coordinate System and Add dirxi = Vector(dirxb.x, diryb.x, dirzb.x) diryi = Vector(dirxb.y, diryb.y, dirzb.y) dirzi = Vector(dirxb.z, diryb.z, dirzb.z) veld += MatrixVector(veldi * dirxi, veldi * diryi, veldi * dirzi) # Factors and Outputs phid = phid / fourPi if incvel: veld = veld / fourPi output = phid, veld else: output = phid return output
def pnts(self): if self._pnts is None: self._pnts = zero_matrix_vector((self.numpnl, 1), dtype=float) for pnl in self.pnls.values(): self._pnts[pnl.ind, 0] = pnl.pnto return self._pnts
hsv = HorseShoe(grda, grdb, diro) #%% # Mesh Points xorg = 0.0 yorg = 0.0 zorg = 0.0 numy = 201 numz = 201 yamp = 2.0 zamp = 2.0 yint = 2 * yamp / (numy - 1) zint = 2 * zamp / (numz - 1) pnts = zero_matrix_vector((numz, numy)) for i in range(numz): for j in range(numy): y = yorg - yamp + yint * j z = zorg - zamp + zint * i pnts[i, j] = Vector(xorg, y, z) start = perf_counter() vel = hsv.trefftz_plane_velocities(pnts) finished = perf_counter() elapsed = finished - start print(f'Time elapsed is {elapsed:.2f} seconds.') #%% # Horseshoe Vortex Velocity in X figv = figure(figsize=(12, 12))