def test_diffusion_cartesian(): # test H2 and H7 dt = 1e5 # test only steady state L = 1 # size of domain N = 500 # number of spatial grid points dx = L / (N-1) # spatial grid size x = np.arange(N)*dx # location corresponding to grid points j=0, ..., N-1 nL = 0.2 # initial conditions n_initial = np.sin(np.pi * x) + nL * x # diffusion problem coefficients D = 0.8 H1 = np.ones_like(x) H2 = D * np.ones_like(x) H7 = 1 - x**2 # solve it for steady state: only one iteration required for linear problem n_final = HToMatrixFD.H_to_matrix_and_solve(dt, dx, nL, n_initial, H1=H1, H2=H2, H7=H7) # compare with analytic and plots n_ss_analytic = nL + 1/(12*D) * (1-x**2) * (5 - x**2) tol = 1e-4 mean_square_error = np.linalg.norm(n_final - n_ss_analytic) / N obs = mean_square_error exp = 0 assert abs(obs - exp) < tol
def test_diffusion_polar(): # test H2 and H7 for spatially-dependent H2. Diffusion in polar coordinates dt = 1e6 L = 1 # size of domain N = 500 # number of spatial grid points dr = L / (N - 0.5) # spatial grid size r = np.linspace(dr/2, L, N) # location corresponding to grid points j=0, ..., N-1 nL = 0.03 # initial conditions n_initial = 0.3*np.sin(np.pi * r) + nL * r # diffusion problem coefficients D = 1.3 H1 = r H2 = D*r H7 = r**2 n_final = HToMatrixFD.H_to_matrix_and_solve(dt, dr, nL, n_initial, H1=H1, H2=H2, H7=H7 ) # compare with analytic and plots n_ss_analytic = nL + 1/(9*D) * (1-r**3) tol = 1e-8 # for N=500 mean_square_error = np.linalg.norm(n_final - n_ss_analytic) / N obs = mean_square_error exp = 0 assert abs(obs - exp) < tol
def test_H4(): # test H4 in a problem with an analytic solution dt = 1e9 # test only steady state L = 1 # size of domain N = 500 # number of spatial grid points dx = L / (N - 1) # spatial grid size x = np.arange( N) * dx # location corresponding to grid points j=0, ..., N-1 UL = 2.2 U_initial = np.sin(np.pi * x) + UL * x H1 = np.ones_like(x) H2 = np.ones_like(x) H4 = -np.sin(x) H7 = 1 - x**2 U_final = HToMatrixFD.H_to_matrix_and_solve(dt, dx, UL, U_initial, H1=H1, H2=H2, H4=H4, H7=H7) U_ss_analytic = UL - (np.cos(x) - np.cos(L)) - (x**2 - L**2) / 2 + (x**4 - L**4) / 12 assert np.allclose(U_final, U_ss_analytic, rtol=1e-3, atol=1e-3)
def test_diffusion_convection_time_polar(): # test H1, H2, H3, H7 -- diffusion-convection problem in polar coordinates, including time dependence # use a manufactured solution to generate a problem with analytic solution L = 1 # size of domain N = 300 # number of spatial grid points dr = L / (N - 0.5) # spatial grid size r = np.linspace(dr / 2, L, N) # location corresponding to grid points j=0, ..., N-1 nL = 0.5 # initial conditions n_initial = nL * np.ones_like(r) n = n_initial # specify diffusion problem coefficients D = 1.3 c0 = 0.7 gamma = 0.9 H1 = r H2 = D * r H3 = -c0 * r**2 fH7 = lambda r, t: r/D * gamma * np.exp(-gamma*t) * (1-r**5) + \ 25 * r**4 * (1 - np.exp(-gamma*t)) + \ c0 * (2*r*nL + 1/D * (1 - np.exp(-gamma*t)) * (2*r - 7*r**6)) # set up time loop dt = 1e-2 tf = 0.1 tvec = np.arange(0, tf + 1e-10, dt) for m in range(1, len(tvec)): t = tvec[m] H7 = fH7(r, t) n = HToMatrixFD.H_to_matrix_and_solve(dt, dr, nL, n, H1=H1, H2=H2, H3=H3, H7=H7) n_final = n # compare with analytic and plots #n_ss_analytic = nL + 1/D * (1-r**5) n_timedep_analytic = nL + 1 / D * (1 - np.exp(-gamma * t)) * (1 - r**5) tol = 2e-5 # for N=300 mean_square_timedep_error = np.linalg.norm(n_final - n_timedep_analytic) / N obs = mean_square_timedep_error exp = 0 assert abs(obs - exp) < tol
def test_uncoupled_Hcoeffs_to_matrix(): """Test Hcoeffs_to_matrix_eqn() method of the UncoupledFieldGroup class.""" # create the UncoupledFieldGroup ufg = fieldgroups.UncoupledFieldGroup('default') # create the Hcoeffs, rightBC, psi_mminus1 (dt, dx, rightBC, psi_mminus1, H1, H2, H7, n_ss_analytic, rtol) = one_field_diffusion_setup() Hcoeffs = multifield.HCoefficients(H1=H1, H2=H2, H7=H7) # discretize into matrix equation matrixEqn = ufg.Hcoeffs_to_matrix_eqn(dt, dx, rightBC, psi_mminus1, Hcoeffs) # matrix solve (using the underlying internals, not the object's method) n_solution = HToMatrixFD.solve(matrixEqn.A, matrixEqn.B, matrixEqn.C, matrixEqn.f) # check assert np.allclose(n_solution, n_ss_analytic, rtol=rtol)
c_EWMA = alpha * c + (1 - alpha) * c_EWMA H2Turb = D_EWMA H3 = -c_EWMA # get H's for all the others (H1, H2, H7). H's represent terms in the transport equation H1 = np.ones_like(x) H7 = source(x) H2const = 0.00 # could represent some background level of (classical) diffusion H2 = H2Turb + H2const ## new --- discretize, then compute the residual, then solve the matrix equation for the new profile (A, B, C, f) = HToMatrixFD.H_to_matrix(dt, dx, nL, n_mminus1, H1, H2=H2, H3=H3, H7=H7) # see fieldgroups.calculate_residual() for additional information on the residual calculation resid = A * np.concatenate( (profile[1:], np.zeros(1))) + B * profile + C * np.concatenate( (np.zeros(1), profile[:-1])) - f resid = resid / np.max(np.abs(f)) # normalize the residual rmsResid = np.sqrt(np.mean( resid**2)) # take an rms characterization of residual residualHistory[iterationNumber] = rmsResid # solve matrix equation for new profile profile = HToMatrixFD.solve(A, B, C, f)
def test_lodestro_shestakovproblem(): # test the LoDestro Method on the analytic shestakov problem # setup L = 1 # size of domain N = 500 # number of spatial grid points dx = L / (N-1) # spatial grid size x = np.arange(N)*dx # location corresponding to grid points j=0, ..., N-1 nL = 1e-2 # right boundary condition lmax = 2000 # max number of iterations dt = 1e4 # timestep thetaParams = {'Dmin': 1e-5, 'Dmax': 1e13, 'dpdxThreshold': 10} lmParams = {'EWMAParamTurbFlux': 0.30, 'EWMAParamProfile': 0.30, 'thetaParams': thetaParams} FluxModel = shestakov_nonlinear_diffusion.shestakov_analytic_fluxmodel(dx) turbhandler = lodestro_method.TurbulenceHandler(dx, x, lmParams, FluxModel) # initial condition n = 1 - 0.5*x tol = 1e-11 # tol for convergence t = np.array([0, 1e6]) # initialize "m minus 1" variables for the first timestep n_mminus1 = n for m in range(1, len(t)): # Implicit time advance: iterate to solve the nonlinear equation! dt = t[m] - t[m-1] # use this if using non-constant timesteps converged = False l = 1 while not converged: # compute H's from current iterate n H1 = np.ones_like(x) H7 = shestakov_nonlinear_diffusion.H7contrib_Source(x) # this needs to be packaged... give n, get out H2, H3. (H2, H3, data) = turbhandler.Hcontrib_turbulent_flux(n) # compute matrix system (A, B, C, f) (A, B, C, f) = HToMatrixFD.H_to_matrix(dt, dx, nL, n_mminus1, H1, H2=H2, H3=H3, H7=H7) # check convergence # convergence check: is || ( M[n^l] n^l - f[n^l] ) / max(abs(f)) || < tol # could add more convergence checks here resid = A*np.concatenate((n[1:], np.zeros(1))) + B*n + C*np.concatenate((np.zeros(1), n[:-1])) - f resid = resid / np.max(np.abs(f)) # normalize residuals rms_error = np.sqrt( 1/len(resid) * np.sum(resid**2)) if rms_error < tol: converged = True # compute new iterate n n = HToMatrixFD.solve(A, B, C, f) # Check for NaNs or infs if np.all(np.isfinite(n)) == False: raise RuntimeError('NaN or Inf detected at l=%d. Exiting...' % (l)) # about to loop to next iteration l l += 1 if l >= lmax: raise RuntimeError('Too many iterations on timestep %d. Error is %f.' % (m, rms_error)) # end of while loop for iteration convergence # Converged. Before advancing to next timestep m, save some stuff n_mminus1 = n nss_analytic = shestakov_nonlinear_diffusion.GetSteadyStateSolution(x, nL) solution_residual = (n - nss_analytic) / np.max(np.abs(nss_analytic)) solution_rms_error = np.sqrt( 1/len(n) * np.sum(solution_residual**2)) obs = solution_rms_error exp = 0 testtol = 1e-3 assert abs(obs - exp) < testtol