def dvinddzeta(zetac, Surf_in, IsBound, M_in_bound=None): """ Produces derivatives of induced velocity by Surf_in w.r.t. the zetac point. Derivatives are divided into those associated to the movement of zetac, and to the movement of the Surf_in vertices (DerVert). If Surf_in is bound (IsBound==True), the circulation over the TE due to the wake is not included in the input. If Surf_in is a wake (IsBound==False), derivatives w.r.t. collocation points are computed ad the TE contribution on DerVert. In this case, the chordwise paneling Min_bound of the associated input is required so as to calculate Kzeta and correctly allocate the derivative matrix. The output derivatives are: - Dercoll: 3 x 3 matrix - Dervert: 3 x 3*Kzeta (if Surf_in is a wake, Kzeta is that of the bound) Warning: zetac must be contiguously stored! """ M_in, N_in = Surf_in.maps.M, Surf_in.maps.N Kzeta_in = Surf_in.maps.Kzeta shape_zeta_in = (3, M_in + 1, N_in + 1) # allocate matrices Dercoll = np.zeros((3, 3)) if IsBound: """ Bound: scan everthing, and include every derivative. The TE is not scanned twice""" Dervert = np.zeros((3, 3 * Kzeta_in)) for pp_in in itertools.product(range(0, M_in), range(0, N_in)): mm_in, nn_in = pp_in # zeta_panel_in=Surf_in.get_panel_vertices_coords(mm_in,nn_in) zeta_panel_in = Surf_in.zeta[:, [ mm_in + 0, mm_in + 1, mm_in + 1, mm_in + 0 ], [nn_in + 0, nn_in + 0, nn_in + 1, nn_in + 1]].T # get local derivatives der_zetac, der_zeta_panel = eval_panel_cpp( zetac, zeta_panel_in, gamma_pan=Surf_in.gamma[mm_in, nn_in]) ### Mid-segment point contribution Dercoll += der_zetac ### Panel vertices contribution for vv_in in range(4): # get vertices m,n indices mm_v, nn_v = mm_in + dmver[vv_in], nn_in + dnver[vv_in] # get vertices 1d index jj_v = [ np.ravel_multi_index((cc, mm_v, nn_v), shape_zeta_in) for cc in range(3) ] Dervert[:, jj_v] += der_zeta_panel[vv_in, :, :] else: """ All segments are scanned when computing the contrib. Dercoll. The TE is scanned a second time to include the contrib. due to the TE elements moviment. The Dervert shape is computed using the chordwse paneling of the associated bound surface (M_in_bound). """ Kzeta_in_bound = (M_in_bound + 1) * (N_in + 1) Dervert = np.zeros((3, 3 * Kzeta_in_bound)) ### loop all panels (coll. contrib) for pp_in in itertools.product(range(0, M_in), range(0, N_in)): mm_in, nn_in = pp_in # zeta_panel_in=Surf_in.get_panel_vertices_coords(mm_in,nn_in) zeta_panel_in = Surf_in.zeta[:, [ mm_in + 0, mm_in + 1, mm_in + 1, mm_in + 0 ], [nn_in + 0, nn_in + 0, nn_in + 1, nn_in + 1]].T # get local derivatives der_zetac = dbiot.eval_panel_cpp_coll( zetac, zeta_panel_in, gamma_pan=Surf_in.gamma[mm_in, nn_in]) # der_zetac_fast=dbiot.eval_panel_fast_coll( # zetac,zeta_panel_in,gamma_pan=Surf_in.gamma[mm_in,nn_in]) # if np.max(np.abs(der_zetac-der_zetac_fast))>1e-10: # embed() ### Mid-segment point contribution Dercoll += der_zetac ### Re-scan the TE to include vertex contrib. # vertex 0 of wake is vertex 1 of bound (local no.) # vertex 3 of wake is vertex 2 of bound (local no.) vvec = [0, 3] # vertices to include dn = [0, 1] # delta to go from (m,n) panel to (m,n) vertices (on bound) shape_zeta_in_bound = (3, M_in_bound + 1, N_in + 1) for nn_in in range(N_in): # zeta_panel_in=Surf_in.get_panel_vertices_coords(0,nn_in) zeta_panel_in = Surf_in.zeta[:, [0, 1, 1, 0], [ nn_in + 0, nn_in + 0, nn_in + 1, nn_in + 1 ]].T # get local derivatives _, der_zeta_panel = eval_panel_cpp(zetac, zeta_panel_in, gamma_pan=Surf_in.gamma[0, nn_in]) for vv in range(2): nn_v = nn_in + dn[vv] jj_v = [] for cc in range(3): jj_v.append( np.ravel_multi_index((cc, M_in_bound, nn_v), shape_zeta_in_bound)) Dervert[:, jj_v] += der_zeta_panel[vvec[vv], :, :] return Dercoll, Dervert
def run_eval_panel_cpp(): for ii in range(10000): eval_panel_cpp(zetaP, ZetaPanel, 1e-6, gamma_pan=3.) # vortex_radius
def eval_panel_cpp_coll(zetaP, ZetaPanel, vortex_radius, gamma_pan=1.0): DerP, DerVertices = eval_panel_cpp(zetaP, ZetaPanel, vortex_radius, gamma_pan) return DerP
zetaP = np.array([3.0, 5.5, 2.0]) zeta0 = np.array([1.0, 3.0, 0.9]) zeta1 = np.array([5.0, 3.1, 1.9]) zeta2 = np.array([4.8, 8.1, 2.5]) zeta3 = np.array([0.9, 7.9, 1.7]) ZetaPanel = np.array([zeta0, zeta1, zeta2, zeta3]) zetap = 0.3 * zeta1 + 0.7 * zeta2 # ZetaPanel=np.array([[ 1.221, -0.064, -0.085], # [ 1.826, -0.064, -0.141], # [ 1.933, 1.456, -0.142], # [ 1.327, 1.456, -0.087]]) # zetaP=np.array([-0.243, 0.776, 0.037]) ### verify model consistency DPcpp, DVcpp = eval_panel_cpp(zetaP, ZetaPanel, 1e-6, gamma_pan=gamma) # vortex_radius DPexp, DVexp = eval_panel_exp(zetaP, ZetaPanel, gamma_pan=gamma) DPcomp, DVcomp = eval_panel_comp(zetaP, ZetaPanel, gamma_pan=gamma) DPfast, DVfast = eval_panel_fast(zetaP, ZetaPanel, vortex_radius, gamma_pan=gamma) DPfast_coll = eval_panel_fast_coll(zetaP, ZetaPanel, vortex_radius, gamma_pan=gamma) ermax = max(np.max(np.abs(DPcpp - DPexp)), np.max(np.abs(DVcpp - DVexp))) assert ermax < 1e-15, 'eval_panel_cpp not matching with eval_panel_exp' ermax = max(np.max(np.abs(DPcomp - DPexp)), np.max(np.abs(DVcomp - DVexp))) assert ermax < 1e-15, 'eval_panel_comp not matching with eval_panel_exp'
def run_eval_panel_cpp(): for ii in range(10000): eval_panel_cpp(zetaP, ZetaPanel, gamma_pan=3.)
zetaP = np.array([3.0, 5.5, 2.0]) zeta0 = np.array([1.0, 3.0, 0.9]) zeta1 = np.array([5.0, 3.1, 1.9]) zeta2 = np.array([4.8, 8.1, 2.5]) zeta3 = np.array([0.9, 7.9, 1.7]) ZetaPanel = np.array([zeta0, zeta1, zeta2, zeta3]) zetap = 0.3 * zeta1 + 0.7 * zeta2 # ZetaPanel=np.array([[ 1.221, -0.064, -0.085], # [ 1.826, -0.064, -0.141], # [ 1.933, 1.456, -0.142], # [ 1.327, 1.456, -0.087]]) # zetaP=np.array([-0.243, 0.776, 0.037]) ### verify model consistency DPcpp, DVcpp = eval_panel_cpp(zetaP, ZetaPanel, gamma_pan=gamma) DPexp, DVexp = eval_panel_exp(zetaP, ZetaPanel, gamma_pan=gamma) DPcomp, DVcomp = eval_panel_comp(zetaP, ZetaPanel, gamma_pan=gamma) DPfast, DVfast = eval_panel_fast(zetaP, ZetaPanel, gamma_pan=gamma) DPfast_coll = eval_panel_fast_coll(zetaP, ZetaPanel, gamma_pan=gamma) ermax = max(np.max(np.abs(DPcpp - DPexp)), np.max(np.abs(DVcpp - DVexp))) assert ermax < 1e-15, 'eval_panel_cpp not matching with eval_panel_exp' ermax = max(np.max(np.abs(DPcomp - DPexp)), np.max(np.abs(DVcomp - DVexp))) assert ermax < 1e-15, 'eval_panel_comp not matching with eval_panel_exp' ermax = max(np.max(np.abs(DPfast - DPexp)), np.max(np.abs(DVfast - DVexp))) assert ermax < 1e-15, 'eval_panel_fast not matching with eval_panel_exp' ermax = np.max(np.abs(DPfast_coll - DPexp)) assert ermax < 1e-15, 'eval_panel_fast_coll not matching with eval_panel_exp'