def main(): po().prog_title('1.0.0') start_time = time.time() COUNTER = P['COUNTER'] DEL_T = P['DEL_T'] DSTEP = P['DSTEP'] TSTEP = P['TSTEP'] T = [DEL_T*i for i in xrange(COUNTER)] RHO = P['RHO'] RE = P['RE'] SwiP = PC.SwimmerParameters(P['CE'], P['DELTA_CORE'], P['SW_KUTTA']) GeoP = PC.GeoVDVParameters(P['N_BODY'], P['S'], P['C'], P['K'], P['EPSILON']) MotP1 = PC.MotionParameters(0., 0., P['V0'], P['THETA_MAX'], P['F'], P['PHI']) S1 = Swimmer(SwiP, GeoP, MotP1, COUNTER) Swimmers = [S1] po().calc_input(MotP1.THETA_MAX/np.pi*180.,RE,MotP1.THETA_MAX/np.pi*180.,DEL_T) # Data points per cycle == 1/(F*DEL_T) for i in xrange(COUNTER): if i == 0: po().initialize_output(T[i]) else: if np.fmod(i,P['VERBOSITY']) == 0: po().timestep_header(i,T[i]) for Swim in Swimmers: Swim.Body.panel_positions(DSTEP, T[i]) Swim.Body.surface_kinematics(DSTEP, TSTEP, DEL_T, T[i], i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) quilt(Swimmers, RHO, DEL_T, i) wake_rollup(Swimmers, DEL_T, i) archive(S1.Body.AF.x_mid) archive(S1.Body.AF.z_mid) if np.fmod(i,P['VERBOSITY']) == 0: po().solution_output(0,0,0,0,0,0) po().solution_complete_output(i/float(COUNTER-1)*100.) total_time = time.time()-start_time print "Simulation time:", np.round(total_time, 3), "seconds" graph.body_wake_plot(Swimmers)
def wake_shed(self, DEL_T, i): """Updates the positions of the Wake panels. This should only be done once each time step for a swimmer. Args: DEL_T: Time step length. i: Time step number. Edge: Edge panel of separation. Wake: Wake panels. V0: Free-stream velocity. """ Edge = self.Edge Wake = self.Wake V0 = self.V0 # Initialize wake coordinates when i==1 if i == 1: Wake.x[0, :] = Edge.x[-1, :] Wake.y[0, :] = Edge.y[-1, :] Wake.z[0, :] = Edge.z[-1, :] # Wake.x[1:,:] = Wake.x[0,:] + np.arange(1,np.size(Wake.x))*(-V0)*DEL_T # Wake.y[1:,:] = Wake.y[0,:] + np.arange(1,np.size(Wake.y))*(-V0)*DEL_T Wake.x[1:, :] = Wake.x[0, :] + np.arange( 1, Wake.x.shape[1] + 1) * (-V0) * DEL_T Wake.y[1:, :] = Wake.y[0, :] Wake.z[1:, :] = Wake.z[0, :] else: archive(Wake.x, axis=0) archive(Wake.y, axis=0) archive(Wake.z, axis=0) archive(Wake.mu, axis=0) Wake.x[0, :] = Edge.x[-1, :] Wake.y[0, :] = Edge.y[-1, :] Wake.z[0, :] = Edge.z[-1, :] Wake.mu[0, :] = Edge.mu Wake.gamma[0, :] = -Wake.mu[0, :] Wake.gamma[1:-1, :] = Wake.mu[:-1] - Wake.mu[1:, :] Wake.gamma[-1, :] = Wake.mu[-1, :]
def wake_shed(self, DEL_T, i): """Updates the positions of the Wake panels. This should only be done once each time step for a swimmer. Args: DEL_T: Time step length. i: Time step number. Edge: Edge panel of separation. Wake: Wake panels. V0: Free-stream velocity. """ Edge = self.Edge Wake = self.Wake V0 = self.V0 # Initialize wake coordinates when i==1 if i == 1: Wake.x[0,:] = Edge.x[-1,:] Wake.y[0,:] = Edge.y[-1,:] Wake.z[0,:] = Edge.z[-1,:] # Wake.x[1:,:] = Wake.x[0,:] + np.arange(1,np.size(Wake.x))*(-V0)*DEL_T # Wake.y[1:,:] = Wake.y[0,:] + np.arange(1,np.size(Wake.y))*(-V0)*DEL_T Wake.x[1:,:] = Wake.x[0,:] + np.arange(1,Wake.x.shape[1]+1)*(-V0)*DEL_T Wake.y[1:,:] = Wake.y[0,:] Wake.z[1:,:] = Wake.z[0,:] else: archive(Wake.x, axis=0) archive(Wake.y, axis=0) archive(Wake.z, axis=0) archive(Wake.mu, axis=0) Wake.x[0,:] = Edge.x[-1,:] Wake.y[0,:] = Edge.y[-1,:] Wake.z[0,:] = Edge.z[-1,:] Wake.mu[0,:] = Edge.mu Wake.gamma[0,:] = -Wake.mu[0,:] Wake.gamma[1:-1,:] = Wake.mu[:-1]-Wake.mu[1:,:] Wake.gamma[-1,:] = Wake.mu[-1,:]
def wake_shed(self, DEL_T, i): """Updates the positions of the Wake panels. This should only be done once each time step for a swimmer. Args: DEL_T: Time step length. i: Time step number. Edge: Edge panel of separation. Wake: Wake panels. V0: Free-stream velocity. """ Edge = self.Edge Wake = self.Wake V0 = self.V0 if i == 0: pass elif i == 1: # Initialize wake coordinates Wake.x[0] = Edge.x[-1] Wake.z[0] = Edge.z[-1] Wake.x[1:] = Wake.x[0] + np.arange(1,np.size(Wake.x))*(-V0)*DEL_T Wake.z[1:] = Wake.z[0] elif i > 1: archive(Wake.x) archive(Wake.z) archive(Wake.mu) Wake.x[0] = Edge.x[-1] Wake.z[0] = Edge.z[-1] Wake.mu[0] = Edge.mu Wake.gamma[0] = -Wake.mu[0] Wake.gamma[1:-1] = Wake.mu[:-1]-Wake.mu[1:] Wake.gamma[-1] = Wake.mu[-1]
po().calc_input(MotL[0].THETA_MAX/np.pi*180.,RE,MotL[0].THETA_MAX/np.pi*180.,DEL_T) po().initialize_output(T[START_COUNTER]) outerCorr = 1 for i in xrange(START_COUNTER, COUNTER): if i == 0: for Swim in Swimmers: Swim.Body.panel_positions(P, i) Swim.Body.surface_kinematics(P, i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) solve_phi(Swimmers, P, i, outerCorr) for Swim in Swimmers: Swim.Body.force(P, i) Swim.Body.free_swimming(P, i) archive(Swim.Body.AF.x_mid) archive(Swim.Body.AF.z_mid) graph.plot_n_go(Swimmers, i, P) DIO.write_data(P, i, DEL_T, SwiL, GeoL, MotL, Swimmers) else: if np.fmod(i, VERBOSITY) == 0: po().timestep_header(i,T[i]) for Swim in Swimmers: Swim.Body.panel_positions(P, i) Swim.Body.surface_kinematics(P, i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) solve_phi(Swimmers, P, i, outerCorr) wake_rollup(Swimmers, DEL_T, i, P)
for i in xrange(START_COUNTER, COUNTER): if i == 0: for Swim in Swimmers: Swim.Body.panel_positions(DSTEP, T[i], P['THETA'][i], P['HEAVE'][i]) Swim.Body.surface_kinematics(DSTEP, TSTEP, P['THETA_MINUS'][i], P['THETA_PLUS'][i], P['HEAVE_MINUS'][i], P['HEAVE_PLUS'][i], DEL_T, T[i], i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) Swim.Body.force(P['THETA'][i], RHO, P['V0'], P['C'], 1.0, i) solve_phi(Swimmers, RHO, DEL_T, i, outerCorr) wake_rollup(Swimmers, DEL_T, i) archive(Swimmers[0].Body.AF.x_mid) archive(Swimmers[0].Body.AF.z_mid) SolidP[0].nodes[:, 0] = (SolidP[0].nodesNew[:, 0] - SolidP[0].nodesNew[0, 0]) * np.cos(P['THETA'][i]) SolidP[0].nodes[:, 1] = (SolidP[0].nodesNew[:, 0] - SolidP[0].nodesNew[0, 0]) * np.sin(P['THETA'][i]) graph.plot_n_go(Swimmers[0].Edge, Swimmers[0].Body, SolidP[0], P['V0'], P['T'][i], P['HEAVE'][i]) DIO.write_data(P, i, DEL_T, SwiP, GeoP, MotP, Swimmers, SolidP, FSIP, PyFEAP) else: if np.fmod(i, P['VERBOSITY']) == 0: po().timestep_header(i, T[i])
po().calc_input(MotP[0].THETA_MAX/np.pi*180.,RE,MotP[0].THETA_MAX/np.pi*180.,DEL_T) po().initialize_output(P['T'][START_COUNTER]) outerCorr = 2 for i in xrange(START_COUNTER, COUNTER): if i == 0: for Swim in Swimmers: Swim.Body.panel_positions(DSTEP, T[i], P['THETA'][i], P['HEAVE'][i]) Swim.Body.surface_kinematics(DSTEP, TSTEP, P['THETA_MINUS'][i], P['THETA_PLUS'][i], P['HEAVE_MINUS'][i], P['HEAVE_PLUS'][i], DEL_T, T[i], i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) Swim.Body.force(P['THETA'][i], RHO, P['V0'], P['C'], 1.0, i, P['SW_SV_FORCES']) solve_phi(Swimmers, RHO, DEL_T, i, outerCorr) wake_rollup(Swimmers, DEL_T, i, P) archive(Swimmers[0].Body.AF.x_mid) archive(Swimmers[0].Body.AF.z_mid) SolidP[0].nodes[:,0] = (SolidP[0].nodesNew[:,0] - SolidP[0].nodesNew[0,0])*np.cos(P['THETA'][i]) SolidP[0].nodes[:,1] = (SolidP[0].nodesNew[:,0] - SolidP[0].nodesNew[0,0])*np.sin(P['THETA'][i]) graph.plot_n_go(Swimmers, P['V0'], P['T'][i], P['HEAVE'][i], i, P['SW_PLOT_FIG']) DIO.write_data(P, i, DEL_T, SwiP, GeoP, MotP, Swimmers, SolidP, FSIP, PyFEAP) else: if np.fmod(i,P['VERBOSITY']) == 0: po().timestep_header(i,T[i]) po().fsi_header() FSIP[0].readFsiControls(P['FIXED_PT_RELAX'], P['N_OUTERCORR_MAX']) FSIP[0].__init__(Swimmers[0].Body, SolidP[0]) outerCorr = 0 while True: outerCorr += 1
def wake_shed(self, DEL_T, i): """Updates the positions of the Wake panels. This should only be done once each time step for a swimmer. Args: DEL_T: Time step length. i: Time step number. Edge: Edge panel of separation. Wake: Wake panels. V0: Free-stream velocity. """ Edge = self.Edge Wake = self.Wake V0 = self.V0 # Initialize wake coordinates when i==1 if i == 1: Wake.x[0] = Edge.x[-1] Wake.z[0] = Edge.z[-1] Wake.x[1:] = Wake.x[0] + np.arange(1,np.size(Wake.x))*(-V0)*DEL_T Wake.z[1:] = Wake.z[0] else: archive(Wake.x) archive(Wake.z) archive(Wake.mu) Wake.x[0] = Edge.x[-1] Wake.z[0] = Edge.z[-1] Wake.mu[0] = Edge.mu Wake.gamma[0] = -Wake.mu[0] Wake.gamma[1:-1] = Wake.mu[:-1]-Wake.mu[1:] Wake.gamma[-1] = Wake.mu[-1] # def influence_matrices(self, i): # """Constructs the influence coefficient matrices. # # Args: # i: Time step number. # Body: Body of the swimmer. # Edge: Edge panel of separation. # Wake: Wake panels. # """ # Body = self.Body # Edge = self.Edge # Wake = self.Wake # # # Tangential and normal body panels and panel length calculations # (xp1,xp2,zp) = transformation(Body.AF.x_col,Body.AF.z_col,Body.AF.x,Body.AF.z) # # # Body source singularities influencing the body # # Transpose so that row elements represent the effect on the (row number)th panel # Body.phi_s = np.transpose((xp1 * np.log(xp1**2 + zp**2) - xp2 * np.log(xp2**2 + zp**2) \ # + 2*zp*(np.arctan2(zp,xp2) - np.arctan2(zp,xp1)))/(4*np.pi)) # # # Body doublet singularities influencing body itself # # Transpose similar to phi_s # Body.phi_db = np.transpose(-(np.arctan2(zp,xp2)\ # - np.arctan2(zp,xp1))/(2*np.pi)) # # # Edge doublet influencing the body # (xp1,xp2,zp) = transformation(Body.AF.x_col,Body.AF.z_col,Edge.x,Edge.z) # # if i > 0: # No wake panels until i==1 # # Wake doublets influencing the body # (xp1_w,xp2_w,zp_w) = transformation(Body.AF.x_col,Body.AF.z_col,Wake.x[:i+1],Wake.z[:i+1]) # # Join edge and wake doublet influences into a single matrix # xp1 = np.insert(xp1, Edge.N, xp1_w, axis=0) # xp2 = np.insert(xp2, Edge.N, xp2_w, axis=0) # zp = np.insert(zp, Edge.N, zp_w, axis=0) # # Body.phi_dw = np.transpose(-(np.arctan2(zp,xp2) \ # -np.arctan2(zp,xp1))/(2*np.pi)) # # def kutta(self, RHO, DEL_T, i): # """Applies Kutta condition to the swimmer's trailing edge. # # Args: # RHO: Fluid density. # SW_KUTTA: Switch for either explicit (0) or unsteady (1) Kutta # condition. # DEL_T: Time step length. # i: Time step number. # Body: Body of the swimmer. # Edge: Edge panel of separation. # Wake: Wake panels. # """ # SW_KUTTA = self.SW_KUTTA # Body = self.Body # Edge = self.Edge # Wake = self.Wake # # n_iter = 0 # mu_guess = np.empty(2) # [0] is current guess, [1] is previous # delta_cp = np.empty(2) # [0] is current delta_cp, [1] is previous # # while True: # n_iter += 1 # # if n_iter == 1: # # Begin with explicit Kutta condition as first guess # # Construct the augmented body matrix by combining body and trailing edge panel arrays # c = np.zeros((Body.N,Body.N)) # c[:,0] = -Body.phi_dw[:,0] # c contains the explicit Kutta condition (first and last columns) # c[:,-1] = Body.phi_dw[:,0] # Body.phi_dinv = np.linalg.inv(Body.phi_db + c) # # Get rhs # if i == 1: # rhs = -np.dot(Body.phi_s,Body.sigma) # else: # rhs = -np.dot(Body.phi_s,Body.sigma) - np.dot(Body.phi_dw[:,1:],Wake.mu[:i]) # # Solve for body doublet strengths using explicit Kutta # Body.mu = np.dot(Body.phi_dinv,rhs) # # First mu_guess (from explicit Kutta) # mu_guess[0] = Body.mu[-1]-Body.mu[0] # # else: # if n_iter == 2: # Make a second initial guess # # Update phi_dinv so it no longer includes explicit Kutta condition # Body.phi_dinv = np.linalg.inv(Body.phi_db) # # mu_guess[1] = mu_guess[0] # delta_cp[1] = delta_cp[0] # mu_guess[0] = 0.8*mu_guess[1] # Multiply first (explicit) guess by arbitrary constant to get second guess # # else: # Newton method to get delta_cp == 0 # # Get slope, which is change in delta_cp divided by change in mu_guess # slope = (delta_cp[0]-delta_cp[1])/(mu_guess[0]-mu_guess[1]) # mu_guess[1] = mu_guess[0] # delta_cp[1] = delta_cp[0] # mu_guess[0] = mu_guess[1] - delta_cp[0]/slope # # # Form right-hand side including mu_guess as an influence # if i == 1: # rhs = -np.dot(Body.phi_s,Body.sigma) - np.squeeze(np.dot(Body.phi_dw,mu_guess[0])) # else: # rhs = -np.dot(Body.phi_s,Body.sigma) - np.dot(Body.phi_dw,np.insert(Wake.mu[:i],0,mu_guess[0])) # # Body.mu = np.dot(Body.phi_dinv,rhs) # # # Body.pressure(RHO, DEL_T, i) # if SW_KUTTA == 0: # break # delta_cp[0] = np.absolute(Body.cp[-1]-Body.cp[0]) # if delta_cp[0] < 0.0001: # break # # # mu_past used in differencing for pressure # Body.mu_past[1,:] = Body.mu_past[0,:] # Body.mu_past[0,:] = Body.mu # # Edge.mu = mu_guess[0] # Edge.gamma[0] = -Edge.mu # Edge.gamma[1] = Edge.mu # # # Get gamma of body panels for use in wake rollup # Body.gamma[0] = -Body.mu[0] # Body.gamma[1:-1] = Body.mu[:-1]-Body.mu[1:] # Body.gamma[-1] = Body.mu[-1] # # def wake_rollup(self, DEL_T, i): # """Performs wake rollup on a swimmer's wake panels. # # Args: # DEL_T: Time step length. # i: Time step number. # Body: Body of the swimmer. # Edge: Edge panel of separation. # Wake: Wake panels. # DELTA_CORE: Constant used to avoid singularities when getting too close # to other panels. # """ # Body = self.Body # Edge = self.Edge # Wake = self.Wake # DELTA_CORE = self.DELTA_CORE # # # Wake panels initialize when i==2 # if i == 0: # pass # # else: # # NT = i # Number of targets (wake panel points that are rolling up) # # vx = np.zeros(NT) # vz = np.zeros(NT) # # # Coordinate transformation for body panels influencing wake # (xp1,xp2,zp) = transformation(Wake.x[1:i+1],Wake.z[1:i+1],Body.AF.x,Body.AF.z) # # # Angle of normal vector with respect to global z-axis # (nx,nz) = panel_vectors(Body.AF.x,Body.AF.z)[2:4] # beta = np.arctan2(-nx,nz) # # # Katz-Plotkin eqns 10.20 and 10.21 for body source influence # dummy1 = np.transpose(np.log((xp1**2+zp**2)/(xp2**2+zp**2))/(4*np.pi)) # dummy2 = np.transpose((np.arctan2(zp,xp2)-np.arctan2(zp,xp1))/(2*np.pi)) # # # Rotate back to global coordinates # dummy3 = dummy1*np.cos(beta) - dummy2*np.sin(beta) # dummy4 = dummy1*np.sin(beta) + dummy2*np.cos(beta) # # # Finish eqns 10.20 and 10.21 for induced velocity by multiplying with Body.sigma # vx = np.dot(dummy3,Body.sigma) # vz = np.dot(dummy4,Body.sigma) # # # Formation of (x-x0) and (z-z0) matrices, similar to xp1/xp2/zp but coordinate transformation is not necessary # NI = Body.N+1 # xp = np.repeat(Wake.x[1:i+1,np.newaxis].T,NI,0) - np.repeat(Body.AF.x[:,np.newaxis],NT,1) # zp = np.repeat(Wake.z[1:i+1,np.newaxis].T,NI,0) - np.repeat(Body.AF.z[:,np.newaxis],NT,1) # # # Find distance r_b between each influence/target # r_b = np.sqrt(xp**2+zp**2) # # # Katz-Plotkin eqns 10.9 and 10.10 for body doublet (represented as point vortices) influence # dummy1 = np.transpose(zp/(2*np.pi*(r_b**2+DELTA_CORE**2))) # dummy2 = np.transpose(-xp/(2*np.pi*(r_b**2+DELTA_CORE**2))) # # # Finish eqns 10.9 and 10.10 by multiplying with Body.gamma, add to induced velocity # vx += np.dot(dummy1,Body.gamma) # vz += np.dot(dummy2,Body.gamma) # # # Formation of (x-x0) and (z-z0) matrices, similar to xp1/xp2/zp but coordinate transformation is not necessary # NI = Edge.N+1 # xp = np.repeat(Wake.x[1:i+1,np.newaxis].T,NI,0) - np.repeat(Edge.x[:,np.newaxis],NT,1) # zp = np.repeat(Wake.z[1:i+1,np.newaxis].T,NI,0) - np.repeat(Edge.z[:,np.newaxis],NT,1) # # # Find distance r_e between each influence/target # r_e = np.sqrt(xp**2+zp**2) # # # Katz-Plotkin eqns 10.9 and 10.10 for edge (as point vortices) influence # dummy1 = np.transpose(zp/(2*np.pi*(r_e**2+DELTA_CORE**2))) # dummy2 = np.transpose(-xp/(2*np.pi*(r_e**2+DELTA_CORE**2))) # # # Finish eqns 10.9 and 10.10 by multiplying with Edge.gamma, add to induced velocity # vx += np.dot(dummy1,Edge.gamma) # vz += np.dot(dummy2,Edge.gamma) # # # Formation of (x-x0) and (z-z0) matrices, similar to xp1/xp2/zp but coordinate transformation is not necessary # NI = i+1 # xp = np.repeat(Wake.x[1:i+1,np.newaxis].T,NI,0) - np.repeat(Wake.x[:i+1,np.newaxis],NT,1) # zp = np.repeat(Wake.z[1:i+1,np.newaxis].T,NI,0) - np.repeat(Wake.z[:i+1,np.newaxis],NT,1) # # # Find distance r_w between each influence/target # r_w = np.sqrt(xp**2+zp**2) # # # Katz-Plotkin eqns 10.9 and 10.10 for wake (as point vortices) influence # dummy1 = np.transpose(zp/(2*np.pi*(r_w**2+DELTA_CORE**2))) # dummy2 = np.transpose(-xp/(2*np.pi*(r_w**2+DELTA_CORE**2))) # # # Finish eqns 10.9 and 10.10 by multiplying with Wake.gamma, add to induced velocity # vx += np.dot(dummy1,Wake.gamma[:i+1]) # vz += np.dot(dummy2,Wake.gamma[:i+1]) # # # Modify wake with the total induced velocity # Wake.x[1:i+1] += vx*DEL_T # Wake.z[1:i+1] += vz*DEL_T
MotL[0].THETA_MAX / np.pi * 180., DEL_T) po().initialize_output(T[START_COUNTER]) outerCorr = 1 for i in xrange(START_COUNTER, COUNTER): if i == 0: for Swim in Swimmers: Swim.Body.panel_positions(P, i) Swim.Body.surface_kinematics(P, i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) solve_phi(Swimmers, P, i, outerCorr) for Swim in Swimmers: Swim.Body.force(P, i) Swim.Body.free_swimming(P, i) archive(Swim.Body.AF.x_mid) archive(Swim.Body.AF.z_mid) graph.plot_n_go(Swimmers, i, P) DIO.write_data(P, i, DEL_T, SwiL, GeoL, MotL, Swimmers) else: if np.fmod(i, VERBOSITY) == 0: po().timestep_header(i, T[i]) for Swim in Swimmers: Swim.Body.panel_positions(P, i) Swim.Body.surface_kinematics(P, i) Swim.edge_shed(DEL_T, i) Swim.wake_shed(DEL_T, i) solve_phi(Swimmers, P, i, outerCorr) wake_rollup(Swimmers, DEL_T, i, P)