def velocity_matrix(ra: MatrixVector, rb: MatrixVector, rc: MatrixVector, betm: float = 1.0, tol: float = 1e-12): if ra.shape != rb.shape: return ValueError() numi = rc.shape[0] numj = ra.shape[1] ra = ra.repeat(numi, axis=0) rb = rb.repeat(numi, axis=0) rc = rc.repeat(numj, axis=1) a = rc - ra b = rc - rb a.x = a.x / betm b.x = b.x / betm am = a.return_magnitude() bm = b.return_magnitude() # Velocity from Bound Vortex adb = elementwise_dot_product(a, b) abm = multiply(am, bm) dm = multiply(abm, abm + adb) axb = elementwise_cross_product(a, b) axbm = axb.return_magnitude() chki = (axbm == 0.0) chki = logical_and(axbm >= -tol, axbm <= tol) veli = elementwise_multiply(axb, divide(am + bm, dm)) veli.x[chki] = 0.0 veli.y[chki] = 0.0 veli.z[chki] = 0.0 # Velocity from Trailing Vortex A axx = MatrixVector(zeros(a.shape, dtype=float), a.z, -a.y) axxm = axx.return_magnitude() chka = (axxm == 0.0) vela = elementwise_divide(axx, multiply(am, am - a.x)) vela.x[chka] = 0.0 vela.y[chka] = 0.0 vela.z[chka] = 0.0 # Velocity from Trailing Vortex B bxx = MatrixVector(zeros(b.shape, dtype=float), b.z, -b.y) bxxm = bxx.return_magnitude() chkb = (bxxm == 0.0) velb = elementwise_divide(bxx, multiply(bm, bm - b.x)) velb.x[chkb] = 0.0 velb.y[chkb] = 0.0 velb.z[chkb] = 0.0 return veli, vela, velb
def vel_doublet_matrix(av, am, bv, bm): adb = elementwise_dot_product(av, bv) abm = multiply(am, bm) dm = multiply(abm, abm + adb) axb = elementwise_cross_product(av, bv) axbm = axb.return_magnitude() chki = (axbm == 0.0) chki = logical_and(axbm >= -tol, axbm <= tol) velvl = elementwise_multiply(axb, divide(am + bm, dm)) velvl.x[chki] = 0.0 velvl.y[chki] = 0.0 velvl.z[chki] = 0.0 return velvl
def vel_doublet_matrix(av, am, bv, bm): adb = elementwise_dot_product(av, bv) abm = multiply(am, bm) dm = multiply(abm, abm+adb) axb = elementwise_cross_product(av, bv) axbm = axb.return_magnitude() chki = (axbm == 0.0) chki = logical_and(axbm >= -tol, axbm <= tol) chkd = absolute(dm) < tol fac = zeros(axbm.shape, dtype=float) divide(am+bm, dm, where=logical_not(chkd), out=fac) velvl = elementwise_multiply(axb, fac) velvl.x[chki] = 0.0 velvl.y[chki] = 0.0 velvl.z[chki] = 0.0 return velvl
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 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 diryab(self): if self._diryab is None: self._diryab = elementwise_cross_product(self.dirzab, self.dirxab) return self._diryab