I am trying to convert this MATLAB code:
function [u,v,w,nodes] = windSimFast(U,f,Su,Sv,Sw,CoeffDecay,Y,Z,varargin)% [u,v,w,nodes] = windSimFast(U,f,Su,Sv,Sw,CoeffDecay,Y,Z,varargin)% simulates the turbulent components u, v and w of the wind% velocity using a target power spectral density (PSD) and coherence model.% The numerical method comes from ref. [1] and a similar Matlab implementation % has been used in ref. [2].%% Inputs:% U: matrix [Ny x Nz] of mean wind velocity (in m/s) at each node of a grid.% f: vector [1 x Nfreq] of frequency (in Hz)% Su: vector [Nm x 1] corresponding to the PSD the u-component.% Sv: vector [Nm x 1] corresponding to the PSD the v-component.% Sw: vector [Nm x 1] corresponding to the PSD the w-component.% CoeffDecay: Structure containing the decay coefficient for the Davenport% model [3] % Z: matrix [Ny x Nz] of height (in m) at each node of a grid.% Y: matrix [Ny x Nz] of lateral position (in m) at each node of a grid.%% Outputs:% Posing Nm = Nx*Ny and N = number of time step,% u: matrix [N x Nm] of along-wind velocity fluctuations% v: matrix [N x Nm] of lateral-wind velocity fluctuations% w: matrix [N x Nm] of vertical-wind velocity fluctuations% nodes: structure containing the position and associated velocity of each% nodes on the 2D-grid.% % Options (varargin):% 'Suw': vector [Nm x 1] corresponding to the CPSD the u and w components% 'Svw': vector [Nm x 1] corresponding to the CPSD the v and w components% 'cohModel': string: the coherence model (so far, only 'Davenport' exist)% % References:% [1] Shinozuka, M., & Deodatis, G. (1991). % Simulation of stochastic processes by spectral representation. % Applied Mechanics Reviews, 44(4), 191-204.% % [2] Wang, J., Cheynet, E., Snæbjörnsson, J. Þ., & Jakobsen, J. B. (2018).% Coupled aerodynamic and hydrodynamic response of a long span bridge% suspended from floating towers. % Journal of Wind Engineering and Industrial Aerodynamics, 177, 19-31.% % [3] Davenport, A. G. (1961). The spectrum of horizontal gustiness near % the ground in high winds. % Quarterly Journal of the Royal Meteorological Society, 87(372), 194-211.% % Author: E. Cheynet - UiB - last modified : 12-06-2020%% optional parameters removed from previous version% 'quadCoh_Cu' are decay coeficients for the quad-coherence of the u component.% Example: quadCoh_Cu = [5 10];% 'quadCoh_Cv' are decay coeficients for the quad-coherence of the w component.% Example: quadCoh_Cv = [5 10];% 'quadCoh_Cw' are decay coeficients for the quad-coherence of the w component.% Example: quadCoh_Cw = [5 10];%% Input parser p = inputParser();p.CaseSensitive = false;% p.addOptional('quadCoh_Cu',[]); % optional coefficients used for the quad-coherence% p.addOptional('quadCoh_Cv',[]); % optional coefficients used for the quad-coherence% p.addOptional('quadCoh_Cw',[]); % optional coefficients used for the quad-coherencep.addOptional('cohModel','Davenport');p.addOptional('Suw',zeros(size(Su)));p.addOptional('Svw',zeros(size(Su)));p.parse(varargin{:});% shorthen the variables nameSuw = p.Results.Suw ;Svw = p.Results.Svw ;cohModel = p.Results.cohModel;% quadCoh_Cu = p.Results.quadCoh_Cu;% quadCoh_Cv = p.Results.quadCoh_Cv;% quadCoh_Cw = p.Results.quadCoh_Cw;%% Create the structure "nodes"Nm = numel(Y(:)); % number of nodes in the grid, equal to Nyy*NzzM = 3*Nm; % u,v and w are generated together, requiring 3 times more points than Nm (u,v and w are not necessarily independant)% Create the structure nodesnodes.U = U;nodes.Y = Y;nodes.Z = Z;% Affect one name and to each nodesfor ii=1:Nm, nodes.name{ii} = strcat('N',num2str(ii));endNfreq = numel(f);N = 2*Nfreq;dt = 1/(2*f(end));%% Compute the core spectral matrix Ady = abs(bsxfun(@minus,nodes.Y(:)',nodes.Y(:))); % Matrix distance along ydz = abs(bsxfun(@minus,nodes.Z(:)',nodes.Z(:))); % Matrix distance along zmeanU = 0.5*abs(bsxfun(@plus,nodes.U(:)',nodes.U(:))); % Mean wind velocity between each nodesA = zeros(Nfreq,M);ZERO = zeros(Nm);for ii=1:Nfreq if ii==2, tStart = tic; end randPhase = rand(M,1); % set random phase % compute the coherence at each frequency step if strcmpi(cohModel,'Davenport') [cohU] = cohDavenport(meanU,dy,dz,f(ii),CoeffDecay.Cuy,CoeffDecay.Cuz); [cohV] = cohDavenport(meanU,dy,dz,f(ii),CoeffDecay.Cvy,CoeffDecay.Cvz); [cohW] = cohDavenport(meanU,dy,dz,f(ii),CoeffDecay.Cwy,CoeffDecay.Cwz); else error('In the present version, no other coherence model than the Davenport model has been implemented'); end% if ~isempty(quadCoh_Cu)% quadCohU = getQuadCoh(meanU,dz,f(ii),quadCoh_Cu); % compute the quad-coherence% cohU = cohU + 1i.*quadCohU; % end% % if ~isempty(quadCoh_Cv)% quadCohV = getQuadCoh(meanU,dz,f(ii),quadCoh_Cv); % compute the quad-coherence% cohU = cohU + 1i.*quadCohV; % end% % if ~isempty(quadCoh_Cw)% quadCohW = getQuadCoh(meanU,dz,f(ii),quadCoh_Cw); % compute the quad-coherence% cohU = cohU + 1i.*quadCohW; % end Suu = sqrt(Su(:,ii)*Su(:,ii)').*cohU; Svv = sqrt(Sv(:,ii)*Sv(:,ii)').*cohV; Sww = sqrt(Sw(:,ii)*Sw(:,ii)').*cohW; Suw2 = sqrt(Suw(:,ii)*Suw(:,ii)').*sqrt(cohU.*cohW); % The cross-coherence is here not very well defined, but this should be good enough at a first approximation Svw2 = sqrt(Svw(:,ii)*Svw(:,ii)').*sqrt(cohU.*cohW); % The cross-coherence is here not very well defined, but this should be good enough at a first approximation S = [Suu, ZERO, Suw2;... ZERO, Svv, Svw2;... Suw2, Svw2, Sww]; [L,D]=ldl(S,'lower'); % a LDL decomposition is applied this time G = L*sqrt(D); A(ii,:)= G*exp(1i*2*pi*randPhase); if ii==2, fprintf(['Expected computation time: From ',num2str(round(min(toc(tStart))*Nfreq/2)),' to ',num2str(round(min(toc(tStart))*Nfreq)),' seconds \n']); endend%% Apply IFFT% Nu = [zeros(1:Nfreq,1);A(1:Nfreq,:) ; real(A(Nfreq,:)); conj(flipud(A(1:Nfreq,:)))];Nu = [zeros(1,M);A(1:Nfreq-1,:) ; real(A(Nfreq,:)); conj(flipud(A(1:Nfreq-1,:)))];speed=real(ifft(Nu).*sqrt(Nfreq./(dt)));u = speed(:,1:Nm);v = speed(:,Nm+1:2*Nm);w = -speed(:,2*Nm+1:3*Nm);%% Nested functions function [coh] = cohDavenport(meanU,dy,dz,f,Cy,Cz) % lateral separation ay = Cy(1).*dy; % vertical separation az = Cz(1).*dz; % Combine them into the coherence matrix for lateral and vertical % separations coh = exp(-sqrt(ay.^2+az.^2).*f./meanU); end function [Qu] = getQuadCoh(meanU,dz,f,C) dummy = -tril(ones(size(dz)),-1) + triu(ones(size(dz)),1); Qu = dummy.*(C(1).*f./meanU.*dz).*exp(-C(2).*f./meanU.*dz); endend
into python. So far I have:
import numpy as npdef kaimal_model(U, Z, f, u_star):""" Computes the one-point auto and cross-spectral densities of the Kaimal model. Inputs: U: matrix [Ny x Nz] of mean wind velocity (in m/s) at each node of a grid. Z: matrix [Ny x Nz] of height (in m) at each node of a grid. f: vector [1 x Nfreq] of frequency (in Hz) u_star: scalar friction velocity (in m/s) Outputs: Su: vector [Nm x 1] corresponding to the PSD the u-component Sv: vector [Nm x 1] corresponding to the PSD the v-component. Sw: vector [Nm x 1] corresponding to the PSD the w-component Suw: vector [Nm x 1] corresponding to the CPSD the u and w components Svw: vector [Nm x 1] corresponding to the CPSD the v and w components""" N = len(f) Nm = np.size(U) Su = np.zeros((Nm, N)) # preallocation Sv = np.zeros((Nm, N)) # preallocation Sw = np.zeros((Nm, N)) # preallocation Suw = np.zeros((Nm, N)) # preallocation Svw = np.zeros((Nm, N)) # preallocation dummyU = U.T.flatten() dummyZ = Z.T.flatten() for jj in range(Nm): fr = f * dummyZ[jj] / dummyU[jj] Su[jj, :] = 102 * fr / (1 + 33 * fr) ** (5 / 3) * u_star ** 2 / f # Kaimal model (NOT normalized) Sv[jj, :] = 17 * fr / (1 + 9.5 * fr) ** (5 / 3) * u_star ** 2 / f # Kaimal model (NOT normalized) Sw[jj, :] = (2 * fr / (1 + 5 * fr ** (5 / 3))) * u_star ** 2 / f # Kaimal model (NOT normalized) Suw[jj, :] = -14 * fr / (1 + 10.5 * fr) ** (7 / 3) * u_star ** 2 / f # corrected (by me) Kaimal cross-spectrum model (NOT normalized) return Su, Sv, Sw, Suw, Svwimport numpy as npfrom scipy.linalg import ldlfrom numpy.fft import ifftimport matplotlib.pyplot as pltdef wind_sim_fast(U, f, Su, Sv, Sw, coeff_decay, Y, Z, **kwargs):""" Simulates the turbulent components u, v, and w of the wind velocity using a target power spectral density (PSD) and coherence model. Inputs: U: matrix [Ny x Nz] of mean wind velocity (in m/s) at each node of a grid. f: vector [1 x Nfreq] of frequency (in Hz) Su: vector [Nm x 1] corresponding to the PSD the u-component. Sv: vector [Nm x 1] corresponding to the PSD the v-component. Sw: vector [Nm x 1] corresponding to the PSD the w-component. CoeffDecay: Structure containing the decay coefficient for the Davenport model. Z: matrix [Ny x Nz] of height (in m) at each node of a grid. Y: matrix [Ny x Nz] of lateral position (in m) at each node of a grid. **kwargs: Additional options (e.g., 'Suw', 'Svw', 'cohModel'). Outputs: u: matrix [N x Nm] of along-wind velocity fluctuations v: matrix [N x Nm] of lateral-wind velocity fluctuations w: matrix [N x Nm] of vertical-wind velocity fluctuations nodes: structure containing the position and associated velocity of each nodes on the 2D-grid.""" Nm = len(Y.flatten()) # number of nodes in the grid M = 3 * Nm # u, v, and w are generated together nodes = {'U': U, 'Y': Y, 'Z': Z, 'name': [f'N{i}' for i in range(1, Nm + 1)]} Nfreq = len(f) N = 2 * Nfreq dt = 1 / (2 * f[-1]) dy = np.abs(np.subtract.outer(Y.T.flatten(), Y.T.flatten())) # Matrix distance along y dz = np.abs(np.subtract.outer(Z.T.flatten(), Z.T.flatten())) # Matrix distance along z meanU = 0.5 * (np.add.outer(U.T.flatten(), U.T.flatten())) # Mean wind velocity between each nodes A = np.zeros((Nfreq, M), dtype=np.complex128) Suw = kwargs.get('Suw', np.zeros_like(Su)) Svw = kwargs.get('Svw', np.zeros_like(Sv)) for ii in range(Nfreq): rand_phase = np.random.rand(M) # Set random phase coh_u = coh_davenport(meanU, dy, dz, f[ii], coeff_decay['Cuy'], coeff_decay['Cuz']) coh_v = coh_davenport(meanU, dy, dz, f[ii], coeff_decay['Cvy'], coeff_decay['Cvz']) coh_w = coh_davenport(meanU, dy, dz, f[ii], coeff_decay['Cwy'], coeff_decay['Cwz']) suu = np.sqrt(np.outer(Su[:, ii], Su[:, ii])) * coh_u svv = np.sqrt(np.outer(Sv[:, ii], Sv[:, ii])) * coh_v sww = np.sqrt(np.outer(Sw[:, ii], Sw[:, ii])) * coh_w suw = np.sqrt(np.outer(Suw[:, ii], Suw[:, ii])) * np.sqrt(coh_u * coh_w) svw = np.sqrt(np.outer(Svw[:, ii], Svw[:, ii])) * np.sqrt(coh_v * coh_w) S = np.block([ [suu, np.zeros((Nm, Nm)), suw], [np.zeros((Nm, Nm)), svv, svw], [suw.conj().T, svw.conj().T, sww] ]) L, D, _ = ldl(S, lower=True) G = L @ np.sqrt(D.astype(np.complex128)) A[ii, :] = G @ np.exp(1j * 2 * np.pi * rand_phase) Nu = np.vstack([np.zeros(M), A[:-1, :], np.real(A[-1, :]), np.conj(np.flipud(A[:-1, :]))]) speed = np.real(ifft(Nu) * np.sqrt(Nfreq / (dt * 2))) u = speed[:, :Nm] v = speed[:, Nm:2 * Nm] w = -speed[:, 2 * Nm:] return u, v, w, nodesdef coh_davenport(meanU, dy, dz, f, Cy, Cz): ay = Cy * dy az = Cz * dz return np.exp(-np.sqrt(ay ** 2 + az ** 2) * f / meanU)import numpy as npdef get_sampling_para(M, fs):""" Computes the time and frequency vectors based on the sampling frequency fs and an integer M. Inputs: M: Natural number used as the power of 2 to compute the number of time steps for the simulation. fs: Sampling frequency (Hz) Outputs: t: Time vector (units: s) f: Frequency vector (units: s^(-1))""" if not isinstance(M, int) or M <= 0: raise ValueError("M should be a natural number.") N = 2 ** M # Number of time steps dt = 1 / fs tmax = dt * N t = np.arange(N) * dt print(f"Duration of target time series is {tmax / 3600:.3f} hours, i.e., {tmax:.3f} sec\n") f0 = 1 / tmax # Minimal frequency recorded fc = fs / 2 # Nyquist frequency f = np.arange(f0, fc + f0, f0) # Frequency vector return t, f
and the value of S in my test script (copying the example 2 in the matlab code) is exactly the same as in matlab. However, when I go to call L, D, _ = ldl(S, lower=True)
in python, the L and D matrices are different to matlab.
A test script for this is pasted here.
This prints:
L max diff = 6.476032714138286D max diff = 499.1013
How can I get the L and D matrices to be the same as matlab?
Thanks
Edit:
The full code for the python port I am running is:
import numpy as npfrom scipy.linalg import ldlfrom numpy.fft import ifftdef kaimal_model(U, Z, f, u_star):""" Computes the one-point auto and cross-spectral densities of the Kaimal model. Inputs: U: matrix [Ny x Nz] of mean wind velocity (in m/s) at each node of a grid. Z: matrix [Ny x Nz] of height (in m) at each node of a grid. f: vector [1 x Nfreq] of frequency (in Hz) u_star: scalar friction velocity (in m/s) Outputs: Su: vector [Nm x 1] corresponding to the PSD the u-component Sv: vector [Nm x 1] corresponding to the PSD the v-component. Sw: vector [Nm x 1] corresponding to the PSD the w-component Suw: vector [Nm x 1] corresponding to the CPSD the u and w components Svw: vector [Nm x 1] corresponding to the CPSD the v and w components""" N = len(f) Nm = np.size(U) Su = np.zeros((Nm, N)) # preallocation Sv = np.zeros((Nm, N)) # preallocation Sw = np.zeros((Nm, N)) # preallocation Suw = np.zeros((Nm, N)) # preallocation Svw = np.zeros((Nm, N)) # preallocation dummyU = U.T.flatten() dummyZ = Z.T.flatten() for jj in range(Nm): fr = f * dummyZ[jj] / dummyU[jj] Su[jj, :] = 102 * fr / (1 + 33 * fr) ** (5 / 3) * u_star ** 2 / f # Kaimal model (NOT normalized) Sv[jj, :] = 17 * fr / (1 + 9.5 * fr) ** (5 / 3) * u_star ** 2 / f # Kaimal model (NOT normalized) Sw[jj, :] = (2 * fr / (1 + 5 * fr ** (5 / 3))) * u_star ** 2 / f # Kaimal model (NOT normalized) Suw[jj, :] = -14 * fr / (1 + 10.5 * fr) ** (7 / 3) * u_star ** 2 / f # corrected (by me) Kaimal cross-spectrum model (NOT normalized) return Su, Sv, Sw, Suw, Svwdef wind_sim_fast(U, f, Su, Sv, Sw, coeff_decay, Y, Z, **kwargs):""" Simulates the turbulent components u, v, and w of the wind velocity using a target power spectral density (PSD) and coherence model. Inputs: U: matrix [Ny x Nz] of mean wind velocity (in m/s) at each node of a grid. f: vector [1 x Nfreq] of frequency (in Hz) Su: vector [Nm x 1] corresponding to the PSD the u-component. Sv: vector [Nm x 1] corresponding to the PSD the v-component. Sw: vector [Nm x 1] corresponding to the PSD the w-component. CoeffDecay: Structure containing the decay coefficient for the Davenport model. Z: matrix [Ny x Nz] of height (in m) at each node of a grid. Y: matrix [Ny x Nz] of lateral position (in m) at each node of a grid. **kwargs: Additional options (e.g., 'Suw', 'Svw', 'cohModel'). Outputs: u: matrix [N x Nm] of along-wind velocity fluctuations v: matrix [N x Nm] of lateral-wind velocity fluctuations w: matrix [N x Nm] of vertical-wind velocity fluctuations nodes: structure containing the position and associated velocity of each nodes on the 2D-grid.""" Nm = len(Y.flatten()) # number of nodes in the grid M = 3 * Nm # u, v, and w are generated together nodes = {'U': U, 'Y': Y, 'Z': Z, 'name': [f'N{i}' for i in range(1, Nm + 1)]} Nfreq = len(f) N = 2 * Nfreq dt = 1 / (2 * f[-1]) dy = np.abs(np.subtract.outer(Y.T.flatten(), Y.T.flatten())) # Matrix distance along y dz = np.abs(np.subtract.outer(Z.T.flatten(), Z.T.flatten())) # Matrix distance along z meanU = 0.5 * (np.add.outer(U.T.flatten(), U.T.flatten())) # Mean wind velocity between each nodes A = np.zeros((Nfreq, M), dtype=np.complex128) Suw = kwargs.get('Suw', np.zeros_like(Su)) Svw = kwargs.get('Svw', np.zeros_like(Sv)) for ii in range(Nfreq): rand_phase = np.random.rand(M) # Set random phase coh_u = coh_davenport(meanU, dy, dz, f[ii], coeff_decay['Cuy'], coeff_decay['Cuz']) coh_v = coh_davenport(meanU, dy, dz, f[ii], coeff_decay['Cvy'], coeff_decay['Cvz']) coh_w = coh_davenport(meanU, dy, dz, f[ii], coeff_decay['Cwy'], coeff_decay['Cwz']) suu = np.sqrt(np.outer(Su[:, ii], Su[:, ii])) * coh_u svv = np.sqrt(np.outer(Sv[:, ii], Sv[:, ii])) * coh_v sww = np.sqrt(np.outer(Sw[:, ii], Sw[:, ii])) * coh_w suw = np.sqrt(np.outer(Suw[:, ii], Suw[:, ii])) * np.sqrt(coh_u * coh_w) svw = np.sqrt(np.outer(Svw[:, ii], Svw[:, ii])) * np.sqrt(coh_v * coh_w) S = np.block([ [suu, np.zeros((Nm, Nm)), suw], [np.zeros((Nm, Nm)), svv, svw], [suw.conj().T, svw.conj().T, sww] ]) L, D, _ = ldl(S, lower=True) G = L @ np.sqrt(D.astype(np.complex128)) A[ii, :] = G @ np.exp(1j * 2 * np.pi * rand_phase) Nu = np.vstack([np.zeros(M), A[:-1, :], np.real(A[-1, :]), np.conj(np.flipud(A[:-1, :]))]) speed = np.real(ifft(Nu) * np.sqrt(Nfreq / (dt * 2))) u = speed[:, :Nm] v = speed[:, Nm:2 * Nm] w = -speed[:, 2 * Nm:] return u, v, w, nodesdef coh_davenport(meanU, dy, dz, f, Cy, Cz): ay = Cy * dy az = Cz * dz return np.exp(-np.sqrt(ay ** 2 + az ** 2) * f / meanU)def get_sampling_para(M, fs):""" Computes the time and frequency vectors based on the sampling frequency fs and an integer M. Inputs: M: Natural number used as the power of 2 to compute the number of time steps for the simulation. fs: Sampling frequency (Hz) Outputs: t: Time vector (units: s) f: Frequency vector (units: s^(-1))""" if not isinstance(M, int) or M <= 0: raise ValueError("M should be a natural number.") N = 2 ** M # Number of time steps dt = 1 / fs tmax = dt * N t = np.arange(N) * dt print(f"Duration of target time series is {tmax / 3600:.3f} hours, i.e., {tmax:.3f} sec\n") f0 = 1 / tmax # Minimal frequency recorded fc = fs / 2 # Nyquist frequency f = np.arange(f0, fc + f0, f0) # Frequency vector return t, fnp.random.seed(1)fs = 9M = 15[t,f] = get_sampling_para(M,fs)N = len(t)Nfreq = len(f)dt = np.median(np.diff(t))Nyy = 5Nzz = 5ymin = -50ymax = 50zmin = 1zmax = zmin + 150y = np.linspace(ymin, ymax, Nyy)z = np.linspace(zmin, zmax, Nzz)Y, Z = np.meshgrid(y, z)u_star = 0.8 # Friction velocity (m/s)kappa = 0.4 # Von Karman constantz0 = 0.03 # Roughness lengthlogProfile = lambda u_star, z, z0, kappa: u_star / kappa * np.log(z / z0)U = logProfile(u_star, Z, z0, kappa)CohDecay = {'Cuy': 7, # Arbitrary decay coefficient for u in the "y" direction'Cuz': 10, # Arbitrary decay coefficient for u in the "z" direction'Cvy': 7, # Arbitrary decay coefficient for v in the "y" direction'Cvz': 10, # Arbitrary decay coefficient for v in the "z" direction'Cwy': 6.5, # Arbitrary decay coefficient for w in the "y" direction'Cwz': 3, # Arbitrary decay coefficient for w in the "z" direction}Su, Sv, Sw, Suw, _ = kaimal_model(U, Z, f, u_star)indZ = np.argmin(np.abs(Z[:, 0] - 100))coeff = f / u_star ** 2fr = f * Z[indZ, 0] / U[indZ, 0]u, v, w, nodes = wind_sim_fast(U, f, Su, Sv, Sw, CohDecay, Y, Z, Suw=Suw)u = np.reshape(u, (N, Nzz, Nyy))v = np.reshape(v, (N, Nzz, Nyy))w = np.reshape(w, (N, Nzz, Nyy))u += U.reshape(Nzz, Nyy)print(f"Mean wind speed for w is {np.nanmean(w):.2f} m/s") # Check if zero m/sprint(f"Mean wind speed for v is {np.nanmean(v):.2f} m/s") # Check if zero m/sindEnd = np.argmin(np.abs(t - 150))plt.figure()plt.subplot(311)plt.plot(t[:indEnd], u[:indEnd, 0, 0])plt.ylabel('u (m/s)')plt.axis('tight')plt.subplot(312)plt.plot(t[:indEnd], v[:indEnd, 0, 0])plt.ylabel('v (m/s)')plt.axis('tight')plt.subplot(313)plt.plot(t[:indEnd], w[:indEnd, 0, 0])plt.xlabel('time (s)')plt.ylabel('w (m/s)')plt.axis('tight')plt.gca().set_facecolor('w')plt.show()
Which can be compared to example2.mlx in the MATLAB file exchange here. However, in my Example2.mlx I have set the same random seed by modifying the first block to be:
clearvars;close all;clc;rng(1);fs = 9; % sampling frequency (in Hertz)M = 15; % M is the power of 2: If M = 10, 2^M = 1024 time step[t,f] = getSamplingPara(M,fs);N=numel(t); % number of time step (should be equal to 2^M)Nfreq = numel(f); % number of frequency step (should be equal to 2^(M-1))dt = median(diff(t)); % time step (should be equal to 1/fs)rng(1)