From dd8bbf5d50402432f79874797a13892e1ed0091c Mon Sep 17 00:00:00 2001 From: Mani Chandra Date: Fri, 24 May 2019 05:18:16 -0400 Subject: [PATCH 01/58] Changed output format to PETSc binary. No more HDF5 headaches. --- bolt/lib/nonlinear/file_io/dump.py | 7 +-- bolt/lib/nonlinear/file_io/load.py | 16 +++--- .../collisionless_shock/1D/post.py | 49 +++++++++++++--- .../collisionless_shock/1D/post_1d.py | 57 ++++++++++++------- 4 files changed, 91 insertions(+), 38 deletions(-) diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index a80cfc2d..5fcf5220 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -3,7 +3,6 @@ from petsc4py import PETSc import numpy as np -import h5py import arrayfire as af def dump_moments(self, file_name): @@ -81,7 +80,7 @@ def dump_moments(self, file_name): af.eval(array_to_dump) af.flat(array_to_dump).to_ndarray(self._glob_moments_array) - viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w', comm=self._comm) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self._glob_moments) # Following segment shows discrepancy due to buggy behaviour of af.mean @@ -147,7 +146,7 @@ def dump_distribution_function(self, file_name): array_to_dump = af.flat(array_to_dump[:, :, N_g:-N_g, N_g:-N_g]) array_to_dump.to_ndarray(self._glob_f_array) - viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w', comm=self._comm) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self._glob_f) return @@ -212,7 +211,7 @@ def dump_EM_fields(self, file_name): af.flat(self.fields_solver.yee_grid_EM_fields[:, :, N_g:-N_g, N_g:-N_g]) flattened_global_EM_fields_array.to_ndarray(self.fields_solver._glob_fields_array) - viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w', comm=self._comm) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self.fields_solver._glob_fields) return diff --git a/bolt/lib/nonlinear/file_io/load.py b/bolt/lib/nonlinear/file_io/load.py index 95281bff..cea0f2d8 100644 --- a/bolt/lib/nonlinear/file_io/load.py +++ b/bolt/lib/nonlinear/file_io/load.py @@ -28,10 +28,10 @@ def load_distribution_function(self, file_name): # Additionally, we also obtain the size of the local zone ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_f.getCorners() - viewer = PETSc.Viewer().createHDF5(file_name + '.h5', - PETSc.Viewer.Mode.READ, - comm=self._comm - ) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', + PETSc.Viewer.Mode.READ, + comm=self._comm + ) self._glob_f.load(viewer) N_g = self.N_ghost @@ -62,10 +62,10 @@ def load_EM_fields(self, file_name): The above statemant will load the EM fields data stored in the file data_EM_fields.h5 into self.cell_centered_EM_fields """ - viewer = PETSc.Viewer().createHDF5(file_name + '.h5', - PETSc.Viewer.Mode.READ, - comm=self._comm - ) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', + PETSc.Viewer.Mode.READ, + comm=self._comm + ) self.fields_solver._glob_fields.load(viewer) diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py index 8f466387..50b542a9 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py @@ -2,8 +2,8 @@ import matplotlib matplotlib.use('agg') import pylab as pl +from petsc4py import PETSc -import h5py import domain import params @@ -49,6 +49,17 @@ q2, q1 = np.meshgrid(q2, q1) +da_fields = PETSc.DMDA().create([domain.N_q1, domain.N_q2], + dof=(6), stencil_width=0 + ) +fields_vec = da_fields.createGlobalVec() + +da_moments = PETSc.DMDA().create([domain.N_q1, domain.N_q2], + dof=(22), stencil_width=0 + ) +moments_vec = da_moments.createGlobalVec() + + # Finding the number of species, by looking at the number of elements in mass: N_s = len(params.mass) @@ -227,6 +238,16 @@ def return_field_to_be_plotted(name, fields): else: raise Exception('Not valid!') +da_fields = PETSc.DMDA().create([domain.N_q1, domain.N_q2], + dof=(6), stencil_width=0 + ) +fields_vec = da_fields.createGlobalVec() + +da_moments = PETSc.DMDA().create([domain.N_q1, domain.N_q2], + dof=(22), stencil_width=0 + ) +moments_vec = da_moments.createGlobalVec() + # Traversal to determine the maximum and minimum: def determine_min_max(name, time_array): """ @@ -252,16 +273,30 @@ def determine_min_max(name, time_array): for time_index, t0 in enumerate(time_array): if(name in ['E1', 'E2', 'E3', 'B1', 'B2', 'B3']): - h5f = h5py.File('dump_fields/t=%.3f'%(t0) + '.h5', 'r') - fields = np.swapaxes(h5f['EM_fields'][:], 0, 1) - h5f.close() + + fields_file = 'dump_fields/t=%.3f'%(t0) + '.bin' + + # Load fields + viewer = PETSc.Viewer().createBinary(fields_file, + PETSc.Viewer.Mode.READ, + ) + + fields_vec.load(viewer) + fields = da_fields.getVecArray(fields_vec) # [N_q1, N_q2, N_fields] array = return_field_to_be_plotted(name, fields) else: - h5f = h5py.File('dump_moments/t=%.3f'%(t0) + '.h5', 'r') - moments = np.swapaxes(h5f['moments'][:], 0, 1) - h5f.close() + + moments_file = 'dump_moments/t=%.3f'%(t0) + '.bin' + + # Load moments + viewer = PETSc.Viewer().createBinary(moments_file, + PETSc.Viewer.Mode.READ, + ) + + moments_vec.load(viewer) + moments = da_moments.getVecArray(moments_vec) # [N_q1, N_q2, N_moments] array = return_moment_to_be_plotted(name, moments) diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py index bdb1fe14..79b1e810 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py @@ -1,21 +1,25 @@ import numpy as np import matplotlib +matplotlib.use('agg') import pylab as pl +from petsc4py import PETSc -import h5py import domain import params -from post import return_moment_to_be_plotted, return_field_to_be_plotted, determine_min_max, q1, q2 +from post import return_moment_to_be_plotted +from post import return_field_to_be_plotted +from post import determine_min_max, q1, q2 +from post import da_moments, da_fields, moments_vec, fields_vec # Optimized plot parameters to make beautiful plots: -pl.rcParams['figure.figsize'] = 9, 4 -pl.rcParams['figure.dpi'] = 300 +pl.rcParams['figure.figsize'] = 18, 8 +pl.rcParams['figure.dpi'] = 100 pl.rcParams['image.cmap'] = 'jet' pl.rcParams['lines.linewidth'] = 1.5 pl.rcParams['font.family'] = 'serif' pl.rcParams['font.weight'] = 'bold' -pl.rcParams['font.size'] = 30 +pl.rcParams['font.size'] = 25 pl.rcParams['font.sans-serif'] = 'serif' pl.rcParams['text.usetex'] = True pl.rcParams['axes.linewidth'] = 1.5 @@ -42,26 +46,34 @@ params.dt_dump_moments ) +print("Determining limits...") n_min, n_max = determine_min_max('density', time_array) v1_min, v1_max = determine_min_max('v1', time_array) T_min, T_max = determine_min_max('temperature', time_array) B1_min, B1_max = determine_min_max('B1', time_array) -for time_index, t0 in enumerate(time_array): +for time_index, t0 in enumerate(time_array[::-1]): + + print("file = ", time_index) - h5f = h5py.File('dump_moments/t=%.3f'%(t0) + '.h5', 'r') - # dump_moments writes files in the structure (q2, q1, N_s) - # But the post-processing functions require it in the form (q1, q2, N_s) - # By using swapaxes we change (q2, q1, N_s) --> (q1, q2, N_s) - moments = np.swapaxes(h5f['moments'][:], 0, 1) - h5f.close() - - h5f = h5py.File('dump_fields/t=%.3f'%(t0) + '.h5', 'r') - # dump_EM_fields writes files in the structure (q2, q1, N_s) - # But the post-processing functions require it in the form (q1, q2, N_s) - # By using swapaxes we change (q2, q1, N_s) --> (q1, q2, N_s) - fields = np.swapaxes(h5f['EM_fields'][:], 0, 1) - h5f.close() + moments_file = 'dump_moments/t=%.3f'%(t0) + '.bin' + fields_file = 'dump_fields/t=%.3f'%(t0) + '.bin' + + # Load moments + viewer = PETSc.Viewer().createBinary(moments_file, + PETSc.Viewer.Mode.READ, + ) + + moments_vec.load(viewer) + moments = da_moments.getVecArray(moments_vec) # [N_q1, N_q2, N_moments] + + # Load fields + viewer = PETSc.Viewer().createBinary(fields_file, + PETSc.Viewer.Mode.READ, + ) + + fields_vec.load(viewer) + fields = da_fields.getVecArray(fields_vec) # [N_q1, N_q2, N_fields] n = return_moment_to_be_plotted('density', moments) v1 = return_moment_to_be_plotted('v1', moments) @@ -81,6 +93,13 @@ ax2 = fig.add_subplot(2, 2, 2) ax2.plot(q2[0, :], v1[0, :, 0] / params.v0, color = 'C0') ax2.plot(q2[0, :], v1[0, :, 1] / params.v0, '--', color = 'C3') + ax2.axvline(100/24, color='black', linestyle='--') + ax2.axvline(200/24, color='black', linestyle='--') + ax2.axvline(300/24, color='black', linestyle='--') + ax2.axvline(400/24, color='black', linestyle='--') + ax2.axvline(500/24, color='black', linestyle='--') + ax2.axvline(600/24, color='black', linestyle='--') + ax2.axvline(700/24, color='black', linestyle='--') ax2.set_xlabel(r'$y(l_s)$') ax2.set_ylabel(r'$v_x(v_0)$') ax2.set_ylim([1.05 * v1_min / params.v0, 1.05 * v1_max / params.v0]) From b035d59c17c6916321b1da563efaa610c25f81d2 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 27 May 2019 14:18:42 -0400 Subject: [PATCH 02/58] Working version of electronic boltzmann with cartesian coordinates. TODO : dump_aux_arrays --- .../electronic_boltzmann/advection_terms.py | 54 +++ .../collision_operator.py | 361 +++++++++++++++ .../electronic_boltzmann/matrix_inverse.py | 189 ++++++++ .../matrix_inverse_test.py | 96 ++++ bolt/src/electronic_boltzmann/moment_defs.py | 17 + bolt/src/electronic_boltzmann/moments.py | 17 + .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" | 14 + .../boundary_conditions.py | 88 ++++ .../domain.py | 21 + .../edge_potential.py | 161 +++++++ .../enstrophy.py | 142 ++++++ .../initialize.py | 56 +++ .../job_script | 4 + .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py | 380 ++++++++++++++++ .../momentum_space_movie.py | 112 +++++ .../movie.py | 145 ++++++ .../params.py | 144 ++++++ .../phase_vs_y.py | 180 ++++++++ .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/post.py | 422 ++++++++++++++++++ .../signals.py | 171 +++++++ .../vorticity.py | 136 ++++++ 21 files changed, 2910 insertions(+) create mode 100644 bolt/src/electronic_boltzmann/advection_terms.py create mode 100644 bolt/src/electronic_boltzmann/collision_operator.py create mode 100644 bolt/src/electronic_boltzmann/matrix_inverse.py create mode 100644 bolt/src/electronic_boltzmann/matrix_inverse_test.py create mode 100644 bolt/src/electronic_boltzmann/moment_defs.py create mode 100644 bolt/src/electronic_boltzmann/moments.py create mode 100644 "example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/job_script create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/post.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/signals.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/vorticity.py diff --git a/bolt/src/electronic_boltzmann/advection_terms.py b/bolt/src/electronic_boltzmann/advection_terms.py new file mode 100644 index 00000000..246e27f4 --- /dev/null +++ b/bolt/src/electronic_boltzmann/advection_terms.py @@ -0,0 +1,54 @@ +#import numpy as np +import arrayfire as af + +#@af.broadcast +def A_q(t, q1, q2, p1, p2, p3, params): + """Return the terms A_q1, A_q2.""" + + A_q1, A_q2 = params.vel_band + + return (A_q1, A_q2) + +def C_q(t, q1, q2, p1, p2, p3, params): + """Return the terms A_q1, A_q2.""" + + C_q1, C_q2 = params.vel_band + + return (C_q1, C_q2) + +# This can then be called inside A_p if needed: +# F1 = (params.char....)(E1 + ....) + T1(q1, q2, p1, p2, p3) + +def A_p(t, q1, q2, p1, p2, p3, + E1, E2, E3, B1, B2, B3, + params + ): + """Return the terms A_p1, A_p2 and A_p3.""" + e = params.charge_electron + c = params.speed_of_light + B3_mean = params.B3_mean + + v1, v2 = params.vel_band + + dp1_dt = e*(E1 + v2*B3_mean/c) # p1 = hcross * k1 + dp2_dt = e*(E2 - v1*B3_mean/c) # p2 = hcross * k2 + dp3_dt = 0.*p1 + + return (dp1_dt, dp2_dt, dp3_dt) + +def C_p(t, q1, q2, p1, p2, p3, + E1, E2, E3, B1, B2, B3, + params + ): + """Return the terms A_p1, A_p2 and A_p3.""" + e = params.charge_electron + c = params.speed_of_light + B3_mean = params.B3_mean + + v1, v2 = params.vel_band + + dp1_dt = e*(E1 + v2*B3_mean/c) # p1 = hcross * k1 + dp2_dt = e*(E2 - v1*B3_mean/c) # p2 = hcross * k2 + dp3_dt = 0.*p1 + + return (dp1_dt, dp2_dt, dp3_dt) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py new file mode 100644 index 00000000..a54ee561 --- /dev/null +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -0,0 +1,361 @@ +"""Contains the function which returns the Source/Sink term.""" + +from petsc4py import PETSc +import numpy as np +import arrayfire as af +from .matrix_inverse import inverse_4x4_matrix +import domain + +@af.broadcast +def f0_defect_constant_T(f, p1, p2, p3, params): + + mu = params.mu + T = params.T + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp = ((E_upper - mu)/(k*T)) + denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + # TODO: Multiply with the integral measure dp1 * dp2 + a00 = af.sum(T / denominator, 0) + + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + + N_g = domain.N_ghost + error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + + print(" rank = ", params.rank, + "||residual_defect|| = ", error_mass_conservation + ) + + res = eqn_mass_conservation + dres_dmu = -a00 + + delta_mu = -res/dres_dmu + + mu = mu + delta_mu + + af.eval(mu) + + # Solved for mu. Now store in params + params.mu = mu + + # Print final residual + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + + N_g = domain.N_ghost + error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + + print(" rank = ", params.rank, + "||residual_defect|| = ", error_mass_conservation + ) + print(" rank = ", params.rank, + "mu = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), + "T = ", af.mean(params.T[0, 0, N_g:-N_g, N_g:-N_g]) + ) + PETSc.Sys.Print(" ------------------") + + return(fermi_dirac) + + +# Using af.broadcast, since p1, p2, p3 are of size (1, 1, Np1*Np2*Np3) +# All moment quantities are of shape (Nq1, Nq2) +# By wrapping with af.broadcast, we can perform batched operations +# on arrays of different sizes. +@af.broadcast +def f0_defect(f, p1, p2, p3, params): + + # Initial guess + mu = params.mu + T = params.T + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp = ((E_upper - mu)/(k*T)) + denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + # TODO: Multiply with the integral measure dp1 * dp2 + a00 = af.sum(T / denominator, 0) + a01 = af.sum((E_upper - mu) / denominator, 0) + a10 = af.sum(E_upper*T / denominator, 0) + a11 = af.sum(E_upper*(E_upper - mu) / denominator, 0) + + # Solve Ax = b + # where A == Jacobian, + # x == delta guess (correction to guess), + # b = -residual + + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + second_moment = E_upper*(f - fermi_dirac) + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_energy_conservation = af.sum(second_moment, 0) + + N_g = domain.N_ghost + error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + error_energy_conservation = af.max(af.abs(eqn_energy_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + + residual = [eqn_mass_conservation, eqn_energy_conservation] + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1]))] + ) + print(" ||residual_defect|| = ", error_norm) + +# if (error_norm < 1e-9): +# params.mu = mu +# params.T = T +# return(fermi_dirac) + + b0 = eqn_mass_conservation + b1 = eqn_energy_conservation + + det = a01*a10 - a00*a11 + delta_mu = -(a11*b0 - a01*b1)/det + delta_T = (a10*b0 - a00*b1)/det + + mu = mu + delta_mu + T = T + delta_T + + af.eval(mu, T) + + # Solved for (mu, T). Now store in params + params.mu = mu + params.T = T + + # Print final residual + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + second_moment = E_upper*(f - fermi_dirac) + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_energy_conservation = af.sum(second_moment, 0) + + residual = [eqn_mass_conservation, eqn_energy_conservation] + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1]))] + ) + print(" ||residual_defect|| = ", error_norm) + print(" mu = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), + "T = ", af.mean(params.T[0, 0, N_g:-N_g, N_g:-N_g]) + ) + print(" ------------------") + + return(fermi_dirac) + +@af.broadcast +def f0_ee(f, p1, p2, p3, params): + + # Initial guess + mu_ee = params.mu_ee + T_ee = params.T_ee + vel_drift_x = params.vel_drift_x + vel_drift_y = params.vel_drift_y + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp1 = (E_upper - mu_ee - p1*vel_drift_x - p2*vel_drift_y) + tmp = (tmp1/(k*T_ee)) + denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + a_0 = T_ee / denominator + a_1 = tmp1 / denominator + a_2 = T_ee * p1 / denominator + a_3 = T_ee * p2 / denominator + + af.eval(a_0, a_1, a_2, a_3) + + # TODO: Multiply with the integral measure dp1 * dp2 + a_00 = af.sum(a_0, 0) + a_01 = af.sum(a_1, 0) + a_02 = af.sum(a_2, 0) + a_03 = af.sum(a_3, 0) + + a_10 = af.sum(E_upper * a_0, 0) + a_11 = af.sum(E_upper * a_1, 0) + a_12 = af.sum(E_upper * a_2, 0) + a_13 = af.sum(E_upper * a_3, 0) + + a_20 = af.sum(p1 * a_0, 0) + a_21 = af.sum(p1 * a_1, 0) + a_22 = af.sum(p1 * a_2, 0) + a_23 = af.sum(p1 * a_3, 0) + + a_30 = af.sum(p2 * a_0, 0) + a_31 = af.sum(p2 * a_1, 0) + a_32 = af.sum(p2 * a_2, 0) + a_33 = af.sum(p2 * a_3, 0) + + A = [ [a_00, a_01, a_02, a_03], \ + [a_10, a_11, a_12, a_13], \ + [a_20, a_21, a_22, a_23], \ + [a_30, a_31, a_32, a_33] \ + ] + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p1 - vel_drift_y*p2 + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = (f - fermi_dirac) + second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p1*(f - fermi_dirac) + first_moment_y = p2*(f - fermi_dirac) + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_energy_conservation = af.sum(second_moment, 0) + eqn_mom_x_conservation = af.sum(first_moment_x, 0) + eqn_mom_y_conservation = af.sum(first_moment_y, 0) + + residual = [eqn_mass_conservation, \ + eqn_energy_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])), + af.max(af.abs(residual[3])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + +# if (error_norm < 1e-13): +# params.mu_ee = mu_ee +# params.T_ee = T_ee +# params.vel_drift_x = vel_drift_x +# params.vel_drift_y = vel_drift_y +# return(fermi_dirac) + + b_0 = eqn_mass_conservation + b_1 = eqn_energy_conservation + b_2 = eqn_mom_x_conservation + b_3 = eqn_mom_y_conservation + b = [b_0, b_1, b_2, b_3] + + # Solve Ax = b + # where A == Jacobian, + # x == delta guess (correction to guess), + # b = -residual + + A_inv = inverse_4x4_matrix(A) + + x_0 = A_inv[0][0]*b[0] + A_inv[0][1]*b[1] + A_inv[0][2]*b[2] + A_inv[0][3]*b[3] + x_1 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + A_inv[1][3]*b[3] + x_2 = A_inv[2][0]*b[0] + A_inv[2][1]*b[1] + A_inv[2][2]*b[2] + A_inv[2][3]*b[3] + x_3 = A_inv[3][0]*b[0] + A_inv[3][1]*b[1] + A_inv[3][2]*b[2] + A_inv[3][3]*b[3] + + delta_mu = x_0 + delta_T = x_1 + delta_vx = x_2 + delta_vy = x_3 + + mu_ee = mu_ee + delta_mu + T_ee = T_ee + delta_T + vel_drift_x = vel_drift_x + delta_vx + vel_drift_y = vel_drift_y + delta_vy + + af.eval(mu_ee, T_ee, vel_drift_x, vel_drift_y) + + # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params + params.mu_ee = mu_ee + params.T_ee = T_ee + params.vel_drift_x = vel_drift_x + params.vel_drift_y = vel_drift_y + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p1 - vel_drift_y*p2 + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p1*(f - fermi_dirac) + first_moment_y = p2*(f - fermi_dirac) + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_energy_conservation = af.sum(second_moment, 0) + eqn_mom_x_conservation = af.sum(first_moment_x, 0) + eqn_mom_y_conservation = af.sum(first_moment_y, 0) + + residual = [eqn_mass_conservation, \ + eqn_energy_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation + ] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])), + af.max(af.abs(residual[3])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + N_g = domain.N_ghost + print(" rank = ", params.rank, + "mu_ee = ", af.mean(params.mu_ee[0, 0, N_g:-N_g, N_g:-N_g]), + "T_ee = ", af.mean(params.T_ee[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_x[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_y[0, 0, N_g:-N_g, N_g:-N_g]) + ) + PETSc.Sys.Print(" ------------------") + + return(fermi_dirac) + +def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): + """Return BGK operator -(f-f0)/tau.""" + + if(af.any_true(params.tau_defect(q1, q2, p1, p2, p3) == 0)): + if (flag == False): + return(0.*f) + + f = f0_defect_constant_T(f, p1, p2, p3, params) + + return(f) + print('RTA : ', f.shape) + print ('RTA : ',f0_defect_constant_T(f, p1, p2, p3, params).shape) + C_f = -( f - f0_defect_constant_T(f, p1, p2, p3, params) \ + ) / params.tau_defect(q1, q2, p1, p2, p3) \ + -( f - f0_ee(f, p1, p2, p3, params) + ) / params.tau_ee(q1, q2, p1, p2, p3) + # When (f - f0) is NaN. Dividing by np.inf doesn't give 0 + # TODO: WORKAROUND + + # Activate the following line to set collision operator to zero + #C_f = 0.*f + + af.eval(C_f) + return(C_f) + diff --git a/bolt/src/electronic_boltzmann/matrix_inverse.py b/bolt/src/electronic_boltzmann/matrix_inverse.py new file mode 100644 index 00000000..4b987180 --- /dev/null +++ b/bolt/src/electronic_boltzmann/matrix_inverse.py @@ -0,0 +1,189 @@ +import numpy as np +import arrayfire as af + +def inverse_4x4_matrix(A): +# TO TEST: +# A_test = np.random.rand(4, 4) +# A_inv_test = np.linalg.inv(A_test) +# A_inv = np.array(inverse_4x4_matrix(A_test)) +# print("err = ", np.max(np.abs(A_inv - A_inv_test))) + + + det = \ + A[0][0]*A[1][1]*A[2][2]*A[3][3] \ + + A[0][0]*A[1][2]*A[2][3]*A[3][1] \ + + A[0][0]*A[1][3]*A[2][1]*A[3][2] \ + + A[0][1]*A[1][0]*A[2][3]*A[3][2] \ + + A[0][1]*A[1][2]*A[2][0]*A[3][3] \ + + A[0][1]*A[1][3]*A[2][2]*A[3][0] \ + + A[0][2]*A[1][0]*A[2][1]*A[3][3] \ + + A[0][2]*A[1][1]*A[2][3]*A[3][0] \ + + A[0][2]*A[1][3]*A[2][0]*A[3][1] \ + + A[0][3]*A[1][0]*A[2][2]*A[3][1] \ + + A[0][3]*A[1][1]*A[2][0]*A[3][2] \ + + A[0][3]*A[1][2]*A[2][1]*A[3][0] \ + - A[0][0]*A[1][1]*A[2][3]*A[3][2] \ + - A[0][0]*A[1][2]*A[2][1]*A[3][3] \ + - A[0][0]*A[1][3]*A[2][2]*A[3][1] \ + - A[0][1]*A[1][0]*A[2][2]*A[3][3] \ + - A[0][1]*A[1][2]*A[2][3]*A[3][0] \ + - A[0][1]*A[1][3]*A[2][0]*A[3][2] \ + - A[0][2]*A[1][0]*A[2][3]*A[3][1] \ + - A[0][2]*A[1][1]*A[2][0]*A[3][3] \ + - A[0][2]*A[1][3]*A[2][1]*A[3][0] \ + - A[0][3]*A[1][0]*A[2][1]*A[3][2] \ + - A[0][3]*A[1][1]*A[2][2]*A[3][0] \ + - A[0][3]*A[1][2]*A[2][0]*A[3][1] + + af.eval(det) + + A_inv = [[0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ] + + A_inv[0][0] = \ + ( A[1][1]*A[2][2]*A[3][3] + + A[1][2]*A[2][3]*A[3][1] + + A[1][3]*A[2][1]*A[3][2] + - A[1][1]*A[2][3]*A[3][2] + - A[1][2]*A[2][1]*A[3][3] + - A[1][3]*A[2][2]*A[3][1])/det + + A_inv[0][1] = \ + ( A[0][1]*A[2][3]*A[3][2] + + A[0][2]*A[2][1]*A[3][3] + + A[0][3]*A[2][2]*A[3][1] + - A[0][1]*A[2][2]*A[3][3] + - A[0][2]*A[2][3]*A[3][1] + - A[0][3]*A[2][1]*A[3][2])/det + + A_inv[0][2] = \ + ( A[0][1]*A[1][2]*A[3][3] + + A[0][2]*A[1][3]*A[3][1] + + A[0][3]*A[1][1]*A[3][2] + - A[0][1]*A[1][3]*A[3][2] + - A[0][2]*A[1][1]*A[3][3] + - A[0][3]*A[1][2]*A[3][1])/det + + A_inv[0][3] = \ + ( A[0][1]*A[1][3]*A[2][2] + + A[0][2]*A[1][1]*A[2][3] + + A[0][3]*A[1][2]*A[2][1] + - A[0][1]*A[1][2]*A[2][3] + - A[0][2]*A[1][3]*A[2][1] + - A[0][3]*A[1][1]*A[2][2])/det + + # b21 + A_inv[1][0] = \ + ( A[1][0]*A[2][3]*A[3][2] + + A[1][2]*A[2][0]*A[3][3] + + A[1][3]*A[2][2]*A[3][0] + - A[1][0]*A[2][2]*A[3][3] + - A[1][2]*A[2][3]*A[3][0] + - A[1][3]*A[2][0]*A[3][2])/det + + A_inv[1][1] = \ + ( A[0][0]*A[2][2]*A[3][3] + + A[0][2]*A[2][3]*A[3][0] + + A[0][3]*A[2][0]*A[3][2] + - A[0][0]*A[2][3]*A[3][2] + - A[0][2]*A[2][0]*A[3][3] + - A[0][3]*A[2][2]*A[3][0])/det + + A_inv[1][2] = \ + ( A[0][0]*A[1][3]*A[3][2] + + A[0][2]*A[1][0]*A[3][3] + + A[0][3]*A[1][2]*A[3][0] + - A[0][0]*A[1][2]*A[3][3] + - A[0][2]*A[1][3]*A[3][0] + - A[0][3]*A[1][0]*A[3][2])/det + + A_inv[1][3] = \ + ( A[0][0]*A[1][2]*A[2][3] + + A[0][2]*A[1][3]*A[2][0] + + A[0][3]*A[1][0]*A[2][2] + - A[0][0]*A[1][3]*A[2][2] + - A[0][2]*A[1][0]*A[2][3] + - A[0][3]*A[1][2]*A[2][0])/det + + # b31 + A_inv[2][0] = \ + ( A[1][0]*A[2][1]*A[3][3] + + A[1][1]*A[2][3]*A[3][0] + + A[1][3]*A[2][0]*A[3][1] + - A[1][0]*A[2][3]*A[3][1] + - A[1][1]*A[2][0]*A[3][3] + - A[1][3]*A[2][1]*A[3][0])/det + + # b32 + A_inv[2][1] = \ + ( A[0][0]*A[2][3]*A[3][1] + + A[0][1]*A[2][0]*A[3][3] + + A[0][3]*A[2][1]*A[3][0] + - A[0][0]*A[2][1]*A[3][3] + - A[0][1]*A[2][3]*A[3][0] + - A[0][3]*A[2][0]*A[3][1])/det + + A_inv[2][2] = \ + ( A[0][0]*A[1][1]*A[3][3] + + A[0][1]*A[1][3]*A[3][0] + + A[0][3]*A[1][0]*A[3][1] + - A[0][0]*A[1][3]*A[3][1] + - A[0][1]*A[1][0]*A[3][3] + - A[0][3]*A[1][1]*A[3][0])/det + + A_inv[2][3] = \ + ( A[0][0]*A[1][3]*A[2][1] + + A[0][1]*A[1][0]*A[2][3] + + A[0][3]*A[1][1]*A[2][0] + - A[0][0]*A[1][1]*A[2][3] + - A[0][1]*A[1][3]*A[2][0] + - A[0][3]*A[1][0]*A[2][1])/det + + # b41 + A_inv[3][0] = \ + ( A[1][0]*A[2][2]*A[3][1] + + A[1][1]*A[2][0]*A[3][2] + + A[1][2]*A[2][1]*A[3][0] + - A[1][0]*A[2][1]*A[3][2] + - A[1][1]*A[2][2]*A[3][0] + - A[1][2]*A[2][0]*A[3][1])/det + + # b42 + A_inv[3][1] = \ + ( A[0][0]*A[2][1]*A[3][2] + + A[0][1]*A[2][2]*A[3][0] + + A[0][2]*A[2][0]*A[3][1] + - A[0][0]*A[2][2]*A[3][1] + - A[0][1]*A[2][0]*A[3][2] + - A[0][2]*A[2][1]*A[3][0])/det + + # b43 + A_inv[3][2] = \ + ( A[0][0]*A[1][2]*A[3][1] + + A[0][1]*A[1][0]*A[3][2] + + A[0][2]*A[1][1]*A[3][0] + - A[0][0]*A[1][1]*A[3][2] + - A[0][1]*A[1][2]*A[3][0] + - A[0][2]*A[1][0]*A[3][1])/det + + A_inv[3][3] = \ + ( A[0][0]*A[1][1]*A[2][2] + + A[0][1]*A[1][2]*A[2][0] + + A[0][2]*A[1][0]*A[2][1] + - A[0][0]*A[1][2]*A[2][1] + - A[0][1]*A[1][0]*A[2][2] + - A[0][2]*A[1][1]*A[2][0])/det + + arrays_to_be_evaled = \ + [A_inv[0][0], A_inv[0][1], A_inv[0][2], A_inv[0][3], \ + A_inv[1][0], A_inv[1][1], A_inv[1][2], A_inv[1][3], \ + A_inv[2][0], A_inv[2][1], A_inv[2][2], A_inv[2][3], \ + A_inv[3][0], A_inv[3][1], A_inv[3][2], A_inv[3][3] \ + ] + + af.eval(*arrays_to_be_evaled) + + return(A_inv) diff --git a/bolt/src/electronic_boltzmann/matrix_inverse_test.py b/bolt/src/electronic_boltzmann/matrix_inverse_test.py new file mode 100644 index 00000000..a628031b --- /dev/null +++ b/bolt/src/electronic_boltzmann/matrix_inverse_test.py @@ -0,0 +1,96 @@ +import numpy as np +import arrayfire as af + +def inverse_3x3_matrix(A): +# TO TEST: +# A_test = np.random.rand(3, 3) +# A_inv_test = np.linalg.inv(A_test) +# A_inv = np.array(inverse_3x3_matrix(A_test)) +# print("err = ", np.max(np.abs(A_inv - A_inv_test))) + + + det = \ + A[0][0]*A[1][1]*A[2][2] \ + - A[0][0]*A[1][2]*A[2][1] \ + - A[0][1]*A[1][0]*A[2][2] \ + + A[0][1]*A[1][2]*A[2][0] \ + + A[0][2]*A[1][0]*A[2][1] \ + - A[0][2]*A[1][1]*A[2][0] \ + + #af.eval(det) + + #TODO : Raise an exception if the matrix is singular + #print ('determinant : ') + #print (det) + + A_inv = [[0, 0, 0], \ + [0, 0, 0], \ + [0, 0, 0] \ + ] + + cofactors = [[0, 0, 0], \ + [0, 0, 0], \ + [0, 0, 0] \ + ] + + adjoint = [[0, 0, 0], \ + [0, 0, 0], \ + [0, 0, 0] \ + ] + + cofactors[0][0] = +(A[1][1]*A[2][2] - A[1][2]*A[2][1]) + cofactors[0][1] = -(A[1][0]*A[2][2] - A[1][2]*A[2][0]) + cofactors[0][2] = +(A[1][0]*A[2][1] - A[1][1]*A[2][0]) + cofactors[1][0] = -(A[0][1]*A[2][2] - A[0][2]*A[2][1]) + cofactors[1][1] = +(A[0][0]*A[2][2] - A[0][2]*A[2][0]) + cofactors[1][2] = -(A[0][0]*A[2][1] - A[0][1]*A[2][0]) + cofactors[2][0] = +(A[0][1]*A[1][2] - A[0][2]*A[1][1]) + cofactors[2][1] = -(A[0][0]*A[1][2] - A[0][2]*A[1][0]) + cofactors[2][2] = +(A[0][0]*A[1][1] - A[0][1]*A[1][0]) + + adjoint[0][0] = cofactors[0][0] + adjoint[0][1] = cofactors[1][0] + adjoint[0][2] = cofactors[2][0] + adjoint[1][0] = cofactors[0][1] + adjoint[1][1] = cofactors[1][1] + adjoint[1][2] = cofactors[2][1] + adjoint[2][0] = cofactors[0][2] + adjoint[2][1] = cofactors[1][2] + adjoint[2][2] = cofactors[2][2] + + + A_inv = adjoint/det + + #A_inv[0][1] = adjoint[0][1]/det + + #A_inv[0][2] = adjoint[0][2]/det + + #A_inv[1][0] = adjoint[1][0]/det + # + #A_inv[1][1] = adjoint[1][1]/det + + #A_inv[1][2] = adjoint[1][2]/det + + #A_inv[2][0] = adjoint[2][0]/det + + #A_inv[2][1] = adjoint[2][1]/det + + #A_inv[2][2] = adjoint[2][2]/det + + + arrays_to_be_evaled = \ + [A_inv[0][0], A_inv[0][1], A_inv[0][2], \ + A_inv[1][0], A_inv[1][1], A_inv[1][2], \ + A_inv[2][0], A_inv[2][1], A_inv[2][2] \ + ] + + #af.eval(*arrays_to_be_evaled) + + return(A_inv) +def main(): + A_test = np.random.rand(3, 3) + A_inv_test = np.linalg.inv(A_test) + A_inv = np.array(inverse_3x3_matrix(A_test)) + print("err = ", A_inv - A_inv_test) + +main() diff --git a/bolt/src/electronic_boltzmann/moment_defs.py b/bolt/src/electronic_boltzmann/moment_defs.py new file mode 100644 index 00000000..6f5a9357 --- /dev/null +++ b/bolt/src/electronic_boltzmann/moment_defs.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from bolt.src.utils.integral_over_v import integral_over_v + +#TODO : Import required constants from libraries +# : pi = 3.1415926535 +# : h_bar = 1.0545718e-4 + +def density(f, v1, v2, v3, integral_measure): + return(integral_over_v(f, integral_measure)) + +def j_x(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * (4./(2.*3.1415926535*1.0545718e-4)**2) * v1, integral_measure)) + +def j_y(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * (4./(2.*3.1415926535*1.0545718e-4)**2) * v2, integral_measure)) diff --git a/bolt/src/electronic_boltzmann/moments.py b/bolt/src/electronic_boltzmann/moments.py new file mode 100644 index 00000000..fba232f6 --- /dev/null +++ b/bolt/src/electronic_boltzmann/moments.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import numpy as np + +from bolt.src.utils.integral_over_v import integral_over_v + +import params + +def density(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * v1**(4./(2.*np.pi*params.h_bar)), integral_measure)) + +def j_x(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * v1**(4./(2.*np.pi*params.h_bar)), integral_measure)) + +def j_y(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * v2**(4./(2.*np.pi*params.h_bar)), integral_measure)) diff --git "a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" "b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" new file mode 100644 index 00000000..b574f48c --- /dev/null +++ "b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from bolt.src.utils.integral_over_v import integral_over_v + + +def density(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * v1**(4./(2.*3.1415926535*1.0545718e-4)), integral_measure)) + +def j_x(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * v1**(4./(2.*3.1415926535*1.0545718e-4)), integral_measure)) + +def j_y(f, v1, v2, v3, integral_measure): + return(integral_over_v(f * v2**(4./(2.*3.1415926535*1.0545718e-4)), integral_measure)) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py new file mode 100644 index 00000000..85724d01 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py @@ -0,0 +1,88 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror+dirichlet' +in_q1_right = 'mirror+dirichlet' +in_q2_bottom = 'mirror' +in_q2_top = 'mirror' + +@af.broadcast +def f_left(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_in = params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p1 - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p1 - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_right(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_out = params.vel_drift_x_out * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p1 - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py new file mode 100644 index 00000000..7bd57eda --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py @@ -0,0 +1,21 @@ +q1_start = 0. +q1_end = 5.0 +N_q1 = 10 + +q2_start = 0. +q2_end = 10. +N_q2 = 20 + +p1_start = [-0.04] +p1_end = [0.04] +N_p1 = 16 + +p2_start = [-0.04] +p2_end = [0.04] +N_p2 = 16 + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/edge_potential.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/edge_potential.py new file mode 100644 index 00000000..b50b3bf5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/edge_potential.py @@ -0,0 +1,161 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#print("Reading sensor signal...") +print("Loading data...") +density = [] +edge_density = [] +for file_number, dump_file in enumerate(moment_files): + + print("File number = ", file_number, ' of ', moment_files.size) + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density.append(moments[:, :, 0]) + edge_density.append(density[file_number][0, sensor_1_left_indices]) + +density = np.array(density) +edge_density = np.array(edge_density) + +mean_density = np.mean(density) +max_density = np.max(density) +min_density = np.min(density) + +np.savetxt("edge_density.txt", edge_density) + +print("Dumping data...") +for file_number in yt.parallel_objects(range(density.shape[0])): + + print("File number = ", file_number, ' of ', moment_files.size) + + pl.semilogy(q2[sensor_1_left_indices], + density[file_number][0, sensor_1_left_indices], + ) + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.title(r'Time = ' + "%.2f"%(file_number*dt*dump_interval) + " ps") + + pl.xlim([sensor_1_left_start, sensor_1_left_end]) + #pl.ylim([min_density-mean_density, max_density-mean_density]) + #pl.ylim([0., np.log(max_density)]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$ ps, $\\tau_\mathrm{mr} = 3.0$ ps') + #pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.savefig('images/density_' + '%06d'%file_number + '.png') + pl.clf() + + + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/enstrophy.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py new file mode 100644 index 00000000..8e6609c6 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py @@ -0,0 +1,56 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 0.*q1 + params.vel_drift_y = 0.*q1 + params.phi = 0.*q1 + + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + params.vel_drift_x = 0.*q1 + 0e-3 + params.vel_drift_y = 0.*q1 + 0e-3 + + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + E_upper = params.E_band + params.charge[0]*params.phi + + f = (1./(af.exp( (E_upper - params.vel_drift_x*p1 + - params.vel_drift_y*p2 + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/job_script b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/job_script new file mode 100644 index 00000000..75c49d28 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/job_script @@ -0,0 +1,4 @@ +#!/bin/bash +#SBATCH -p gpu -n 4 --gres=gpu:4 -c1 --hint=nomultithread -t 2-00:00 +# (Note: use one MPI process per gpu, update both gres and -n together; max 6) +time mpirun python main.py -snes_monitor -snes_max_it 1 -snes_lag_jacobian_persists TRUE -snes_lag_jacobian 1000000 -snes_atol 1e-50 -snes_rtol 1e-50 > output.txt diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py new file mode 100644 index 00000000..9ddbb6e7 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py @@ -0,0 +1,380 @@ +import sys +import arrayfire as af +import numpy as np +import pylab as pl +import h5py +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +#from bolt.lib.nonlinear.fields.fields.fields \ +# import fields_solver.compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +#pl.rcParams['figure.figsize'] = 12, 7.5 +#pl.rcParams['figure.dpi'] = 150 +#pl.rcParams['image.cmap'] = 'jet' +#pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['font.family'] = 'serif' +#pl.rcParams['font.weight'] = 'bold' +#pl.rcParams['font.size'] = 20 +#pl.rcParams['font.sans-serif'] = 'serif' +#pl.rcParams['text.usetex'] = False +#pl.rcParams['axes.linewidth'] = 1.5 +#pl.rcParams['axes.titlesize'] = 'medium' +#pl.rcParams['axes.labelsize'] = 'medium' +# +#pl.rcParams['xtick.major.size'] = 8 +#pl.rcParams['xtick.minor.size'] = 4 +#pl.rcParams['xtick.major.pad'] = 8 +#pl.rcParams['xtick.minor.pad'] = 8 +#pl.rcParams['xtick.color'] = 'k' +#pl.rcParams['xtick.labelsize'] = 'medium' +#pl.rcParams['xtick.direction'] = 'in' +# +#pl.rcParams['ytick.major.size'] = 8 +#pl.rcParams['ytick.minor.size'] = 4 +#pl.rcParams['ytick.major.pad'] = 8 +#pl.rcParams['ytick.minor.pad'] = 8 +#pl.rcParams['ytick.color'] = 'k' +#pl.rcParams['ytick.labelsize'] = 'medium' +#pl.rcParams['ytick.direction'] = 'in' + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moment_defs + ) + +# Time parameters: +dt = params.dt +t_final = params.t_final +params.current_time = t0 = 0.0 +params.time_step = time_step = 0 +dump_counter = 0 +dump_time_array = [] + +N_g = domain.N_ghost + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +params.rank = nls._comm.rank + +if (params.restart): + nls.load_distribution_function(params.restart_file) + + viewer = PETSc.Viewer().createHDF5(params.phi_restart_file, + PETSc.Viewer.Mode.READ, + comm=nls._comm + ) + PETSc.Object.setName(nls.poisson.glob_phi, 'phi') + nls.poisson.glob_phi.load(viewer) + + params.solve_for_equilibrium = 0 + #compute_electrostatic_fields(nls) + + params.mu = params.global_chem_potential + params.charge[0]*params.phi + params.mu_analytic = params.global_chem_potential + params.charge[0]*params.phi + params.mu = af.moddims(params.mu, + 1, + nls.N_q1_local + 2*N_g, + nls.N_q2_local + 2*N_g + ) +else: + if (params.solve_for_equilibrium): + PETSc.Sys.Print("=============================") + PETSc.Sys.Print("Solving for equilibrium state") + PETSc.Sys.Print("=============================") + params.solve_for_equilibrium = 1 + #compute_electrostatic_fields(nls) + params.solve_for_equilibrium = 0 + + params.mu = params.global_chem_potential + params.charge[0]*params.phi + params.mu = af.moddims(params.mu, + 1, + nls.N_q1_local + 2*N_g, + nls.N_q2_local + 2*N_g + ) + + nls.f = params.fermi_dirac(params.mu, params.E_band) + + PETSc.Sys.Print("=====================") + PETSc.Sys.Print("Solution diagnostics:") + PETSc.Sys.Print("=====================") + + density = nls.compute_moments('density') + print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, N_g:-N_g, N_g:-N_g]), "\n", + #" = ", af.mean(params.phi[N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, N_g:-N_g, N_g:-N_g]), "\n" + #" |E1| = ", af.mean(af.abs(nls.cell_centered_EM_fields[0, N_g:-N_g, N_g:-N_g])), + #"\n", + #" |E2| = ", af.mean(af.abs(nls.cell_centered_EM_fields[1, N_g:-N_g, N_g:-N_g])) + ) + + PETSc.Sys.Print("===============") + PETSc.Sys.Print("Dumping data...") + PETSc.Sys.Print("===============") + + nls.dump_moments('dumps/moments_eqbm') + nls.dump_distribution_function('dumps/f_eqbm') + + # Dump EM fields + #af.flat(nls.cell_centered_EM_fields[:, N_g:-N_g, N_g:-N_g]).to_ndarray(nls._glob_fields_array) + #PETSc.Object.setName(nls._glob_fields, 'fields') + #viewer = PETSc.Viewer().createHDF5('dumps/fields_eqbm.h5', + # 'w', comm=nls._comm + # ) + #viewer(nls._glob_fields) + + # Dump eqbm potential + PETSc.Object.setName(nls.poisson.glob_phi, 'phi') + viewer = PETSc.Viewer().createHDF5('dumps/phi_eqbm.h5', + 'w', comm=nls._comm + ) + viewer(nls.poisson.glob_phi) + + sys.exit("Terminating execution") + else: + + #compute_electrostatic_fields(nls) + pass + +density = nls.compute_moments('density') +print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + #" = ", af.mean(params.phi[N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + #" |E1| = ", af.mean(af.abs(nls.cell_centered_EM_fields[0, N_g:-N_g, N_g:-N_g])), + #"\n", + #" |E2| = ", af.mean(af.abs(nls.cell_centered_EM_fields[1, N_g:-N_g, N_g:-N_g])) + ) + +nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) +while t0 < t_final: + + # Refine to machine error + if (time_step==0): + params.collision_nonlinear_iters = 10 + else: + params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters + + dump_steps = params.dump_steps + # Uncomment if need to dump more frequently during a desired time interval + #if (params.current_time > 149. and params.current_time < 154): + # dump_steps = 1 + #else: + # dump_steps = params.dump_steps + if (time_step%dump_steps==0): + file_number = '%06d'%dump_counter + dump_counter= dump_counter + 1 + dump_time_array.append(params.current_time) + PETSc.Sys.Print("=====================================================") + PETSc.Sys.Print("Dumping data at time step =", time_step, + ", file number =", file_number + ) + PETSc.Sys.Print("=====================================================") + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + + nls.dump_moments('dumps/moments_' + file_number) + if (time_step==0): + nls.dump_distribution_function('dumps/f_' + file_number) + nls.dump_distribution_function('dumps/f_' + file_number) + #nls.dump_aux_arrays([params.mu, + # params.mu_ee, + # params.T_ee, + # params.vel_drift_x, params.vel_drift_y], + # 'lagrange_multipliers', + # 'dumps/lagrange_multipliers_' + file_number + # ) + + # Dump EM fields + #af.flat(nls.cell_centered_EM_fields[:, N_g:-N_g, N_g:-N_g]).to_ndarray(nls._glob_fields_array) + #PETSc.Object.setName(nls._glob_fields, 'fields') + #viewer = PETSc.Viewer().createHDF5('dumps/fields_' + # + '%06d'%(time_step/dump_steps) + '.h5', + # 'w', comm=nls._comm + # ) + #viewer(nls._glob_fields) + + + dt_force_constraint = 0. +# dt_force_constraint = \ +# 0.5 * np.min(nls.dp1, nls.dp2) \ +# / np.max((af.max(nls.cell_centered_EM_fields[0]), +# af.max(nls.cell_centered_EM_fields[1]) +# ) +# ) + + + PETSc.Sys.Print("Time step =", time_step, ", Time =", t0) + + mean_density = af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]) + density_pert = density - mean_density + +# if (time_step%1==0): +# chemical_potential = np.array(params.mu)[0, :, :] \ +# - params.charge*np.array(params.phi)[:, :] +# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(params.mu)[0, N_g:-N_g, N_g:-N_g], \ +# 100, cmap='bwr' +# ) +# pl.title('Time = ' + "%.2f"%(t0) ) +# pl.xlabel('$x$') +# pl.ylabel('$y$') +# pl.colorbar() +# pl.gca().set_aspect('equal') +# pl.savefig('/tmp/mu_' + '%06d'%time_step + '.png' ) +# pl.clf() +# +# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(density)[0, N_g:-N_g, N_g:-N_g], \ +# 100, cmap='bwr' +# ) +# pl.title('Time = ' + "%.2f"%(t0) ) +# pl.xlabel('$x$') +# pl.ylabel('$y$') +# pl.colorbar() +# pl.gca().set_aspect('equal') +# pl.savefig('/tmp/density_' + '%06d'%time_step + '.png' ) +# pl.clf() +# +# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(params.phi)[N_g:-N_g, N_g:-N_g], \ +# 100, cmap='bwr' +# ) +# pl.title('Time = ' + "%.2f"%(t0) ) +# pl.xlabel('$x$') +# pl.ylabel('$y$') +# pl.colorbar() +# pl.gca().set_aspect('equal') +# pl.savefig('/tmp/phi_' + '%06d'%time_step + '.png' ) +# pl.clf() +# +# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.cell_centered_EM_fields)[0, N_g:-N_g, N_g:-N_g], \ +# 100, cmap='bwr' +# ) +# pl.title('Time = ' + "%.2f"%(t0) ) +# pl.xlabel('$x$') +# pl.ylabel('$y$') +# pl.colorbar() +# pl.gca().set_aspect('equal') +# pl.savefig('/tmp/E1_' + '%06d'%time_step + '.png' ) +# pl.clf() +# +# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ +# np.array(nls.cell_centered_EM_fields)[1, N_g:-N_g, N_g:-N_g], \ +# 100, cmap='bwr' +# ) +# pl.title('Time = ' + "%.2f"%(t0) ) +# pl.xlabel('$x$') +# pl.ylabel('$y$') +# pl.colorbar() +# pl.gca().set_aspect('equal') +# pl.savefig('/tmp/E2_' + '%06d'%time_step + '.png' ) +# pl.clf() +# +# f_at_desired_q = af.moddims(nls.f[:, N_g, N_g + 0.*nls.N_q2/2], +# nls.N_p1, nls.N_p2 +# ) +# p1 = af.moddims(nls.p1, nls.N_p1, nls.N_p2) +# p2 = af.moddims(nls.p2, nls.N_p1, nls.N_p2) +# pl.contourf(np.array(p1), \ +# np.array(p2), \ +# np.array((f_at_desired_q)), \ +# 100, cmap='bwr' +# ) +# pl.title('Time = ' + "%.2f"%(t0) ) +# pl.xlabel('$x$') +# pl.ylabel('$y$') +# pl.colorbar() +# pl.gca().set_aspect('equal') +# pl.savefig('/tmp/f_' + '%06d'%time_step + '.png' ) +# pl.clf() + + nls.strang_timestep(dt) + t0 = t0 + dt + time_step = time_step + 1 + params.time_step = time_step + params.current_time = t0 + + # Floors + nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) + + density = nls.compute_moments('density') + print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + #" = ", af.mean(params.phi[N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + #" |E1| = ", af.mean(af.abs(nls.cell_centered_EM_fields[0, N_g:-N_g, N_g:-N_g])), + #"\n", + #" |E2| = ", af.mean(af.abs(nls.cell_centered_EM_fields[1, N_g:-N_g, N_g:-N_g])) + ) + PETSc.Sys.Print("--------------------\n") + +nls.dump_distribution_function('dumps/f_laststep') + +#phi_array = nls.poisson.glob_phi.getArray() +#phi_array = phi_array.reshape([nls.poisson.N_q3_3D_local, \ +# nls.poisson.N_q2_3D_local, \ +# nls.poisson.N_q1_3D_local] +# ) +# +#q3_index = np.where(nls.poisson.q3_3D[N_g:-N_g] >= nls.location_in_q3)[0][0] +#pl.plot(nls.poisson.q1_3D[N_g:-N_g], +# phi_array[q3_index, nls.poisson.N_q2_3D_local/2, :], 'o-' +# ) +#pl.show() + +#pl.rcParams['figure.figsize'] = 20, 7.5 +#pl.subplot(121) +#N_g = domain.N_ghost +#pl.contourf( +# phi_array[nls.N_q3_poisson/2, :, :], 100, cmap='jet' +# ) +#pl.colorbar() +#pl.title('Top View') +#pl.xlabel('$x$') +#pl.ylabel('$y$') +#pl.gca().set_aspect('equal') +# +#pl.subplot(122) +#pl.contourf(phi_array[:, nls.N_q2_poisson/2, :], 100, cmap='jet') +#pl.title('Side View') +#pl.xlabel('$x$') +#pl.ylabel('$z$') +#pl.colorbar() +#pl.gca().set_aspect('equal') +#pl.show() diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py new file mode 100644 index 00000000..f82105ea --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py @@ -0,0 +1,112 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - \ + domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - \ + domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +filepath = \ +'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +distribution_function_files = np.sort(glob.glob(filepath+'/f_*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +h5f = h5py.File(distribution_function_files[0], 'r') +dist_func_background = h5f['distribution_function'][:] +h5f.close() + +q1_position = 10 +q2_position = 100 + +for file_number, dump_file in yt.parallel_objects(enumerate(distribution_function_files)): + + print("file number = ", file_number, "of ", distribution_function_files.size) + + h5f = h5py.File(distribution_function_files[file_number], 'r') + dist_func = h5f['distribution_function'][:] + h5f.close() + + + f_at_desired_q = np.reshape((dist_func - dist_func_background)[q2_position, q1_position, :], + [N_p1, N_p2] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.colorbar() + pl.savefig('images/dist_func_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py new file mode 100644 index 00000000..24a8ae48 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py @@ -0,0 +1,145 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + print('moments : ', moments.shape) + print('density : ', density.shape) + + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + + #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + #lagrange_multipliers = h5f['lagrange_multipliers'][:] + #h5f.close() + + #mu = lagrange_multipliers[:, :, 0] + #mu_ee = lagrange_multipliers[:, :, 1] + #T_ee = lagrange_multipliers[:, :, 2] + #vel_drift_x = lagrange_multipliers[:, :, 3] + #vel_drift_y = lagrange_multipliers[:, :, 4] + + #pl.streamplot(q1, q2, + # vel_drift_x, vel_drift_y, + # density=2, color='blue', + # linewidth=0.7, arrowsize=1 + # ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py new file mode 100644 index 00000000..5109c995 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -0,0 +1,144 @@ +import numpy as np +import arrayfire as af + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +# Restart(Set to zero for no-restart): +restart = 0 +restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/f_eqbm.h5' +phi_restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/phi_eqbm.h5' +electrostatic_solver_every_nth_step = 1000000 +solve_for_equilibrium = 0 + + +# File-writing Parameters: +dump_steps = 10 + +# Time parameters: +dt = 0.025/2 # ps +t_final = 200. # ps + +# Dimensionality considered in velocity space: +p_dim = 2 + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 6 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 4.5 # um +contact_end = 5.5 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 12e-4 +initial_mu = 0.015 +vel_drift_x_in = 1e-4*fermi_velocity +vel_drift_x_out = 1e-4*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +phi = None # Electric potential in the plane of graphene sheet + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(1.0 * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(0.2 * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + +def band_energy(p_x, p_y): + + p = af.sqrt(p_x**2. + p_y**2.) + + E_upper = p*fermi_velocity + + af.eval(E_upper) + return(E_upper) + +def band_velocity(p_x, p_y): + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + v_f = fermi_velocity + + upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] + + af.eval(upper_band_velocity[0], upper_band_velocity[1]) + return(upper_band_velocity) + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/phase_vs_y.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/post.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/signals.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/signals.py new file mode 100644 index 00000000..62104908 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/signals.py @@ -0,0 +1,171 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +# Calculate the phase difference between input_signal_array and sensor_normalized +# Code copied from : +# https:/stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves + +corr = correlate(input_normalized, sensor_normalized) +nsamples = input_normalized.size +time_corr = time_array[half_time:] +dt_corr = np.linspace(-time_corr[-1] + time_corr[0], + time_corr[-1] - time_corr[0], 2*nsamples-1) +time_shift = dt_corr[corr.argmax()] + +#Force the phase shift to be in [-pi:pi] +period = 1./AC_freq +phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) + +pl.plot(time_array, input_signal_array) +pl.plot(time_array, sensor_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=1) +pl.text(135, 1.14, '$\phi : %.2f \; rad$' %phase_diff) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-1.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 0.5$ ps') +pl.savefig('images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/vorticity.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() + From 86753c0581f89a036982e8f25a50764053dc8e83 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 30 May 2019 03:34:36 -0400 Subject: [PATCH 03/58] Added dump_aux_arrays function back --- bolt/lib/nonlinear/file_io/dump.py | 32 ++++++++++++++++++ bolt/lib/nonlinear/nonlinear_solver.py | 5 +++ .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py | 14 ++++---- .../movie.py | 33 +++++++++---------- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index a80cfc2d..ca1ca8a7 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -6,6 +6,38 @@ import h5py import arrayfire as af +def dump_aux_arrays(self, arrays, name, file_name): + + if (self.dump_aux_arrays_initial_call): + self._da_aux_arrays = PETSc.DMDA().create([self.N_q1, self.N_q2], + dof = len(arrays), + proc_sizes = (PETSc.DECIDE, + PETSc.DECIDE + ), + comm = self._comm + ) + self._glob_aux = self._da_aux_arrays.createGlobalVec() + self._glob_aux_array = self._glob_aux.getArray() + + self.dump_aux_arrays_initial_call = 0 + + N_g = self.N_ghost + + for i in range(len(arrays)): + if (i==0): + array_to_dump = arrays[0][:, :, N_g:-N_g, N_g:-N_g] + else: + array_to_dump = af.join(0, array_to_dump, + arrays[i][:, :, + N_g:-N_g, + N_g:-N_g] + ) + + af.flat(array_to_dump).to_ndarray(self._glob_aux_array) + PETSc.Object.setName(self._glob_aux, name) + viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w', comm=self._comm) + viewer(self._glob_aux) + def dump_moments(self, file_name): """ This function is used to dump moment variables to a file for later usage. diff --git a/bolt/lib/nonlinear/nonlinear_solver.py b/bolt/lib/nonlinear/nonlinear_solver.py index ed46382f..c13a688d 100644 --- a/bolt/lib/nonlinear/nonlinear_solver.py +++ b/bolt/lib/nonlinear/nonlinear_solver.py @@ -276,6 +276,10 @@ def __init__(self, physical_system, performance_test_flag = False): comm = self._comm ) + # For dumping aux arrays: + self.dump_aux_arrays_initial_call = 1 + + # Creation of the local and global vectors from the DA: # This is for the distribution function self._glob_f = self._da_f.createGlobalVec() @@ -519,6 +523,7 @@ def _initialize(self, params): dump_distribution_function = dump.dump_distribution_function dump_moments = dump.dump_moments + dump_aux_arrays = dump.dump_aux_arrays dump_EM_fields = dump.dump_EM_fields load_distribution_function = load.load_distribution_function diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py index 9ddbb6e7..ce36cd44 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py @@ -204,13 +204,13 @@ if (time_step==0): nls.dump_distribution_function('dumps/f_' + file_number) nls.dump_distribution_function('dumps/f_' + file_number) - #nls.dump_aux_arrays([params.mu, - # params.mu_ee, - # params.T_ee, - # params.vel_drift_x, params.vel_drift_y], - # 'lagrange_multipliers', - # 'dumps/lagrange_multipliers_' + file_number - # ) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y], + 'lagrange_multipliers', + 'dumps/lagrange_multipliers_' + file_number + ) # Dump EM fields #af.flat(nls.cell_centered_EM_fields[:, N_g:-N_g, N_g:-N_g]).to_ndarray(nls._glob_fields_array) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py index 24a8ae48..44c4aaee 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py @@ -110,31 +110,28 @@ j_x = moments[:, :, 1] j_y = moments[:, :, 2] - print('moments : ', moments.shape) - print('density : ', density.shape) - pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") - #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') - #lagrange_multipliers = h5f['lagrange_multipliers'][:] - #h5f.close() + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() - #mu = lagrange_multipliers[:, :, 0] - #mu_ee = lagrange_multipliers[:, :, 1] - #T_ee = lagrange_multipliers[:, :, 2] - #vel_drift_x = lagrange_multipliers[:, :, 3] - #vel_drift_y = lagrange_multipliers[:, :, 4] + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] - #pl.streamplot(q1, q2, - # vel_drift_x, vel_drift_y, - # density=2, color='blue', - # linewidth=0.7, arrowsize=1 - # ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) - pl.xlim([domain.q1_start, domain.q1_end]) - pl.ylim([domain.q2_start, domain.q2_end]) + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) pl.gca().set_aspect('equal') pl.xlabel(r'$x\;(\mu \mathrm{m})$') From 348354c7e5f89f964b5004c6e4c1756e45f3d78e Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 30 May 2019 06:47:42 -0400 Subject: [PATCH 04/58] Cleaned up collision_operator.py --- bolt/src/electronic_boltzmann/collision_operator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index a54ee561..abd9ace8 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -344,16 +344,18 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): f = f0_defect_constant_T(f, p1, p2, p3, params) return(f) - print('RTA : ', f.shape) - print ('RTA : ',f0_defect_constant_T(f, p1, p2, p3, params).shape) + + # Activate the following lines to enable normal operation of collision + # operator C_f = -( f - f0_defect_constant_T(f, p1, p2, p3, params) \ ) / params.tau_defect(q1, q2, p1, p2, p3) \ -( f - f0_ee(f, p1, p2, p3, params) ) / params.tau_ee(q1, q2, p1, p2, p3) + # When (f - f0) is NaN. Dividing by np.inf doesn't give 0 # TODO: WORKAROUND - # Activate the following line to set collision operator to zero + # Activate the following line to disable the collision operator #C_f = 0.*f af.eval(C_f) From 94f1b65caf01b9c3bceb622b5d28f50e68c89905 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 01:05:01 -0400 Subject: [PATCH 05/58] Fixed a naming bug --- bolt/lib/nonlinear/nonlinear_solver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bolt/lib/nonlinear/nonlinear_solver.py b/bolt/lib/nonlinear/nonlinear_solver.py index c13a688d..848f4c75 100644 --- a/bolt/lib/nonlinear/nonlinear_solver.py +++ b/bolt/lib/nonlinear/nonlinear_solver.py @@ -393,7 +393,7 @@ def __init__(self, physical_system, performance_test_flag = False): # If local zone includes the bottom physical boundary: if(i_q2_start == 0): self.f[:, :, :, :N_g] = self.boundary_conditions.\ - f_bot(*args)[:, :, :, :N_g] + f_bottom(*args)[:, :, :, :N_g] if(self.physical_system.boundary_conditions.in_q2_top == 'dirichlet'): # If local zone includes the top physical boundary: From 05657b22a20822afd7fb6f5ae4585ae6b3028d5e Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 03:04:10 -0400 Subject: [PATCH 06/58] main.py cleaned up --- .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py | 259 +----------------- 1 file changed, 6 insertions(+), 253 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py index ce36cd44..e40356b1 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py @@ -25,35 +25,6 @@ import bolt.src.electronic_boltzmann.moment_defs as moment_defs -#pl.rcParams['figure.figsize'] = 12, 7.5 -#pl.rcParams['figure.dpi'] = 150 -#pl.rcParams['image.cmap'] = 'jet' -#pl.rcParams['lines.linewidth'] = 1.5 -#pl.rcParams['font.family'] = 'serif' -#pl.rcParams['font.weight'] = 'bold' -#pl.rcParams['font.size'] = 20 -#pl.rcParams['font.sans-serif'] = 'serif' -#pl.rcParams['text.usetex'] = False -#pl.rcParams['axes.linewidth'] = 1.5 -#pl.rcParams['axes.titlesize'] = 'medium' -#pl.rcParams['axes.labelsize'] = 'medium' -# -#pl.rcParams['xtick.major.size'] = 8 -#pl.rcParams['xtick.minor.size'] = 4 -#pl.rcParams['xtick.major.pad'] = 8 -#pl.rcParams['xtick.minor.pad'] = 8 -#pl.rcParams['xtick.color'] = 'k' -#pl.rcParams['xtick.labelsize'] = 'medium' -#pl.rcParams['xtick.direction'] = 'in' -# -#pl.rcParams['ytick.major.size'] = 8 -#pl.rcParams['ytick.minor.size'] = 4 -#pl.rcParams['ytick.major.pad'] = 8 -#pl.rcParams['ytick.minor.pad'] = 8 -#pl.rcParams['ytick.color'] = 'k' -#pl.rcParams['ytick.labelsize'] = 'medium' -#pl.rcParams['ytick.direction'] = 'in' - # Defining the physical system to be solved: system = physical_system(domain, @@ -82,98 +53,15 @@ if (params.restart): nls.load_distribution_function(params.restart_file) - viewer = PETSc.Viewer().createHDF5(params.phi_restart_file, - PETSc.Viewer.Mode.READ, - comm=nls._comm - ) - PETSc.Object.setName(nls.poisson.glob_phi, 'phi') - nls.poisson.glob_phi.load(viewer) - - params.solve_for_equilibrium = 0 - #compute_electrostatic_fields(nls) - - params.mu = params.global_chem_potential + params.charge[0]*params.phi - params.mu_analytic = params.global_chem_potential + params.charge[0]*params.phi - params.mu = af.moddims(params.mu, - 1, - nls.N_q1_local + 2*N_g, - nls.N_q2_local + 2*N_g - ) -else: - if (params.solve_for_equilibrium): - PETSc.Sys.Print("=============================") - PETSc.Sys.Print("Solving for equilibrium state") - PETSc.Sys.Print("=============================") - params.solve_for_equilibrium = 1 - #compute_electrostatic_fields(nls) - params.solve_for_equilibrium = 0 - - params.mu = params.global_chem_potential + params.charge[0]*params.phi - params.mu = af.moddims(params.mu, - 1, - nls.N_q1_local + 2*N_g, - nls.N_q2_local + 2*N_g - ) - - nls.f = params.fermi_dirac(params.mu, params.E_band) - - PETSc.Sys.Print("=====================") - PETSc.Sys.Print("Solution diagnostics:") - PETSc.Sys.Print("=====================") - - density = nls.compute_moments('density') - print("rank = ", params.rank, "\n", - " = ", af.mean(params.mu[0, N_g:-N_g, N_g:-N_g]), "\n", - " max(mu) = ", af.max(params.mu[0, N_g:-N_g, N_g:-N_g]), "\n", - #" = ", af.mean(params.phi[N_g:-N_g, N_g:-N_g]), "\n", - " = ", af.mean(density[0, N_g:-N_g, N_g:-N_g]), "\n", - " max(n) = ", af.max(density[0, N_g:-N_g, N_g:-N_g]), "\n" - #" |E1| = ", af.mean(af.abs(nls.cell_centered_EM_fields[0, N_g:-N_g, N_g:-N_g])), - #"\n", - #" |E2| = ", af.mean(af.abs(nls.cell_centered_EM_fields[1, N_g:-N_g, N_g:-N_g])) - ) - - PETSc.Sys.Print("===============") - PETSc.Sys.Print("Dumping data...") - PETSc.Sys.Print("===============") - - nls.dump_moments('dumps/moments_eqbm') - nls.dump_distribution_function('dumps/f_eqbm') - - # Dump EM fields - #af.flat(nls.cell_centered_EM_fields[:, N_g:-N_g, N_g:-N_g]).to_ndarray(nls._glob_fields_array) - #PETSc.Object.setName(nls._glob_fields, 'fields') - #viewer = PETSc.Viewer().createHDF5('dumps/fields_eqbm.h5', - # 'w', comm=nls._comm - # ) - #viewer(nls._glob_fields) - - # Dump eqbm potential - PETSc.Object.setName(nls.poisson.glob_phi, 'phi') - viewer = PETSc.Viewer().createHDF5('dumps/phi_eqbm.h5', - 'w', comm=nls._comm - ) - viewer(nls.poisson.glob_phi) - - sys.exit("Terminating execution") - else: - - #compute_electrostatic_fields(nls) - pass - density = nls.compute_moments('density') print("rank = ", params.rank, "\n", " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", - #" = ", af.mean(params.phi[N_g:-N_g, N_g:-N_g]), "\n", " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" - #" |E1| = ", af.mean(af.abs(nls.cell_centered_EM_fields[0, N_g:-N_g, N_g:-N_g])), - #"\n", - #" |E2| = ", af.mean(af.abs(nls.cell_centered_EM_fields[1, N_g:-N_g, N_g:-N_g])) ) -nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) +nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) while t0 < t_final: # Refine to machine error @@ -189,8 +77,8 @@ #else: # dump_steps = params.dump_steps if (time_step%dump_steps==0): - file_number = '%06d'%dump_counter - dump_counter= dump_counter + 1 + file_number = '%06d'%dump_counter + dump_counter = dump_counter + 1 dump_time_array.append(params.current_time) PETSc.Sys.Print("=====================================================") PETSc.Sys.Print("Dumping data at time step =", time_step, @@ -201,9 +89,11 @@ np.savetxt("dump_time_array.txt", dump_time_array) nls.dump_moments('dumps/moments_' + file_number) + if (time_step==0): nls.dump_distribution_function('dumps/f_' + file_number) - nls.dump_distribution_function('dumps/f_' + file_number) + + #nls.dump_distribution_function('dumps/f_' + file_number) nls.dump_aux_arrays([params.mu, params.mu_ee, params.T_ee, @@ -212,16 +102,6 @@ 'dumps/lagrange_multipliers_' + file_number ) - # Dump EM fields - #af.flat(nls.cell_centered_EM_fields[:, N_g:-N_g, N_g:-N_g]).to_ndarray(nls._glob_fields_array) - #PETSc.Object.setName(nls._glob_fields, 'fields') - #viewer = PETSc.Viewer().createHDF5('dumps/fields_' - # + '%06d'%(time_step/dump_steps) + '.h5', - # 'w', comm=nls._comm - # ) - #viewer(nls._glob_fields) - - dt_force_constraint = 0. # dt_force_constraint = \ # 0.5 * np.min(nls.dp1, nls.dp2) \ @@ -230,98 +110,8 @@ # ) # ) - PETSc.Sys.Print("Time step =", time_step, ", Time =", t0) - mean_density = af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]) - density_pert = density - mean_density - -# if (time_step%1==0): -# chemical_potential = np.array(params.mu)[0, :, :] \ -# - params.charge*np.array(params.phi)[:, :] -# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(params.mu)[0, N_g:-N_g, N_g:-N_g], \ -# 100, cmap='bwr' -# ) -# pl.title('Time = ' + "%.2f"%(t0) ) -# pl.xlabel('$x$') -# pl.ylabel('$y$') -# pl.colorbar() -# pl.gca().set_aspect('equal') -# pl.savefig('/tmp/mu_' + '%06d'%time_step + '.png' ) -# pl.clf() -# -# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(density)[0, N_g:-N_g, N_g:-N_g], \ -# 100, cmap='bwr' -# ) -# pl.title('Time = ' + "%.2f"%(t0) ) -# pl.xlabel('$x$') -# pl.ylabel('$y$') -# pl.colorbar() -# pl.gca().set_aspect('equal') -# pl.savefig('/tmp/density_' + '%06d'%time_step + '.png' ) -# pl.clf() -# -# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(params.phi)[N_g:-N_g, N_g:-N_g], \ -# 100, cmap='bwr' -# ) -# pl.title('Time = ' + "%.2f"%(t0) ) -# pl.xlabel('$x$') -# pl.ylabel('$y$') -# pl.colorbar() -# pl.gca().set_aspect('equal') -# pl.savefig('/tmp/phi_' + '%06d'%time_step + '.png' ) -# pl.clf() -# -# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.cell_centered_EM_fields)[0, N_g:-N_g, N_g:-N_g], \ -# 100, cmap='bwr' -# ) -# pl.title('Time = ' + "%.2f"%(t0) ) -# pl.xlabel('$x$') -# pl.ylabel('$y$') -# pl.colorbar() -# pl.gca().set_aspect('equal') -# pl.savefig('/tmp/E1_' + '%06d'%time_step + '.png' ) -# pl.clf() -# -# pl.contourf(np.array(nls.q1_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.q2_center)[0, N_g:-N_g, N_g:-N_g], \ -# np.array(nls.cell_centered_EM_fields)[1, N_g:-N_g, N_g:-N_g], \ -# 100, cmap='bwr' -# ) -# pl.title('Time = ' + "%.2f"%(t0) ) -# pl.xlabel('$x$') -# pl.ylabel('$y$') -# pl.colorbar() -# pl.gca().set_aspect('equal') -# pl.savefig('/tmp/E2_' + '%06d'%time_step + '.png' ) -# pl.clf() -# -# f_at_desired_q = af.moddims(nls.f[:, N_g, N_g + 0.*nls.N_q2/2], -# nls.N_p1, nls.N_p2 -# ) -# p1 = af.moddims(nls.p1, nls.N_p1, nls.N_p2) -# p2 = af.moddims(nls.p2, nls.N_p1, nls.N_p2) -# pl.contourf(np.array(p1), \ -# np.array(p2), \ -# np.array((f_at_desired_q)), \ -# 100, cmap='bwr' -# ) -# pl.title('Time = ' + "%.2f"%(t0) ) -# pl.xlabel('$x$') -# pl.ylabel('$y$') -# pl.colorbar() -# pl.gca().set_aspect('equal') -# pl.savefig('/tmp/f_' + '%06d'%time_step + '.png' ) -# pl.clf() - nls.strang_timestep(dt) t0 = t0 + dt time_step = time_step + 1 @@ -335,46 +125,9 @@ print("rank = ", params.rank, "\n", " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", - #" = ", af.mean(params.phi[N_g:-N_g, N_g:-N_g]), "\n", " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" - #" |E1| = ", af.mean(af.abs(nls.cell_centered_EM_fields[0, N_g:-N_g, N_g:-N_g])), - #"\n", - #" |E2| = ", af.mean(af.abs(nls.cell_centered_EM_fields[1, N_g:-N_g, N_g:-N_g])) ) PETSc.Sys.Print("--------------------\n") nls.dump_distribution_function('dumps/f_laststep') - -#phi_array = nls.poisson.glob_phi.getArray() -#phi_array = phi_array.reshape([nls.poisson.N_q3_3D_local, \ -# nls.poisson.N_q2_3D_local, \ -# nls.poisson.N_q1_3D_local] -# ) -# -#q3_index = np.where(nls.poisson.q3_3D[N_g:-N_g] >= nls.location_in_q3)[0][0] -#pl.plot(nls.poisson.q1_3D[N_g:-N_g], -# phi_array[q3_index, nls.poisson.N_q2_3D_local/2, :], 'o-' -# ) -#pl.show() - -#pl.rcParams['figure.figsize'] = 20, 7.5 -#pl.subplot(121) -#N_g = domain.N_ghost -#pl.contourf( -# phi_array[nls.N_q3_poisson/2, :, :], 100, cmap='jet' -# ) -#pl.colorbar() -#pl.title('Top View') -#pl.xlabel('$x$') -#pl.ylabel('$y$') -#pl.gca().set_aspect('equal') -# -#pl.subplot(122) -#pl.contourf(phi_array[:, nls.N_q2_poisson/2, :], 100, cmap='jet') -#pl.title('Side View') -#pl.xlabel('$x$') -#pl.ylabel('$z$') -#pl.colorbar() -#pl.gca().set_aspect('equal') -#pl.show() From 8b179387b86e88f9e3e36f4e939c960bcbbe6380 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 06:21:10 -0400 Subject: [PATCH 07/58] Comments added to domain.py --- .../graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py index 7bd57eda..c5e4bef7 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py @@ -6,14 +6,23 @@ q2_end = 10. N_q2 = 20 +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero + p1_start = [-0.04] p1_end = [0.04] N_p1 = 16 +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero + p2_start = [-0.04] p2_end = [0.04] N_p2 = 16 +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + p3_start = [-0.5] p3_end = [0.5] N_p3 = 1 From 6fb3d51e93d4e5fb2ce03ed91908c319755d0555 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 06:30:21 -0400 Subject: [PATCH 08/58] cartesian/polar p_space_grid switch added. TODO : Implement polar bcs --- bolt/lib/nonlinear/boundaries.py | 46 ++++++++++++++----- .../params.py | 1 + 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/bolt/lib/nonlinear/boundaries.py b/bolt/lib/nonlinear/boundaries.py index 3d2d5a47..e197f687 100644 --- a/bolt/lib/nonlinear/boundaries.py +++ b/bolt/lib/nonlinear/boundaries.py @@ -224,10 +224,10 @@ def apply_dirichlet_bcs_f(self, boundary): return -def apply_mirror_bcs_f(self, boundary): +def apply_mirror_bcs_f_cartesian(self, boundary): """ Applies mirror boundary conditions along boundary specified - for the distribution function + for the distribution function when momentum space is on a cartesian grid Parameters ---------- @@ -332,10 +332,16 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'left') elif(self.boundary_conditions.in_q1_left == 'mirror'): - apply_mirror_bcs_f(self, 'left') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'left') + else : + raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q1_left == 'mirror+dirichlet'): - apply_mirror_bcs_f(self, 'left') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'left') + else : + raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'left') # This is automatically handled by the PETSc function globalToLocal() @@ -355,12 +361,18 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'right') elif(self.boundary_conditions.in_q1_right == 'mirror'): - apply_mirror_bcs_f(self, 'right') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'right') + else: + raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q1_right == 'mirror+dirichlet'): - apply_mirror_bcs_f(self, 'right') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'right') + else: + raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'right') - + # This is automatically handled by the PETSc function globalToLocal() elif(self.boundary_conditions.in_q1_right == 'periodic'): pass @@ -378,10 +390,16 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'bottom') elif(self.boundary_conditions.in_q2_bottom == 'mirror'): - apply_mirror_bcs_f(self, 'bottom') + if (self.physical_system.params.p_space_grid =='cartesian'): + apply_mirror_bcs_f_cartesian(self, 'bottom') + else: + raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q2_bottom == 'mirror+dirichlet'): - apply_mirror_bcs_f(self, 'bottom') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'bottom') + else: + raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'bottom') # This is automatically handled by the PETSc function globalToLocal() @@ -401,10 +419,16 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'top') elif(self.boundary_conditions.in_q2_top == 'mirror'): - apply_mirror_bcs_f(self, 'top') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'top') + else: + raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q2_top == 'mirror+dirichlet'): - apply_mirror_bcs_f(self, 'top') + if (self.physical_system.params.p_space_grid == 'cartesian'): + apply_mirror_bcs_f_cartesian(self, 'top') + else: + raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'top') # This is automatically handled by the PETSc function globalToLocal() diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 5109c995..2bb10261 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -48,6 +48,7 @@ # Dimensionality considered in velocity space: p_dim = 2 +p_space_grid = 'cartesian' # Supports 'cartesian' or 'polar' grids # Number of devices(GPUs/Accelerators) on each node: num_devices = 6 From 77f3c4ecd2b6dfe3d43d2bd0117a4573d7ab8479 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 08:06:55 -0400 Subject: [PATCH 09/58] Added f0_ee_constant_T() to collision_operator.py with auxiliary functions --- .../collision_operator.py | 283 ++++++++++++++---- .../electronic_boltzmann/matrix_inverse.py | 175 ++++++++--- 2 files changed, 359 insertions(+), 99 deletions(-) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index abd9ace8..6b65a0b8 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -4,10 +4,11 @@ import numpy as np import arrayfire as af from .matrix_inverse import inverse_4x4_matrix +from .matrix_inverse import inverse_3x3_matrix import domain @af.broadcast -def f0_defect_constant_T(f, p1, p2, p3, params): +def f0_defect_constant_T(f, p_x, p_y, p_z, params): mu = params.mu T = params.T @@ -20,7 +21,7 @@ def f0_defect_constant_T(f, p1, p2, p3, params): tmp = ((E_upper - mu)/(k*T)) denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) - # TODO: Multiply with the integral measure dp1 * dp2 + # TODO: Multiply with the integral measure dp_x * dp_y a00 = af.sum(T / denominator, 0) fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) @@ -54,7 +55,7 @@ def f0_defect_constant_T(f, p1, p2, p3, params): af.eval(fermi_dirac) zeroth_moment = f - fermi_dirac - + eqn_mass_conservation = af.sum(zeroth_moment, 0) N_g = domain.N_ghost @@ -72,26 +73,26 @@ def f0_defect_constant_T(f, p1, p2, p3, params): return(fermi_dirac) -# Using af.broadcast, since p1, p2, p3 are of size (1, 1, Np1*Np2*Np3) +# Using af.broadcast, since p_x, p_y, p_z are of size (1, 1, Np_x*Np_y*Np_z) # All moment quantities are of shape (Nq1, Nq2) # By wrapping with af.broadcast, we can perform batched operations # on arrays of different sizes. @af.broadcast -def f0_defect(f, p1, p2, p3, params): +def f0_defect(f, p_x, p_y, p_z, params): # Initial guess mu = params.mu T = params.T for n in range(params.collision_nonlinear_iters): - + E_upper = params.E_band k = params.boltzmann_constant tmp = ((E_upper - mu)/(k*T)) denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) - # TODO: Multiply with the integral measure dp1 * dp2 + # TODO: Multiply with the integral measure dp_x * dp_y a00 = af.sum(T / denominator, 0) a01 = af.sum((E_upper - mu) / denominator, 0) a10 = af.sum(E_upper*T / denominator, 0) @@ -99,7 +100,7 @@ def f0_defect(f, p1, p2, p3, params): # Solve Ax = b # where A == Jacobian, - # x == delta guess (correction to guess), + # x == delta guess (correction to guess), # b = -residual fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) @@ -107,7 +108,7 @@ def f0_defect(f, p1, p2, p3, params): zeroth_moment = f - fermi_dirac second_moment = E_upper*(f - fermi_dirac) - + eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_energy_conservation = af.sum(second_moment, 0) @@ -116,7 +117,7 @@ def f0_defect(f, p1, p2, p3, params): error_energy_conservation = af.max(af.abs(eqn_energy_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) residual = [eqn_mass_conservation, eqn_energy_conservation] - error_norm = np.max([af.max(af.abs(residual[0])), + error_norm = np.max([af.max(af.abs(residual[0])), af.max(af.abs(residual[1]))] ) print(" ||residual_defect|| = ", error_norm) @@ -148,12 +149,12 @@ def f0_defect(f, p1, p2, p3, params): zeroth_moment = f - fermi_dirac second_moment = E_upper*(f - fermi_dirac) - + eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_energy_conservation = af.sum(second_moment, 0) residual = [eqn_mass_conservation, eqn_energy_conservation] - error_norm = np.max([af.max(af.abs(residual[0])), + error_norm = np.max([af.max(af.abs(residual[0])), af.max(af.abs(residual[1]))] ) print(" ||residual_defect|| = ", error_norm) @@ -165,7 +166,7 @@ def f0_defect(f, p1, p2, p3, params): return(fermi_dirac) @af.broadcast -def f0_ee(f, p1, p2, p3, params): +def f0_ee(f, p_x, p_y, p_z, params): # Initial guess mu_ee = params.mu_ee @@ -178,18 +179,18 @@ def f0_ee(f, p1, p2, p3, params): E_upper = params.E_band k = params.boltzmann_constant - tmp1 = (E_upper - mu_ee - p1*vel_drift_x - p2*vel_drift_y) + tmp1 = (E_upper - mu_ee - p_x*vel_drift_x - p_y*vel_drift_y) tmp = (tmp1/(k*T_ee)) denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) a_0 = T_ee / denominator a_1 = tmp1 / denominator - a_2 = T_ee * p1 / denominator - a_3 = T_ee * p2 / denominator + a_2 = T_ee * p_x / denominator + a_3 = T_ee * p_y / denominator af.eval(a_0, a_1, a_2, a_3) - # TODO: Multiply with the integral measure dp1 * dp2 + # TODO: Multiply with the integral measure dp_x * dp_y a_00 = af.sum(a_0, 0) a_01 = af.sum(a_1, 0) a_02 = af.sum(a_2, 0) @@ -200,33 +201,33 @@ def f0_ee(f, p1, p2, p3, params): a_12 = af.sum(E_upper * a_2, 0) a_13 = af.sum(E_upper * a_3, 0) - a_20 = af.sum(p1 * a_0, 0) - a_21 = af.sum(p1 * a_1, 0) - a_22 = af.sum(p1 * a_2, 0) - a_23 = af.sum(p1 * a_3, 0) + a_20 = af.sum(p_x * a_0, 0) + a_21 = af.sum(p_x * a_1, 0) + a_22 = af.sum(p_x * a_2, 0) + a_23 = af.sum(p_x * a_3, 0) - a_30 = af.sum(p2 * a_0, 0) - a_31 = af.sum(p2 * a_1, 0) - a_32 = af.sum(p2 * a_2, 0) - a_33 = af.sum(p2 * a_3, 0) + a_30 = af.sum(p_y * a_0, 0) + a_31 = af.sum(p_y * a_1, 0) + a_32 = af.sum(p_y * a_2, 0) + a_33 = af.sum(p_y * a_3, 0) A = [ [a_00, a_01, a_02, a_03], \ [a_10, a_11, a_12, a_13], \ [a_20, a_21, a_22, a_23], \ [a_30, a_31, a_32, a_33] \ ] - + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee - - vel_drift_x*p1 - vel_drift_y*p2 - )/(k*T_ee) + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) ) + 1. ) af.eval(fermi_dirac) zeroth_moment = (f - fermi_dirac) second_moment = E_upper*(f - fermi_dirac) - first_moment_x = p1*(f - fermi_dirac) - first_moment_y = p2*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_energy_conservation = af.sum(second_moment, 0) @@ -249,21 +250,21 @@ def f0_ee(f, p1, p2, p3, params): ) # if (error_norm < 1e-13): -# params.mu_ee = mu_ee -# params.T_ee = T_ee +# params.mu_ee = mu_ee +# params.T_ee = T_ee # params.vel_drift_x = vel_drift_x # params.vel_drift_y = vel_drift_y # return(fermi_dirac) - b_0 = eqn_mass_conservation + b_0 = eqn_mass_conservation b_1 = eqn_energy_conservation - b_2 = eqn_mom_x_conservation - b_3 = eqn_mom_y_conservation + b_2 = eqn_mom_x_conservation + b_3 = eqn_mom_y_conservation b = [b_0, b_1, b_2, b_3] # Solve Ax = b # where A == Jacobian, - # x == delta guess (correction to guess), + # x == delta guess (correction to guess), # b = -residual A_inv = inverse_4x4_matrix(A) @@ -277,7 +278,7 @@ def f0_ee(f, p1, p2, p3, params): delta_T = x_1 delta_vx = x_2 delta_vy = x_3 - + mu_ee = mu_ee + delta_mu T_ee = T_ee + delta_T vel_drift_x = vel_drift_x + delta_vx @@ -286,23 +287,23 @@ def f0_ee(f, p1, p2, p3, params): af.eval(mu_ee, T_ee, vel_drift_x, vel_drift_y) # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params - params.mu_ee = mu_ee - params.T_ee = T_ee + params.mu_ee = mu_ee + params.T_ee = T_ee params.vel_drift_x = vel_drift_x params.vel_drift_y = vel_drift_y fermi_dirac = 1./(af.exp( ( E_upper - mu_ee - - vel_drift_x*p1 - vel_drift_y*p2 - )/(k*T_ee) + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) ) + 1. ) af.eval(fermi_dirac) zeroth_moment = f - fermi_dirac second_moment = E_upper*(f - fermi_dirac) - first_moment_x = p1*(f - fermi_dirac) - first_moment_y = p2*(f - fermi_dirac) - + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_energy_conservation = af.sum(second_moment, 0) eqn_mom_x_conservation = af.sum(first_moment_x, 0) @@ -334,24 +335,198 @@ def f0_ee(f, p1, p2, p3, params): return(fermi_dirac) -def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): +@af.broadcast +def f0_ee_constant_T(f, p_x, p_y, p_z, params): + + # Initial guess + mu_ee = params.mu_ee + T_ee = params.T_ee + vel_drift_x = params.vel_drift_x + vel_drift_y = params.vel_drift_y + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp1 = (E_upper - mu_ee - p_x*vel_drift_x - p_y*vel_drift_y) + tmp = (tmp1/(k*T_ee)) + denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + a_0 = T_ee / denominator + a_1 = tmp1 / denominator + a_2 = T_ee * p_x / denominator + a_3 = T_ee * p_y / denominator + + af.eval(a_0, a_1, a_2, a_3) + + + # TODO: Multiply with the integral measure dp_x * dp_y + a_00 = af.sum(a_0, 0) + #a_01 = af.sum(a_1, 0) + a_02 = af.sum(a_2, 0) + a_03 = af.sum(a_3, 0) + + #a_10 = af.sum(E_upper * a_0, 0) + #a_11 = af.sum(E_upper * a_1, 0) + #a_12 = af.sum(E_upper * a_2, 0) + #a_13 = af.sum(E_upper * a_3, 0) + + a_20 = af.sum(p_x * a_0, 0) + #a_21 = af.sum(p_x * a_1, 0) + a_22 = af.sum(p_x * a_2, 0) + a_23 = af.sum(p_x * a_3, 0) + + a_30 = af.sum(p_y * a_0, 0) + #a_31 = af.sum(p_y * a_1, 0) + a_32 = af.sum(p_y * a_2, 0) + a_33 = af.sum(p_y * a_3, 0) + + A = [ [a_00, a_02, a_03], \ + [a_20, a_22, a_23], \ + [a_30, a_32, a_33] \ + ] + + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = (f - fermi_dirac) + #second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + #eqn_energy_conservation = af.sum(second_moment, 0) + eqn_mom_x_conservation = af.sum(first_moment_x, 0) + eqn_mom_y_conservation = af.sum(first_moment_y, 0) + + residual = [eqn_mass_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + +# if (error_norm < 1e-13): +# params.mu_ee = mu_ee +# params.T_ee = T_ee +# params.vel_drift_x = vel_drift_x +# params.vel_drift_y = vel_drift_y +# return(fermi_dirac) + + b_0 = eqn_mass_conservation + #b_1 = eqn_energy_conservation + b_2 = eqn_mom_x_conservation + b_3 = eqn_mom_y_conservation + b = [b_0, b_2, b_3] + + # Solve Ax = b + # where A == Jacobian, + # x == delta guess (correction to guess), + # b = -residual + + A_inv = inverse_3x3_matrix(A) + + x_0 = A_inv[0][0]*b[0] + A_inv[0][1]*b[1] + A_inv[0][2]*b[2] + #x_1 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + A_inv[1][3]*b[3] + x_2 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + x_3 = A_inv[2][0]*b[0] + A_inv[2][1]*b[1] + A_inv[2][2]*b[2] + + delta_mu = x_0 + #delta_T = x_1 + delta_vx = x_2 + delta_vy = x_3 + + mu_ee = mu_ee + delta_mu + #T_ee = T_ee + delta_T + vel_drift_x = vel_drift_x + delta_vx + vel_drift_y = vel_drift_y + delta_vy + + af.eval(mu_ee, vel_drift_x, vel_drift_y) + + # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params + params.mu_ee = mu_ee + #params.T_ee = T_ee + params.vel_drift_x = vel_drift_x + params.vel_drift_y = vel_drift_y + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + #second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + + eqn_mass_conservation = af.sum(zeroth_moment, 0) + #eqn_energy_conservation = af.sum(second_moment, 0) + eqn_mom_x_conservation = af.sum(first_moment_x, 0) + eqn_mom_y_conservation = af.sum(first_moment_y, 0) + + residual = [eqn_mass_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation + ] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + N_g = domain.N_ghost + print(" rank = ", params.rank, + "mu_ee = ", af.mean(params.mu_ee[0, N_g:-N_g, N_g:-N_g]), + "T_ee = ", af.mean(params.T_ee[0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_x[0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_y[0, N_g:-N_g, N_g:-N_g]) + ) + PETSc.Sys.Print(" ------------------") + + return(fermi_dirac) + +def RTA(f, q1, q2, p1, p2, p3, moments, params, flag = False): """Return BGK operator -(f-f0)/tau.""" - if(af.any_true(params.tau_defect(q1, q2, p1, p2, p3) == 0)): + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + p_z = p3 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + if(af.any_true(params.tau_defect(q1, q2, p_x, p_y, p_z) == 0)): if (flag == False): return(0.*f) - f = f0_defect_constant_T(f, p1, p2, p3, params) - + f = f0_defect_constant_T(f, p_x, p_y, p_z, params) + return(f) - + # Activate the following lines to enable normal operation of collision # operator - C_f = -( f - f0_defect_constant_T(f, p1, p2, p3, params) \ - ) / params.tau_defect(q1, q2, p1, p2, p3) \ - -( f - f0_ee(f, p1, p2, p3, params) - ) / params.tau_ee(q1, q2, p1, p2, p3) - + C_f = -( f - f0_defect_constant_T(f, p_x, p_y, p_z, params) \ + ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ + -( f - f0_ee(f, p_x, p_y, p_z, params) + ) / params.tau_ee(q1, q2, p_x, p_y, p_z) + # When (f - f0) is NaN. Dividing by np.inf doesn't give 0 # TODO: WORKAROUND diff --git a/bolt/src/electronic_boltzmann/matrix_inverse.py b/bolt/src/electronic_boltzmann/matrix_inverse.py index 4b987180..2c8fce0b 100644 --- a/bolt/src/electronic_boltzmann/matrix_inverse.py +++ b/bolt/src/electronic_boltzmann/matrix_inverse.py @@ -37,28 +37,32 @@ def inverse_4x4_matrix(A): af.eval(det) - A_inv = [[0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0], + #TODO : Raise an exception if the matrix is singular + #print ('determinant : ') + #print (det) + + A_inv = [[0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], [0, 0, 0, 0] ] A_inv[0][0] = \ - ( A[1][1]*A[2][2]*A[3][3] - + A[1][2]*A[2][3]*A[3][1] - + A[1][3]*A[2][1]*A[3][2] - - A[1][1]*A[2][3]*A[3][2] - - A[1][2]*A[2][1]*A[3][3] + ( A[1][1]*A[2][2]*A[3][3] + + A[1][2]*A[2][3]*A[3][1] + + A[1][3]*A[2][1]*A[3][2] + - A[1][1]*A[2][3]*A[3][2] + - A[1][2]*A[2][1]*A[3][3] - A[1][3]*A[2][2]*A[3][1])/det - + A_inv[0][1] = \ - ( A[0][1]*A[2][3]*A[3][2] - + A[0][2]*A[2][1]*A[3][3] - + A[0][3]*A[2][2]*A[3][1] - - A[0][1]*A[2][2]*A[3][3] - - A[0][2]*A[2][3]*A[3][1] + ( A[0][1]*A[2][3]*A[3][2] + + A[0][2]*A[2][1]*A[3][3] + + A[0][3]*A[2][2]*A[3][1] + - A[0][1]*A[2][2]*A[3][3] + - A[0][2]*A[2][3]*A[3][1] - A[0][3]*A[2][1]*A[3][2])/det - + A_inv[0][2] = \ ( A[0][1]*A[1][2]*A[3][3] + A[0][2]*A[1][3]*A[3][1] @@ -66,7 +70,7 @@ def inverse_4x4_matrix(A): - A[0][1]*A[1][3]*A[3][2] - A[0][2]*A[1][1]*A[3][3] - A[0][3]*A[1][2]*A[3][1])/det - + A_inv[0][3] = \ ( A[0][1]*A[1][3]*A[2][2] + A[0][2]*A[1][1]*A[2][3] @@ -74,7 +78,7 @@ def inverse_4x4_matrix(A): - A[0][1]*A[1][2]*A[2][3] - A[0][2]*A[1][3]*A[2][1] - A[0][3]*A[1][1]*A[2][2])/det - + # b21 A_inv[1][0] = \ ( A[1][0]*A[2][3]*A[3][2] @@ -83,7 +87,7 @@ def inverse_4x4_matrix(A): - A[1][0]*A[2][2]*A[3][3] - A[1][2]*A[2][3]*A[3][0] - A[1][3]*A[2][0]*A[3][2])/det - + A_inv[1][1] = \ ( A[0][0]*A[2][2]*A[3][3] + A[0][2]*A[2][3]*A[3][0] @@ -91,7 +95,7 @@ def inverse_4x4_matrix(A): - A[0][0]*A[2][3]*A[3][2] - A[0][2]*A[2][0]*A[3][3] - A[0][3]*A[2][2]*A[3][0])/det - + A_inv[1][2] = \ ( A[0][0]*A[1][3]*A[3][2] + A[0][2]*A[1][0]*A[3][3] @@ -99,7 +103,7 @@ def inverse_4x4_matrix(A): - A[0][0]*A[1][2]*A[3][3] - A[0][2]*A[1][3]*A[3][0] - A[0][3]*A[1][0]*A[3][2])/det - + A_inv[1][3] = \ ( A[0][0]*A[1][2]*A[2][3] + A[0][2]*A[1][3]*A[2][0] @@ -107,7 +111,7 @@ def inverse_4x4_matrix(A): - A[0][0]*A[1][3]*A[2][2] - A[0][2]*A[1][0]*A[2][3] - A[0][3]*A[1][2]*A[2][0])/det - + # b31 A_inv[2][0] = \ ( A[1][0]*A[2][1]*A[3][3] @@ -125,7 +129,7 @@ def inverse_4x4_matrix(A): - A[0][0]*A[2][1]*A[3][3] - A[0][1]*A[2][3]*A[3][0] - A[0][3]*A[2][0]*A[3][1])/det - + A_inv[2][2] = \ ( A[0][0]*A[1][1]*A[3][3] + A[0][1]*A[1][3]*A[3][0] @@ -133,7 +137,7 @@ def inverse_4x4_matrix(A): - A[0][0]*A[1][3]*A[3][1] - A[0][1]*A[1][0]*A[3][3] - A[0][3]*A[1][1]*A[3][0])/det - + A_inv[2][3] = \ ( A[0][0]*A[1][3]*A[2][1] + A[0][1]*A[1][0]*A[2][3] @@ -141,40 +145,40 @@ def inverse_4x4_matrix(A): - A[0][0]*A[1][1]*A[2][3] - A[0][1]*A[1][3]*A[2][0] - A[0][3]*A[1][0]*A[2][1])/det - + # b41 A_inv[3][0] = \ - ( A[1][0]*A[2][2]*A[3][1] - + A[1][1]*A[2][0]*A[3][2] - + A[1][2]*A[2][1]*A[3][0] - - A[1][0]*A[2][1]*A[3][2] - - A[1][1]*A[2][2]*A[3][0] + ( A[1][0]*A[2][2]*A[3][1] + + A[1][1]*A[2][0]*A[3][2] + + A[1][2]*A[2][1]*A[3][0] + - A[1][0]*A[2][1]*A[3][2] + - A[1][1]*A[2][2]*A[3][0] - A[1][2]*A[2][0]*A[3][1])/det # b42 A_inv[3][1] = \ - ( A[0][0]*A[2][1]*A[3][2] - + A[0][1]*A[2][2]*A[3][0] - + A[0][2]*A[2][0]*A[3][1] - - A[0][0]*A[2][2]*A[3][1] - - A[0][1]*A[2][0]*A[3][2] + ( A[0][0]*A[2][1]*A[3][2] + + A[0][1]*A[2][2]*A[3][0] + + A[0][2]*A[2][0]*A[3][1] + - A[0][0]*A[2][2]*A[3][1] + - A[0][1]*A[2][0]*A[3][2] - A[0][2]*A[2][1]*A[3][0])/det # b43 A_inv[3][2] = \ - ( A[0][0]*A[1][2]*A[3][1] - + A[0][1]*A[1][0]*A[3][2] - + A[0][2]*A[1][1]*A[3][0] - - A[0][0]*A[1][1]*A[3][2] - - A[0][1]*A[1][2]*A[3][0] + ( A[0][0]*A[1][2]*A[3][1] + + A[0][1]*A[1][0]*A[3][2] + + A[0][2]*A[1][1]*A[3][0] + - A[0][0]*A[1][1]*A[3][2] + - A[0][1]*A[1][2]*A[3][0] - A[0][2]*A[1][0]*A[3][1])/det - + A_inv[3][3] = \ - ( A[0][0]*A[1][1]*A[2][2] - + A[0][1]*A[1][2]*A[2][0] - + A[0][2]*A[1][0]*A[2][1] - - A[0][0]*A[1][2]*A[2][1] - - A[0][1]*A[1][0]*A[2][2] + ( A[0][0]*A[1][1]*A[2][2] + + A[0][1]*A[1][2]*A[2][0] + + A[0][2]*A[1][0]*A[2][1] + - A[0][0]*A[1][2]*A[2][1] + - A[0][1]*A[1][0]*A[2][2] - A[0][2]*A[1][1]*A[2][0])/det arrays_to_be_evaled = \ @@ -187,3 +191,84 @@ def inverse_4x4_matrix(A): af.eval(*arrays_to_be_evaled) return(A_inv) + + +def inverse_3x3_matrix(A): +# TO TEST: +# A_test = np.random.rand(3, 3) +# A_inv_test = np.linalg.inv(A_test) +# A_inv = np.array(inverse_3x3_matrix(A_test)) +# print("err = ", np.max(np.abs(A_inv - A_inv_test))) + + + det = \ + A[0][0]*A[1][1]*A[2][2] \ + - A[0][0]*A[1][2]*A[2][1] \ + - A[0][1]*A[1][0]*A[2][2] \ + + A[0][1]*A[1][2]*A[2][0] \ + + A[0][2]*A[1][0]*A[2][1] \ + - A[0][2]*A[1][1]*A[2][0] \ + + af.eval(det) + + #TODO : Raise an exception if the matrix is singular + #print ('determinant : ') + #print (det) + + A_inv = [[0, 0, 0], \ + [0, 0, 0], \ + [0, 0, 0] \ + ] + + cofactors = [[0, 0, 0], \ + [0, 0, 0], \ + [0, 0, 0] \ + ] + + adjoint = [[0, 0, 0], \ + [0, 0, 0], \ + [0, 0, 0] \ + ] + + cofactors[0][0] = +(A[1][1]*A[2][2] - A[1][2]*A[2][1]) + cofactors[0][1] = -(A[1][0]*A[2][2] - A[1][2]*A[2][0]) + cofactors[0][2] = +(A[1][0]*A[2][1] - A[1][1]*A[2][0]) + cofactors[1][0] = -(A[0][1]*A[2][2] - A[0][2]*A[2][1]) + cofactors[1][1] = +(A[0][0]*A[2][2] - A[0][2]*A[2][0]) + cofactors[1][2] = -(A[0][0]*A[2][1] - A[0][1]*A[2][0]) + cofactors[2][0] = +(A[0][1]*A[1][2] - A[0][2]*A[1][1]) + cofactors[2][1] = -(A[0][0]*A[1][2] - A[0][2]*A[1][0]) + cofactors[2][2] = +(A[0][0]*A[1][1] - A[0][1]*A[1][0]) + + adjoint[0][0] = cofactors[0][0] + adjoint[0][1] = cofactors[1][0] + adjoint[0][2] = cofactors[2][0] + adjoint[1][0] = cofactors[0][1] + adjoint[1][1] = cofactors[1][1] + adjoint[1][2] = cofactors[2][1] + adjoint[2][0] = cofactors[0][2] + adjoint[2][1] = cofactors[1][2] + adjoint[2][2] = cofactors[2][2] + + + A_inv[0][0] = adjoint[0][0]/det + A_inv[0][1] = adjoint[0][1]/det + A_inv[0][2] = adjoint[0][2]/det + A_inv[1][0] = adjoint[1][0]/det + A_inv[1][1] = adjoint[1][1]/det + A_inv[1][2] = adjoint[1][2]/det + A_inv[2][0] = adjoint[2][0]/det + A_inv[2][1] = adjoint[2][1]/det + A_inv[2][2] = adjoint[2][2]/det + + + arrays_to_be_evaled = \ + [A_inv[0][0], A_inv[0][1], A_inv[0][2], \ + A_inv[1][0], A_inv[1][1], A_inv[1][2], \ + A_inv[2][0], A_inv[2][1], A_inv[2][2] \ + ] + + af.eval(*arrays_to_be_evaled) + + return(A_inv) + From 8854ea83bab35a329b55a22932733ca10401a615 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 13:44:33 -0400 Subject: [PATCH 10/58] cartesian/polar switch added to files in the example folder --- .../boundary_conditions.py | 19 ++++++++++++++++--- .../initialize.py | 10 ++++++++-- .../params.py | 16 ++++++++++++++-- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py index 85724d01..ec810209 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py @@ -19,7 +19,14 @@ def f_left(f, t, q1, q2, p1, p2, p3, params): omega = 2. * np.pi * params.AC_freq vel_drift_x_in = params.vel_drift_x_in * np.sin(omega*t) - fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p1 - mu)/(k*T) ) + 1.) + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p_x - mu)/(k*T) ) + 1.) ) if (params.contact_geometry=="straight"): @@ -39,7 +46,7 @@ def f_left(f, t, q1, q2, p1, p2, p3, params): vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) - fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p1 - mu)/(k*T) ) + 1.) + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) ) # TODO: set these parameters in params.py @@ -63,8 +70,14 @@ def f_right(f, t, q1, q2, p1, p2, p3, params): t = params.current_time omega = 2. * np.pi * params.AC_freq vel_drift_x_out = params.vel_drift_x_out * np.sin(omega*t) + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + else: + raise NotImplementedError('Unsupported coordinate system in p_space') - fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p1 - mu)/(k*T) ) + 1.) + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) ) if (params.contact_geometry=="straight"): diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py index 8e6609c6..abf25bdb 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py @@ -28,8 +28,14 @@ def initialize_f(q1, q2, p1, p2, p3, params): E_upper = params.E_band + params.charge[0]*params.phi - f = (1./(af.exp( (E_upper - params.vel_drift_x*p1 - - params.vel_drift_y*p2 + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + f = (1./(af.exp( (E_upper - params.vel_drift_x*p_x + - params.vel_drift_y*p_y - params.mu )/(k*params.T) ) + 1. diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 2bb10261..39bb0502 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -108,7 +108,13 @@ def tau_ee(q1, q2, p1, p2, p3): def tau(q1, q2, p1, p2, p3): return(tau_defect(q1, q2, p1, p2, p3)) -def band_energy(p_x, p_y): +def band_energy(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') p = af.sqrt(p_x**2. + p_y**2.) @@ -117,8 +123,14 @@ def band_energy(p_x, p_y): af.eval(E_upper) return(E_upper) -def band_velocity(p_x, p_y): +def band_velocity(p1, p2): + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + p = af.sqrt(p_x**2. + p_y**2.) p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] From 507b734bf6a6527687a3c9e12e9659ebb85e8d0f Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 1 Jun 2019 13:46:14 -0400 Subject: [PATCH 11/58] Indentation fixed --- bolt/src/electronic_boltzmann/collision_operator.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 6b65a0b8..3ec172db 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -502,13 +502,13 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): return(fermi_dirac) -def RTA(f, q1, q2, p1, p2, p3, moments, params, flag = False): +def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): """Return BGK operator -(f-f0)/tau.""" if (params.p_space_grid == 'cartesian'): - p_x = p1 - p_y = p2 - p_z = p3 + p_x = p1 + p_y = p2 + p_z = p3 else : raise NotImplementedError('Unsupported coordinate system in p_space') From 9ced5e2306e5f5e933e8b5372ffe8b4143e12baa Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sun, 2 Jun 2019 01:57:34 -0400 Subject: [PATCH 12/58] Polar option added to switch, working --- bolt/lib/nonlinear/boundaries.py | 118 ++++++++++++++++++ .../collision_operator.py | 4 + .../boundary_conditions.py | 6 + .../domain.py | 40 +++++- .../initialize.py | 3 + .../params.py | 6 + 6 files changed, 171 insertions(+), 6 deletions(-) diff --git a/bolt/lib/nonlinear/boundaries.py b/bolt/lib/nonlinear/boundaries.py index e197f687..146656ac 100644 --- a/bolt/lib/nonlinear/boundaries.py +++ b/bolt/lib/nonlinear/boundaries.py @@ -310,6 +310,108 @@ def apply_mirror_bcs_f_cartesian(self, boundary): return +def apply_mirror_bcs_f_polar(self, boundary): + """ + Applies mirror boundary conditions along boundary specified + for the distribution function when momentum space is on a polar grid + + Parameters + ---------- + boundary: str + Boundary along which the boundary condition is to be applied. + """ + + N_g = self.N_ghost + + if(boundary == 'left'): + # x-0-x-0-x-0-|-0-x-0-x-0-x-.... + # 0 1 2 3 4 5 + # For mirror boundary conditions: + # 0 = 5; 1 = 4; 2 = 3; + self.f[:, :, :N_g] = af.flip(self.f[:, :, N_g:2 * N_g], 2) + + # For a particle moving with initial momentum at an angle \theta + # with the x-axis, a collision with the left boundary changes + # the angle of momentum after reflection to (pi - \theta) + # To do this, we split the array into to equal halves, + # flip each of the halves along the p_theta axis and then + # join the two flipped halves together. + + N_theta = self.N_p2 + + tmp1 = self._convert_to_p_expanded(self.f)[:, :N_theta/2, :, :] + tmp1 = af.flip(tmp1, 1) + tmp2 = self._convert_to_p_expanded(self.f)[:, N_theta/2:, :, :] + tmp2 = af.flip(tmp2, 1) + tmp = af.join(1, tmp1, tmp2) + + self.f[:, :, :N_g] = \ + self._convert_to_q_expanded(tmp)[:, :, :N_g] + + elif(boundary == 'right'): + # ...-x-0-x-0-x-0-|-0-x-0-x-0-x + # -6 -5 -4 -3 -2 -1 + # For mirror boundary conditions: + # -1 = -6; -2 = -5; -3 = -4; + self.f[:, :, -N_g:] = af.flip(self.f[:, :, -2 * N_g:-N_g], 2) + + # For a particle moving with initial momentum at an angle \theta + # with the x-axis, a collision with the right boundary changes + # the angle of momentum after reflection to (pi - \theta) + # To do this, we split the array into to equal halves, + # flip each of the halves along the p_theta axis and then + # join the two flipped halves together. + + N_theta = self.N_p2 + + tmp1 = self._convert_to_p_expanded(self.f)[:, :N_theta/2, :, :] + tmp1 = af.flip(tmp1, 1) + tmp2 = self._convert_to_p_expanded(self.f)[:, N_theta/2:, :, :] + tmp2 = af.flip(tmp2, 1) + tmp = af.join(1, tmp1, tmp2) + + self.f[:, :, -N_g:] = \ + self._convert_to_q_expanded(tmp)[:, :, -N_g:] + + elif(boundary == 'bottom'): + # x-0-x-0-x-0-|-0-x-0-x-0-x-.... + # 0 1 2 3 4 5 + # For mirror boundary conditions: + # 0 = 5; 1 = 4; 2 = 3; + self.f[:, :, :, :N_g] = af.flip(self.f[:, :, :, N_g:2 * N_g], 3) + + # For a particle moving with initial momentum at an angle \theta + # with the x-axis, a collision with the bottom boundary changes + # the angle of momentum after reflection to (2*pi - \theta) = (-\theta) + # To do this we flip the axis that contains the variation in p_theta + self.f[:, :, :, :N_g] = \ + self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f), + 1 + ) + )[:, :, :, :N_g] + + elif(boundary == 'top'): + # ...-x-0-x-0-x-0-|-0-x-0-x-0-x + # -6 -5 -4 -3 -2 -1 + # For mirror boundary conditions: + # -1 = -6; -2 = -5; -3 = -4; + self.f[:, :, :, -N_g:] = af.flip(self.f[:, :, :, -2 * N_g:-N_g], 3) + + # For a particle moving with initial momentum at an angle \theta + # with the x-axis, a collision with the top boundary changes + # the angle of momentum after reflection to (2*pi - \theta) = (-\theta) + # To do this we flip the axis that contains the variation in p_theta + self.f[:, :, :, -N_g:] = \ + self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f), + 1 + ) + )[:, :, :, -N_g:] + + else: + raise Exception('Invalid choice for boundary') + + return + def apply_bcs_f(self): """ Applies boundary conditions to the distribution function as specified by @@ -334,12 +436,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q1_left == 'mirror'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'left') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'left') else : raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q1_left == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'left') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'left') else : raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'left') @@ -363,12 +469,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q1_right == 'mirror'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'right') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'right') else: raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q1_right == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'right') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'right') else: raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'right') @@ -392,12 +502,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q2_bottom == 'mirror'): if (self.physical_system.params.p_space_grid =='cartesian'): apply_mirror_bcs_f_cartesian(self, 'bottom') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'bottom') else: raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q2_bottom == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'bottom') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'bottom') else: raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'bottom') @@ -421,12 +535,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q2_top == 'mirror'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'top') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'top') else: raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q2_top == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'top') + elif (self.physical_system.params.p_space_grid == 'polar'): + apply_mirror_bcs_f_polar(self, 'top') else: raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'top') diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 3ec172db..9dca4784 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -509,6 +509,10 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): p_x = p1 p_y = p2 p_z = p3 + elif (params.p_space_grid == 'polar'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + p_z = p3 else : raise NotImplementedError('Unsupported coordinate system in p_space') diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py index ec810209..e383778a 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py @@ -22,6 +22,9 @@ def f_left(f, t, q1, q2, p1, p2, p3, params): if (params.p_space_grid == 'cartesian'): p_x = p1 p_y = p2 + elif (params.p_space_grid == 'polar'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) else: raise NotImplementedError('Unsupported coordinate system in p_space') @@ -74,6 +77,9 @@ def f_right(f, t, q1, q2, p1, p2, p3, params): if (params.p_space_grid == 'cartesian'): p_x = p1 p_y = p2 + elif (params.p_space_grid == 'polar'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) else: raise NotImplementedError('Unsupported coordinate system in p_space') diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py index c5e4bef7..686b6c0e 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py @@ -1,3 +1,6 @@ +import numpy as np +import params + q1_start = 0. q1_end = 5.0 N_q1 = 10 @@ -8,18 +11,43 @@ # If N_p1 > 1, mirror boundary conditions require p1 to be # symmetric about zero - -p1_start = [-0.04] -p1_end = [0.04] +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation N_p1 = 16 +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 +#p1_start = [-0.04] +#p1_end = [0.04] + + +# In the polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu +p1_start = [params.initial_mu - \ + 16.*params.boltzmann_constant*params.initial_temperature] +p1_end = [params.initial_mu + \ + 16.*params.boltzmann_constant*params.initial_temperature] + + + # If N_p2 > 1, mirror boundary conditions require p2 to be # symmetric about zero - -p2_start = [-0.04] -p2_end = [0.04] N_p2 = 16 +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +#p2_start = [-0.04] +#p2_end = [0.04] + +# In the polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +p2_start = [-np.pi] +p2_end = [np.pi] + # If N_p3 > 1, mirror boundary conditions require p3 to be # symmetric about zero diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py index abf25bdb..ba7cb21e 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py @@ -31,6 +31,9 @@ def initialize_f(q1, q2, p1, p2, p3, params): if (params.p_space_grid == 'cartesian'): p_x = p1 p_y = p2 + elif (params.p_space_grid == 'polar'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) else: raise NotImplementedError('Unsupported coordinate system in p_space') diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 39bb0502..2037c661 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -113,6 +113,9 @@ def band_energy(p1, p2): if (p_space_grid == 'cartesian'): p_x = p1 p_y = p2 + elif (p_space_grid == 'polar'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) else : raise NotImplementedError('Unsupported coordinate system in p_space') @@ -128,6 +131,9 @@ def band_velocity(p1, p2): if (p_space_grid == 'cartesian'): p_x = p1 p_y = p2 + elif (p_space_grid == 'polar'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) else : raise NotImplementedError('Unsupported coordinate system in p_space') From ed9d4e9f2da61561bd632ac50f8a0c2129646ff6 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sun, 2 Jun 2019 02:00:14 -0400 Subject: [PATCH 13/58] Removed extra file \ --- .../graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 "example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" diff --git "a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" "b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" deleted file mode 100644 index b574f48c..00000000 --- "a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/\\" +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from bolt.src.utils.integral_over_v import integral_over_v - - -def density(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v1**(4./(2.*3.1415926535*1.0545718e-4)), integral_measure)) - -def j_x(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v1**(4./(2.*3.1415926535*1.0545718e-4)), integral_measure)) - -def j_y(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v2**(4./(2.*3.1415926535*1.0545718e-4)), integral_measure)) From b9d4279e4bbd1e32bc891de465fffe4e1fdf2591 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 3 Jun 2019 06:44:03 -0400 Subject: [PATCH 14/58] Changed polar to polar2D, added multiplicative factor mu in compute_moments.py for polar2D --- bolt/lib/nonlinear/boundaries.py | 36 +++++++++---------- bolt/lib/nonlinear/compute_moments.py | 21 ++++++++--- .../collision_operator.py | 2 +- bolt/src/electronic_boltzmann/moments.py | 17 --------- .../boundary_conditions.py | 4 +-- .../domain.py | 4 +-- .../initialize.py | 2 +- .../params.py | 7 ++-- 8 files changed, 44 insertions(+), 49 deletions(-) delete mode 100644 bolt/src/electronic_boltzmann/moments.py diff --git a/bolt/lib/nonlinear/boundaries.py b/bolt/lib/nonlinear/boundaries.py index 146656ac..c949ce27 100644 --- a/bolt/lib/nonlinear/boundaries.py +++ b/bolt/lib/nonlinear/boundaries.py @@ -310,10 +310,10 @@ def apply_mirror_bcs_f_cartesian(self, boundary): return -def apply_mirror_bcs_f_polar(self, boundary): +def apply_mirror_bcs_f_polar2D(self, boundary): """ Applies mirror boundary conditions along boundary specified - for the distribution function when momentum space is on a polar grid + for the distribution function when momentum space is on a 2D polar grid Parameters ---------- @@ -436,16 +436,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q1_left == 'mirror'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'left') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'left') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'left') else : raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q1_left == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'left') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'left') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'left') else : raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'left') @@ -469,16 +469,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q1_right == 'mirror'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'right') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'right') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'right') else: raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q1_right == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'right') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'right') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'right') else: raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'right') @@ -502,16 +502,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q2_bottom == 'mirror'): if (self.physical_system.params.p_space_grid =='cartesian'): apply_mirror_bcs_f_cartesian(self, 'bottom') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'bottom') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'bottom') else: raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q2_bottom == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'bottom') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'bottom') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'bottom') else: raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'bottom') @@ -535,16 +535,16 @@ def apply_bcs_f(self): elif(self.boundary_conditions.in_q2_top == 'mirror'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'top') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'top') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'top') else: raise NotImplementedError('Unsupported coordinate system in p_space') elif(self.boundary_conditions.in_q2_top == 'mirror+dirichlet'): if (self.physical_system.params.p_space_grid == 'cartesian'): apply_mirror_bcs_f_cartesian(self, 'top') - elif (self.physical_system.params.p_space_grid == 'polar'): - apply_mirror_bcs_f_polar(self, 'top') + elif (self.physical_system.params.p_space_grid == 'polar2D'): + apply_mirror_bcs_f_polar2D(self, 'top') else: raise NotImplementedError('Unsupported coordinate system in p_space') apply_dirichlet_bcs_f(self, 'top') diff --git a/bolt/lib/nonlinear/compute_moments.py b/bolt/lib/nonlinear/compute_moments.py index 17b2ff8d..cac25188 100644 --- a/bolt/lib/nonlinear/compute_moments.py +++ b/bolt/lib/nonlinear/compute_moments.py @@ -38,11 +38,22 @@ def compute_moments(self, moment_name, f=None): if(f is None): f = self.f - - moment = af.broadcast(getattr(self.physical_system.moments, - moment_name - ), f, p1, p2, p3, self.dp3 * self.dp2 * self.dp1 - ) + + if (self.physical_system.params.p_space_grid == 'cartesian'): + moment = af.broadcast(getattr(self.physical_system.moments, + moment_name + ), f, p1, p2, p3, self.dp3 * self.dp2 * self.dp1 + ) + + elif (self.physical_system.params.p_space_grid == 'polar2D'): + moment = self.physical_system.params.initial_mu * \ + af.broadcast(getattr(self.physical_system.moments, + moment_name + ), f, p1, p2, p3, self.dp3 * self.dp2 * self.dp1 + ) + + else: + raise NotImplementedError('Unsupported coordinate system in p_space') af.eval(moment) return (moment) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 9dca4784..725b2279 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -509,7 +509,7 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): p_x = p1 p_y = p2 p_z = p3 - elif (params.p_space_grid == 'polar'): + elif (params.p_space_grid == 'polar2D'): p_x = p1 * af.cos(p2) p_y = p1 * af.sin(p2) p_z = p3 diff --git a/bolt/src/electronic_boltzmann/moments.py b/bolt/src/electronic_boltzmann/moments.py deleted file mode 100644 index fba232f6..00000000 --- a/bolt/src/electronic_boltzmann/moments.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import numpy as np - -from bolt.src.utils.integral_over_v import integral_over_v - -import params - -def density(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v1**(4./(2.*np.pi*params.h_bar)), integral_measure)) - -def j_x(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v1**(4./(2.*np.pi*params.h_bar)), integral_measure)) - -def j_y(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v2**(4./(2.*np.pi*params.h_bar)), integral_measure)) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py index e383778a..24d0598b 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py @@ -22,7 +22,7 @@ def f_left(f, t, q1, q2, p1, p2, p3, params): if (params.p_space_grid == 'cartesian'): p_x = p1 p_y = p2 - elif (params.p_space_grid == 'polar'): + elif (params.p_space_grid == 'polar2D'): p_x = p1 * af.cos(p2) p_y = p1 * af.sin(p2) else: @@ -77,7 +77,7 @@ def f_right(f, t, q1, q2, p1, p2, p3, params): if (params.p_space_grid == 'cartesian'): p_x = p1 p_y = p2 - elif (params.p_space_grid == 'polar'): + elif (params.p_space_grid == 'polar2D'): p_x = p1 * af.cos(p2) p_y = p1 * af.sin(p2) else: diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py index 686b6c0e..79d6cc62 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py @@ -22,7 +22,7 @@ #p1_end = [0.04] -# In the polar representation of momentum space, +# In the 2D polar representation of momentum space, # p1 = p_r (magnitude of momentum) # p1_start and p1_end are set such that p1_center is mu p1_start = [params.initial_mu - \ @@ -42,7 +42,7 @@ #p2_start = [-0.04] #p2_end = [0.04] -# In the polar representation of momentum space, +# In the 2D polar representation of momentum space, # p2 = p_theta (angle of momentum) # N_p_theta MUST be even. p2_start = [-np.pi] diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py index ba7cb21e..fd1a0ffb 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py @@ -31,7 +31,7 @@ def initialize_f(q1, q2, p1, p2, p3, params): if (params.p_space_grid == 'cartesian'): p_x = p1 p_y = p2 - elif (params.p_space_grid == 'polar'): + elif (params.p_space_grid == 'polar2D'): p_x = p1 * af.cos(p2) p_y = p1 * af.sin(p2) else: diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 2037c661..525dc12f 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -48,7 +48,8 @@ # Dimensionality considered in velocity space: p_dim = 2 -p_space_grid = 'cartesian' # Supports 'cartesian' or 'polar' grids +p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py # Number of devices(GPUs/Accelerators) on each node: num_devices = 6 @@ -113,7 +114,7 @@ def band_energy(p1, p2): if (p_space_grid == 'cartesian'): p_x = p1 p_y = p2 - elif (p_space_grid == 'polar'): + elif (p_space_grid == 'polar2D'): p_x = p1 * af.cos(p2) p_y = p1 * af.sin(p2) else : @@ -131,7 +132,7 @@ def band_velocity(p1, p2): if (p_space_grid == 'cartesian'): p_x = p1 p_y = p2 - elif (p_space_grid == 'polar'): + elif (p_space_grid == 'polar2D'): p_x = p1 * af.cos(p2) p_y = p1 * af.sin(p2) else : From bff6c0d1ab236664de7b8a06330e624901488701 Mon Sep 17 00:00:00 2001 From: Mani Chandra Date: Sat, 8 Jun 2019 12:13:35 -0400 Subject: [PATCH 15/58] (1) True 1D3V works. Tested with nonrelativistic_boltzmann/instabilities/collisionless_shock/1D (2) Fixed random number bug that shows up when running in parallel. Uses correct parallel random number generator now and is set in params.random_vals. (3) Deep clean all over. --- bolt/lib/nonlinear/boundaries.py | 16 +- bolt/lib/nonlinear/communicate.py | 77 ++----- bolt/lib/nonlinear/fields/boundaries.py | 16 +- bolt/lib/nonlinear/fields/fields.py | 205 +++++++++++------- bolt/lib/nonlinear/file_io/dump.py | 40 +--- .../nonlinear/finite_volume/fvm_operator.py | 60 +---- bolt/lib/nonlinear/nonlinear_solver.py | 199 ++++++++--------- bolt/lib/nonlinear/tests/test_petsc_IO.py | 42 ++++ bolt/lib/physical_system.py | 1 + bolt/lib/utils/af_petsc_conversion.py | 38 ++++ bolt/lib/utils/calculate_p.py | 92 +++----- bolt/lib/utils/calculate_q.py | 99 ++------- .../1D/boundary_conditions.py | 4 +- .../collisionless_shock/1D/domain.py | 4 +- .../collisionless_shock/1D/initialize.py | 7 +- .../collisionless_shock/1D/main.py | 12 +- .../collisionless_shock/1D/params.py | 6 +- .../collisionless_shock/1D/post_1d.py | 12 +- 18 files changed, 424 insertions(+), 506 deletions(-) create mode 100644 bolt/lib/nonlinear/tests/test_petsc_IO.py create mode 100644 bolt/lib/utils/af_petsc_conversion.py diff --git a/bolt/lib/nonlinear/boundaries.py b/bolt/lib/nonlinear/boundaries.py index 3d2d5a47..f7f3bff7 100644 --- a/bolt/lib/nonlinear/boundaries.py +++ b/bolt/lib/nonlinear/boundaries.py @@ -339,7 +339,9 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'left') # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q1_left == 'periodic'): + elif( self.boundary_conditions.in_q1_left == 'periodic' + or self.boundary_conditions.in_q1_left == 'none' # no ghost zones (1D) + ): pass elif(self.boundary_conditions.in_q1_left == 'shearing-box'): @@ -362,7 +364,9 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'right') # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q1_right == 'periodic'): + elif( self.boundary_conditions.in_q1_right == 'periodic' + or self.boundary_conditions.in_q1_right == 'none' # no ghost zones (1D) + ): pass elif(self.boundary_conditions.in_q1_right == 'shearing-box'): @@ -385,7 +389,9 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'bottom') # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q2_bottom == 'periodic'): + elif( self.boundary_conditions.in_q2_bottom == 'periodic' + or self.boundary_conditions.in_q2_bottom == 'none' # no ghost zones (1D) + ): pass elif(self.boundary_conditions.in_q2_bottom == 'shearing-box'): @@ -408,7 +414,9 @@ def apply_bcs_f(self): apply_dirichlet_bcs_f(self, 'top') # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q2_top == 'periodic'): + elif( self.boundary_conditions.in_q2_top == 'periodic' + or self.boundary_conditions.in_q2_top == 'none' # no ghost zones (1D) + ): pass elif(self.boundary_conditions.in_q2_top == 'shearing-box'): diff --git a/bolt/lib/nonlinear/communicate.py b/bolt/lib/nonlinear/communicate.py index eed144e7..1322cbe7 100644 --- a/bolt/lib/nonlinear/communicate.py +++ b/bolt/lib/nonlinear/communicate.py @@ -2,6 +2,8 @@ # -*- coding: utf-8 -*- import arrayfire as af +from bolt.lib.utils.af_petsc_conversion import af_to_petsc_glob_array +from bolt.lib.utils.af_petsc_conversion import petsc_local_array_to_af def communicate_f(self): """ @@ -14,43 +16,19 @@ def communicate_f(self): if(self.performance_test_flag == True): tic = af.time() - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_f.getCorners() - - N_g = self.N_ghost - - # Assigning the local array only when Dirichlet - # boundary conditions are applied. This is needed since - # only inflowing characteristics are to be changed by - # the apply boundary conditions function. - - if( self.boundary_conditions.in_q1_left == 'dirichlet' - or self.boundary_conditions.in_q1_right == 'dirichlet' - or self.boundary_conditions.in_q2_bottom == 'dirichlet' - or self.boundary_conditions.in_q2_top == 'dirichlet' - ): - af.flat(self.f).to_ndarray(self._local_f_array) - - # Global value is non-inclusive of the ghost-zones: - af.flat(self.f[:, :, N_g:-N_g, N_g:-N_g]).to_ndarray(self._glob_f_array) + # Transfer data from af.Array to PETSc.Vec + af_to_petsc_glob_array(self, self.f, self._glob_f_array) # The following function takes care of interzonal communications # Additionally, it also automatically applies periodic BCs when necessary self._da_f.globalToLocal(self._glob_f, self._local_f) # Converting back from PETSc.Vec to af.Array: - f_flattened = af.to_array(self._local_f_array) - self.f = af.moddims(f_flattened, - self.N_p1 - * self.N_p2 - * self.N_p3, - self.N_species, - N_q1_local + 2 * N_g, - N_q2_local + 2 * N_g - ) - - af.eval(self.f) + self.f = petsc_local_array_to_af(self, + self.N_p1*self.N_p2*self.N_p3, + self.N_species, + self._local_f_array + ) if(self.performance_test_flag == True): af.sync() @@ -59,7 +37,6 @@ def communicate_f(self): return - def communicate_fields(self, on_fdtd_grid = False): """ Used in communicating the values at the boundary zones for each of @@ -72,46 +49,26 @@ def communicate_fields(self, on_fdtd_grid = False): if(self.performance_test_flag == True): tic = af.time() - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_fields.getCorners() - - N_g = self.N_g - # Assigning the values of the af.Array # fields quantities to the PETSc.Vec: if(on_fdtd_grid is True): - flattened_global_EM_fields_array = \ - af.flat(self.yee_grid_EM_fields[:, :, N_g:-N_g, N_g:-N_g]) - flattened_global_EM_fields_array.to_ndarray(self._glob_fields_array) - + tmp_array = self.yee_grid_EM_fields else: - flattened_global_EM_fields_array = \ - af.flat(self.cell_centered_EM_fields[:, :, N_g:-N_g, N_g:-N_g]) - flattened_global_EM_fields_array.to_ndarray(self._glob_fields_array) + tmp_array = self.cell_centered_EM_fields + + af_to_petsc_glob_array(self, tmp_array, self._glob_fields_array) # Takes care of boundary conditions and interzonal communications: self._da_fields.globalToLocal(self._glob_fields, self._local_fields) # Converting back to af.Array - if(on_fdtd_grid is True): - - self.yee_grid_EM_fields = af.moddims(af.to_array(self._local_fields_array), - 6, 1, N_q1_local + 2 * N_g, - N_q2_local + 2 * N_g - ) - - af.eval(self.yee_grid_EM_fields) + tmp_array = petsc_local_array_to_af(self, 6, 1, self._local_fields_array) + if(on_fdtd_grid is True): + self.yee_grid_EM_fields = tmp_array else: - - self.cell_centered_EM_fields = af.moddims(af.to_array(self._local_fields_array), - 6, 1, N_q1_local + 2 * N_g, - N_q2_local + 2 * N_g - ) + self.cell_centered_EM_fields = tmp_array - af.eval(self.cell_centered_EM_fields) - if(self.performance_test_flag == True): af.sync() toc = af.time() diff --git a/bolt/lib/nonlinear/fields/boundaries.py b/bolt/lib/nonlinear/fields/boundaries.py index 0bd08761..4d3d555e 100644 --- a/bolt/lib/nonlinear/fields/boundaries.py +++ b/bolt/lib/nonlinear/fields/boundaries.py @@ -595,7 +595,9 @@ def apply_bcs_fields(self, on_fdtd_grid = False): apply_dirichlet_bcs_fields(self, 'left', on_fdtd_grid) # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q1_left == 'periodic'): + elif( self.boundary_conditions.in_q1_left == 'periodic' + or self.boundary_conditions.in_q1_left == 'none' + ): pass elif(self.boundary_conditions.in_q1_left == 'shearing-box'): @@ -618,7 +620,9 @@ def apply_bcs_fields(self, on_fdtd_grid = False): apply_dirichlet_bcs_fields(self, 'right', on_fdtd_grid) # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q1_right == 'periodic'): + elif( self.boundary_conditions.in_q1_right == 'periodic' + or self.boundary_conditions.in_q1_right == 'none' + ): pass elif(self.boundary_conditions.in_q1_right == 'shearing-box'): @@ -641,7 +645,9 @@ def apply_bcs_fields(self, on_fdtd_grid = False): apply_dirichlet_bcs_fields(self, 'bottom', on_fdtd_grid) # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q2_bottom == 'periodic'): + elif( self.boundary_conditions.in_q2_bottom == 'periodic' + or self.boundary_conditions.in_q2_bottom == 'none' + ): pass elif(self.boundary_conditions.in_q2_bottom == 'shearing-box'): @@ -664,7 +670,9 @@ def apply_bcs_fields(self, on_fdtd_grid = False): apply_dirichlet_bcs_fields(self, 'top', on_fdtd_grid) # This is automatically handled by the PETSc function globalToLocal() - elif(self.boundary_conditions.in_q2_top == 'periodic'): + elif( self.boundary_conditions.in_q2_top == 'periodic' + or self.boundary_conditions.in_q2_top == 'none' + ): pass elif(self.boundary_conditions.in_q2_top == 'shearing-box'): diff --git a/bolt/lib/nonlinear/fields/fields.py b/bolt/lib/nonlinear/fields/fields.py index 0e6f9f7e..e0769619 100644 --- a/bolt/lib/nonlinear/fields/fields.py +++ b/bolt/lib/nonlinear/fields/fields.py @@ -12,13 +12,13 @@ from .electrostatic.fft import fft_poisson from .electrodynamic.fdtd_explicit import fdtd -from bolt.lib.utils.calculate_q import \ - calculate_q_center, calculate_q_left_center, \ - calculate_q_center_bot, calculate_q_left_bot +from bolt.lib.utils.calculate_q import calculate_q +from bolt.lib.utils.af_petsc_conversion import af_to_petsc_glob_array +from bolt.lib.utils.af_petsc_conversion import petsc_local_array_to_af class fields_solver(object): - - # Computing divB on cell edges + + # Computing divB at cell corners (i, j) def compute_divB(self): B1 = self.yee_grid_EM_fields[3] # (i + 1/2, j) @@ -27,10 +27,11 @@ def compute_divB(self): B1_minus_q1 = af.shift(B1, 0, 0, 1) # (i - 1/2, j) B2_minus_q2 = af.shift(B2, 0, 0, 0, 1) # (i, j - 1/2) - divB = (B1 - B1_minus_q1) / self.dq1 + (B2 - B2_minus_q2) / self.dq2 # (i, j) + divB = (B1 - B1_minus_q1)/self.dq1 + (B2 - B2_minus_q2)/self.dq2 # (i, j) + return(divB) - # Computing divE at cell centers + # Computing divE at cell centers (i+1/2, j+1/2) def compute_divE(self): communicate.communicate_fields(self, True) @@ -41,36 +42,38 @@ def compute_divE(self): E1_plus_q1 = af.shift(E1, 0, 0, -1) # (i + 1, j + 1/2) E2_plus_q2 = af.shift(E2, 0, 0, 0, -1) # (i + 1/2, j + 1) - divE = (E1_plus_q1 - E1) / self.dq1 + (E2_plus_q2 - E2) / self.dq2 # (i + 1/2, j + 1/2) + divE = (E1_plus_q1 - E1)/self.dq1 + (E2_plus_q2 - E2)/self.dq2 # (i + 1/2, j + 1/2) return(divE) def check_maxwells_contraint_equations(self, rho): - N_g = self.N_g - PETSc.Sys.Print("Initial Maxwell's Constraints:") - mean_divB = af.mean(af.abs(self.compute_divB()[:, :, N_g:-N_g, N_g:-N_g])) - PETSc.Sys.Print('MEAN(|divB|) =', mean_divB) + divB_error = af.abs(self.compute_divB()) + af_to_petsc_glob_array(self, divB_error, self._glob_divB_error_array) - rho_by_eps = rho / self.params.eps + PETSc.Sys.Print('MAX(|divB|) =', self._glob_divB_error.max()) + + # TODO: What the is going on here? rho_b?? + rho_by_eps = rho #/ self.params.dielectric_epsilon rho_b = af.mean(rho_by_eps) # background - divE = self.compute_divE() - mean_gauss_law = af.mean(af.abs((divE- rho_by_eps + rho_b)[:, :, N_g:-N_g, N_g:-N_g])) - PETSc.Sys.Print('MEAN(|divE-rho|) =', mean_gauss_law) + divE_error = self.compute_divE() - rho_by_eps + rho_b + + af_to_petsc_glob_array(self, divE_error, self._glob_divE_error_array) + PETSc.Sys.Print('MAX(|divE-rho|) =', self._glob_divE_error.max()) # Appropriately raising exceptions: # Checking for ∇.B = 0 - try: - assert(mean_divB < 1e-10) - except: - raise SystemExit('divB contraint isn\'t preserved') - - # Checking for ∇.E = ρ/ε: - # TODO: Need to look into this further: - # try: - # assert(mean_gauss_law < 1e-7) - # except: - # raise SystemExit('divE - rho/epsilon contraint isn\'t preserved') - +# try: +# assert(mean_divB < params.divB_tol) +# except: +# raise SystemExit('divB contraint isn\'t preserved') +# +# # Checking for ∇.E = ρ/ε: +# # TODO: Need to look into this further: +# try: +# assert(mean_gauss_law < params.divE_tol) +# except: +# raise SystemExit('divE - rho/epsilon contraint isn\'t preserved') +# def __init__(self, physical_system, rho_initial, performance_test_flag = False): """ Constructor for the fields_solver object, which takes in the physical system @@ -99,7 +102,7 @@ def __init__(self, physical_system, rho_initial, performance_test_flag = False): self.N_q1 = physical_system.N_q1 self.N_q2 = physical_system.N_q2 - self.N_g = physical_system.N_ghost + self.N_ghost = self.N_g = physical_system.N_ghost self.dq1 = physical_system.dq1 self.dq2 = physical_system.dq2 @@ -121,8 +124,8 @@ def __init__(self, physical_system, rho_initial, performance_test_flag = False): self.time_elapsed = 0 - petsc_bc_in_q1 = 'ghosted' - petsc_bc_in_q2 = 'ghosted' + petsc_bc_in_q1 = 'ghosted'; self.N_g1 = self.N_ghost + petsc_bc_in_q2 = 'ghosted'; self.N_g2 = self.N_ghost # Only for periodic boundary conditions or shearing-box boundary conditions # do the boundary conditions passed to the DA need to be changed. PETSc @@ -143,6 +146,12 @@ def __init__(self, physical_system, rho_initial, performance_test_flag = False): ): petsc_bc_in_q2 = 'periodic' + if(self.boundary_conditions.in_q1_left == 'none'): + petsc_bc_in_q1 = 'none'; self.N_g1 = 0 + + if(self.boundary_conditions.in_q2_bottom == 'none'): + petsc_bc_in_q2 = 'none'; self.N_g2 = 0 + nproc_in_q1 = PETSc.DECIDE nproc_in_q2 = PETSc.DECIDE @@ -170,38 +179,64 @@ def __init__(self, physical_system, rho_initial, performance_test_flag = False): comm = self._comm ) - - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_fields.getCorners() - - self.q1_center, self.q2_center = \ - calculate_q_center(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, self.N_g, - self.dq1, self.dq2 - ) - - self.q1_left_center, self.q2_left_center = \ - calculate_q_left_center(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, self.N_g, - self.dq1, self.dq2 - ) - - self.q1_center_bot, self.q2_center_bot = \ - calculate_q_center_bot(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, self.N_g, - self.dq1, self.dq2 - ) - - self.q1_left_bot, self.q2_left_bot = \ - calculate_q_left_bot(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, self.N_g, - self.dq1, self.dq2 - ) + # Make to da to create aux vecs, such as holding random numbers, + # storing errors etc + self._da_aux = PETSc.DMDA().create([self.N_q1, self.N_q2], + dof = 1, + stencil_width = self.N_g, + boundary_type = (petsc_bc_in_q1, + petsc_bc_in_q2 + ), + proc_sizes = (nproc_in_q1, + nproc_in_q2 + ), + stencil_type = 1, + comm = self._comm + ) + + # Get start (corner) indices of the local zone wrt global ordering and its size + ((_i_q1_start, _i_q2_start), (_N_q1_local, _N_q2_local)) = \ + self._da_fields.getCorners() + + # Coordinates of the local zone in a global coord system + self.q1_start_local = self.q1_start + _i_q1_start * self.dq1 + self.q2_start_local = self.q2_start + _i_q2_start * self.dq2 + + self.N_q1_local = _N_q1_local + self.N_q2_local = _N_q2_local + + self.N_q1_local_with_Ng = _N_q1_local + 2*self.N_g1 + self.N_q2_local_with_Ng = _N_q2_local + 2*self.N_g2 + + # Indexing vars used through out + self.i_q1_start = self.N_g1; self.i_q1_end = -self.N_g1 + self.i_q2_start = self.N_g2; self.i_q2_end = -self.N_g2 + if (self.N_g1 == 0): + self.i_q1_end = 1 + + if (self.N_g2 == 0): + self.i_q2_end = 1 + + # Obtaining the array values of spatial coordinates: + q_left_bot, q_center_bot, q_left_center, q_center = \ + calculate_q(self.q1_start_local, + self.q2_start_local, + self.N_q1_local, self.N_q2_local, + self.N_g1, self.N_g2, + self.dq1, self.dq2 + ) + + self.q1_left_bot = q_left_bot[0] + self.q2_left_bot = q_left_bot[1] + + self.q1_center_bot = q_center_bot[0] + self.q2_center_bot = q_center_bot[1] + + self.q1_left_center = q_left_center[0] + self.q2_left_center = q_left_center[1] + + self.q1_center = q_center[0] + self.q2_center = q_center[1] # The following global and local vectors are used in # the communication routines for EM fields @@ -212,7 +247,27 @@ def __init__(self, physical_system, rho_initial, performance_test_flag = False): self._local_fields_array = self._local_fields.getArray() PETSc.Object.setName(self._glob_fields, 'EM_fields') + + self._glob_divB_error = self._da_aux.createGlobalVec() + self._glob_divE_error = self._da_aux.createGlobalVec() + + self._glob_divB_error_array = self._glob_divB_error.getArray() + self._glob_divE_error_array = self._glob_divE_error.getArray() + # Create a random number vec to use when needed, e.g, initial conditions + self._glob_random = self._da_aux.createGlobalVec() + self._glob_random.setRandom() + self._glob_random_array = self._glob_random.getArray() + + self._local_random = self._da_aux.createLocalVec() + self._da_aux.globalToLocal(self._glob_random, self._local_random) + self._local_random_array = self._local_random.getArray() + + self.random_vals = petsc_local_array_to_af(self, 1, 1, self._local_random_array) + # Inject random_vals into params so that it can be used for + # initialization + self.params.random_vals = self.random_vals + # Alternating upon each call to get_fields for FVM: # This ensures that the fields are staggerred correctly in time: self.at_n = True @@ -376,37 +431,33 @@ def _initialize(self, rho_initial): The initial charge density array that's passed to an electrostatic solver for initialization """ - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_fields.getCorners() - # Following quantities are cell-centered (i + 0.5, j + 0.5): # Electric fields are defined at the n-th timestep: # Magnetic fields are defined at the (n-1/2)-th timestep: self.cell_centered_EM_fields = af.constant(0, 6, 1, - N_q1_local + 2 * self.N_g, - N_q2_local + 2 * self.N_g, + self.N_q1_local_with_Ng, + self.N_q2_local_with_Ng, dtype=af.Dtype.f64 ) # Field values at n-th timestep: self.cell_centered_EM_fields_at_n = af.constant(0, 6, 1, - N_q1_local + 2 * self.N_g, - N_q2_local + 2 * self.N_g, + self.N_q1_local_with_Ng, + self.N_q2_local_with_Ng, dtype=af.Dtype.f64 ) # Field values at (n+1/2)-th timestep: self.cell_centered_EM_fields_at_n_plus_half = af.constant(0, 6, 1, - N_q1_local + 2 * self.N_g, - N_q2_local + 2 * self.N_g, + self.N_q1_local_with_Ng, + self.N_q2_local_with_Ng, dtype=af.Dtype.f64 ) # Declaring the arrays which store data on the yee grid for FDTD: self.yee_grid_EM_fields = af.constant(0, 6, 1, - N_q1_local + 2 * self.N_g, - N_q2_local + 2 * self.N_g, + self.N_q1_local_with_Ng, + self.N_q2_local_with_Ng, dtype=af.Dtype.f64 ) @@ -471,7 +522,6 @@ def cell_centered_grid_to_yee_grid(self, fields_to_transform = None): + af.shift(B3, 0, 0, 1, 1) ) # (i, j) - af.eval(self.yee_grid_EM_fields) return def yee_grid_to_cell_centered_grid(self, fields_to_transform = None): @@ -504,7 +554,6 @@ def yee_grid_to_cell_centered_grid(self, fields_to_transform = None): + af.shift(B3_yee, 0, 0, -1, -1) ) - af.eval(self.cell_centered_EM_fields) return def compute_electrostatic_fields(self, rho): @@ -516,8 +565,6 @@ def compute_electrostatic_fields(self, rho): communicate.communicate_fields(self) apply_bcs_fields(self) - # ADD SNES BELOW - def evolve_electrodynamic_fields(self, J1, J2, J3, dt): """ Evolve the fields using FDTD. diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index 5fcf5220..fe7cd553 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -4,6 +4,7 @@ from petsc4py import PETSc import numpy as np import arrayfire as af +from bolt.lib.utils.af_petsc_conversion import af_to_petsc_glob_array def dump_moments(self, file_name): """ @@ -71,30 +72,20 @@ def dump_moments(self, file_name): for i in range(len(attributes)): if(i == 0): - array_to_dump = self.compute_moments(attributes[i])[:, :, N_g:-N_g,N_g:-N_g] + array_to_dump = self.compute_moments(attributes[i]) else: array_to_dump = af.join(1, array_to_dump, - self.compute_moments(attributes[i])[:, :, N_g:-N_g, N_g:-N_g] + self.compute_moments(attributes[i]) ) af.eval(array_to_dump) - af.flat(array_to_dump).to_ndarray(self._glob_moments_array) + + af_to_petsc_glob_array(self, array_to_dump, self._glob_moments_array) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self._glob_moments) - # Following segment shows discrepancy due to buggy behaviour of af.mean - # Reported in https://github.com/QuazarTech/Bolt/issues/46 - # print("MEAN_n for species 1(RAW DATA):", af.mean(array_to_dump[:, 0, :, :])) - # print("MEAN_n for species 2(RAW DATA):", af.mean(array_to_dump[:, 1, :, :])) - - # h5f = h5py.File(file_name + '.h5', 'r') - # mom = np.swapaxes(h5f['moments'][:], 0, 1) - # h5f.close() - - # print("MEAN_n for species 1(DUMP DATA):", np.mean(mom[:, :, 0])) - # print("MEAN_n for species 2(DUMP DATA):", np.mean(mom[:, :, 1])) - def dump_distribution_function(self, file_name): """ This function is used to dump distribution function to a file for @@ -137,15 +128,8 @@ def dump_distribution_function(self, file_name): >> solver.load_distribution_function('distribution_function') """ - N_g = self.N_ghost - - N_q1_local = self.f.shape[2] - N_q2_local = self.f.shape[3] - array_to_dump = self.f - - array_to_dump = af.flat(array_to_dump[:, :, N_g:-N_g, N_g:-N_g]) - array_to_dump.to_ndarray(self._glob_f_array) + af_to_petsc_glob_array(self, self.f, self._glob_f_array) viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self._glob_f) @@ -205,12 +189,12 @@ def dump_EM_fields(self, file_name): >> solver.load_EM_fields('data_EM_fields') """ - N_g = self.N_ghost - - flattened_global_EM_fields_array = \ - af.flat(self.fields_solver.yee_grid_EM_fields[:, :, N_g:-N_g, N_g:-N_g]) - flattened_global_EM_fields_array.to_ndarray(self.fields_solver._glob_fields_array) + af_to_petsc_glob_array(self, + self.fields_solver.yee_grid_EM_fields, + self.fields_solver._glob_fields_array + ) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self.fields_solver._glob_fields) diff --git a/bolt/lib/nonlinear/finite_volume/fvm_operator.py b/bolt/lib/nonlinear/finite_volume/fvm_operator.py index 83622019..ab90b6dd 100644 --- a/bolt/lib/nonlinear/finite_volume/fvm_operator.py +++ b/bolt/lib/nonlinear/finite_volume/fvm_operator.py @@ -18,11 +18,9 @@ def timestep_fvm(self, dt): dt : double Time-step size to evolve the system """ - # self.fields_solver.check_maxwells_contraint_equations(af.sum(-10 * self.compute_moments('density'), 1)) - # rho_n = -1 * self.compute_moments('density') - # rho_n[0, 1] = -1 * rho_n[0, 1] - # rho_n = af.sum(rho_n, 1) + self._communicate_f() + self._apply_bcs_f() f_initial = self.f # this is f^{n} self.f = self.f + df_dt_fvm(self.f, self) * (dt / 2) # this is f{n+1/2} @@ -34,66 +32,14 @@ def timestep_fvm(self, dt): # there df_dt() is the function that returns df / dt self.f = f_initial + df_dt_fvm(self.f, self) * dt - # self.count += 1 - - # rho_n_plus_one = -1 * self.compute_moments('density') - # rho_n_plus_one[0, 1] = -1 * rho_n_plus_one[0, 1] - # rho_n_plus_one = af.sum(rho_n_plus_one, 1) - - # drho_dt = (rho_n_plus_one - rho_n) / dt - - # J1 = self.fields_solver.J1 - # J2 = self.fields_solver.J2 - - # J1_plus_q1 = af.shift(self.fields_solver.J1, 0, 0, -1) - # J2_plus_q2 = af.shift(self.fields_solver.J2, 0, 0, 0, -1) - - # divJ = (J1_plus_q1 - J1) / self.dq1 + (J2_plus_q2 - J2) / self.dq2 - - # print(af.mean(af.abs(drho_dt + divJ)[:, :, 4:-4, 4:-4])) - - # print(af.sum(af.abs(af.sum(((self.f - f_initial)*0 / dt + - # 0*multiply(self.p1_center, (af.shift(self.f_left, 0, 0, -1) - self.f_left) / self.dq1) + - # multiply(-10 * self.fields_solver.cell_centered_EM_fields[0], (self.f_right_p1 - self.f_left_p1) / self.dp1)), 1 - # ) - # ) - # ) - # ) - - # self.data[self.count] = af.sum(af.abs(af.sum(((self.f - f_initial) / dt + - # multiply(self.p1_center, (af.shift(self.f_left, 0, 0, -1) - self.f_left) / self.dq1) + - # multiply(-10 * self.fields_solver.cell_centered_EM_fields_at_n[0], (self.f_right_p1 - self.f_left_p1) / self.dp1)), 0 - # ) - # ) - # ) - - # print(self.data[self.count]) - # print(af.sum(af.abs(multiply(-10 * self.fields_solver.cell_centered_EM_fields_at_n[0], (self.f[-1] - self.f[0]) / self.dp1)))) - -def update_for_instantaneous_collisions(self, dt): - - self.f = self._source(self.f, self.time_elapsed, - self.q1_center, self.q2_center, - self.p1_center, self.p2_center, self.p3_center, - self.compute_moments, - self.physical_system.params, - True - ) - return def op_fvm(self, dt): - self._communicate_f() - self._apply_bcs_f() - if(self.performance_test_flag == True): tic = af.time() - if(self.physical_system.params.instantaneous_collisions == True): - split.strang(self, timestep_fvm, update_for_instantaneous_collisions, dt) - else: - timestep_fvm(self, dt) + timestep_fvm(self, dt) af.eval(self.f) if(self.performance_test_flag == True): diff --git a/bolt/lib/nonlinear/nonlinear_solver.py b/bolt/lib/nonlinear/nonlinear_solver.py index ed46382f..2a54c2d2 100644 --- a/bolt/lib/nonlinear/nonlinear_solver.py +++ b/bolt/lib/nonlinear/nonlinear_solver.py @@ -44,13 +44,10 @@ from bolt.lib.utils.performance_timings import print_table from bolt.lib.utils.broadcasted_primitive_operations import multiply -from bolt.lib.utils.calculate_q import \ - calculate_q_center, calculate_q_left_center, \ - calculate_q_center_bot, calculate_q_left_bot +from bolt.lib.utils.calculate_q import calculate_q -from bolt.lib.utils.calculate_p import \ - calculate_p_center, calculate_p_left, \ - calculate_p_bottom, calculate_p_back +from bolt.lib.utils.calculate_p import calculate_p_center +from bolt.lib.utils.calculate_p import calculate_p_corner from .compute_moments import compute_moments as compute_moments_imported from .fields.fields import fields_solver @@ -130,8 +127,9 @@ def __init__(self, physical_system, performance_test_flag = False): af.set_device(self._comm.rank%self.physical_system.params.num_devices) # Getting number of species: - N_s = self.N_species = len(physical_system.params.mass) + N_s = self.N_species = self.physical_system.N_species + # TODO: Remove mass and charge from lib if(type(physical_system.params.mass) == list): # Having a temporary copy of the lists to copy to af.Array: list_mass = physical_system.params.mass.copy() @@ -176,8 +174,8 @@ def __init__(self, physical_system, performance_test_flag = False): self.time_apply_bcs_f = 0 self.time_communicate_f = 0 - petsc_bc_in_q1 = 'ghosted' - petsc_bc_in_q2 = 'ghosted' + petsc_bc_in_q1 = 'ghosted'; self.N_g1 = self.N_ghost + petsc_bc_in_q2 = 'ghosted'; self.N_g2 = self.N_ghost # Only for periodic boundary conditions or shearing-box boundary conditions # do the boundary conditions passed to the DA need to be changed. PETSc @@ -196,6 +194,12 @@ def __init__(self, physical_system, performance_test_flag = False): ): petsc_bc_in_q2 = 'periodic' + if(self.boundary_conditions.in_q1_left == 'none'): + petsc_bc_in_q1 = 'none'; self.N_g1 = 0 + + if(self.boundary_conditions.in_q2_bottom == 'none'): + petsc_bc_in_q2 = 'none'; self.N_g2 = 0 + if(self.boundary_conditions.in_q1_left == 'periodic'): try: assert(self.boundary_conditions.in_q1_right == 'periodic') @@ -228,6 +232,22 @@ def __init__(self, physical_system, performance_test_flag = False): both the boundaries of a particular axis' ) + if(self.boundary_conditions.in_q1_left == 'none'): + try: + assert(self.boundary_conditions.in_q1_right == 'none') + except: + raise Exception('NONE boundary conditions need to be applied to \ + both the boundaries of a particular axis' + ) + + if(self.boundary_conditions.in_q2_bottom == 'none'): + try: + assert(self.boundary_conditions.in_q2_top == 'none') + except: + raise Exception('NONE boundary conditions need to be applied to \ + both the boundaries of a particular axis' + ) + nproc_in_q1 = PETSc.DECIDE nproc_in_q2 = PETSc.DECIDE @@ -294,33 +314,48 @@ def __init__(self, physical_system, performance_test_flag = False): PETSc.Object.setName(self._glob_f, 'distribution_function') PETSc.Object.setName(self._glob_moments, 'moments') - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_f.getCorners() - # Obtaining the end coordinates for the local zone - (i_q1_end, i_q2_end) = (i_q1_start + N_q1_local - 1, i_q2_start + N_q2_local - 1) - - # Obtaining the array values of the cannonical variables: - self.q1_center, self.q2_center = \ - calculate_q_center(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, N_g, - self.dq1, self.dq2 - ) + # Indexing vars used through out + self.i_q1_start = self.N_g1; self.i_q1_end = -self.N_g1 + self.i_q2_start = self.N_g2; self.i_q2_end = -self.N_g2 + if (self.N_g1 == 0): + self.i_q1_end = 1 - self.q1_left_center, self.q2_left_center = \ - calculate_q_left_center(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, self.N_ghost, - self.dq1, self.dq2 - ) - - self.q1_center_bot, self.q2_center_bot = \ - calculate_q_center_bot(self.q1_start + i_q1_start * self.dq1, - self.q2_start + i_q2_start * self.dq2, - N_q1_local, N_q2_local, self.N_ghost, - self.dq1, self.dq2 - ) + if (self.N_g2 == 0): + self.i_q2_end = 1 + + # Get start (corner) indices of the local zone wrt global ordering and its size + ((_i_q1_start, _i_q2_start), (_N_q1_local, _N_q2_local)) = self._da_f.getCorners() + + # Coordinates of the local zone in a global coord system + self.q1_start_local = self.q1_start + _i_q1_start * self.dq1 + self.q2_start_local = self.q2_start + _i_q2_start * self.dq2 + + self.N_q1_local = _N_q1_local + self.N_q2_local = _N_q2_local + + self.N_q1_local_with_Ng = _N_q1_local + 2*self.N_g1 + self.N_q2_local_with_Ng = _N_q2_local + 2*self.N_g2 + + # Obtaining the array values of spatial coordinates: + q_left_bot, q_center_bot, q_left_center, q_center = \ + calculate_q(self.q1_start_local, + self.q2_start_local, + self.N_q1_local, self.N_q2_local, + self.N_g1, self.N_g2, + self.dq1, self.dq2 + ) + + self.q1_left_bot = q_left_bot[0] + self.q2_left_bot = q_left_bot[1] + + self.q1_center_bot = q_center_bot[0] + self.q2_center_bot = q_center_bot[1] + + self.q1_left_center = q_left_center[0] + self.q2_left_center = q_left_center[1] + + self.q1_center = q_center[0] + self.q2_center = q_center[1] self.p1_center, self.p2_center, self.p3_center = \ calculate_p_center(self.p1_start, self.p2_start, self.p3_start, @@ -328,30 +363,19 @@ def __init__(self, physical_system, performance_test_flag = False): self.dp1, self.dp2, self.dp3, ) - self.p1_left, self.p2_left, self.p3_left = \ - calculate_p_left(self.p1_start, self.p2_start, self.p3_start, - self.N_p1, self.N_p2, self.N_p3, - self.dp1, self.dp2, self.dp3, - ) - - self.p1_bottom, self.p2_bottom, self.p3_bottom = \ - calculate_p_bottom(self.p1_start, self.p2_start, self.p3_start, + self.p1_left, self.p2_bottom, self.p3_back = \ + calculate_p_corner(self.p1_start, self.p2_start, self.p3_start, self.N_p1, self.N_p2, self.N_p3, self.dp1, self.dp2, self.dp3, ) - self.p1_back, self.p2_back, self.p3_back = \ - calculate_p_back(self.p1_start, self.p2_start, self.p3_start, - self.N_p1, self.N_p2, self.N_p3, - self.dp1, self.dp2, self.dp3, - ) - - # Converting dp1, dp2, dp3 to af.Array: + # Need to convert the lists dp1, dp2, dp3 to af.Arrays for vector + # computations to work self.dp1 = af.moddims(af.to_array(np.array(self.dp1)), 1, self.N_species) self.dp2 = af.moddims(af.to_array(np.array(self.dp2)), 1, self.N_species) self.dp3 = af.moddims(af.to_array(np.array(self.dp3)), 1, self.N_species) - # Converting p_start and p_end to af.Array: + # Need to do the same for the p1_start/end lists. self.p1_start = af.moddims(af.to_array(self.p1_start), 1, self.N_species) self.p2_start = af.moddims(af.to_array(self.p2_start), 1, self.N_species) self.p3_start = af.moddims(af.to_array(self.p3_start), 1, self.N_species) @@ -360,47 +384,21 @@ def __init__(self, physical_system, performance_test_flag = False): self.p2_end = af.moddims(af.to_array(self.p2_end), 1, self.N_species) self.p3_end = af.moddims(af.to_array(self.p3_end), 1, self.N_species) + self.p2_left = self.p2_center + self.p3_left = self.p3_center + + self.p1_bottom = self.p1_center + self.p3_bottom = self.p3_center + + self.p1_back = self.p1_center + self.p2_back = self.p2_center + # Initialize according to initial condition provided by user: self._initialize(physical_system.params) # Initializing a variable to track time-elapsed: self.time_elapsed = 0 - # Applying dirichlet boundary conditions: - # Arguments that are passing to the called functions: - args = (self.f, self.time_elapsed, self.q1_center, self.q2_center, - self.p1_center, self.p2_center, self.p3_center, - self.physical_system.params - ) - - if(self.physical_system.boundary_conditions.in_q1_left == 'dirichlet'): - # If local zone includes the left physical boundary: - if(i_q1_start == 0): - self.f[:, :, :N_g] = self.boundary_conditions.\ - f_left(*args)[:, :, :N_g] - - if(self.physical_system.boundary_conditions.in_q1_right == 'dirichlet'): - # If local zone includes the right physical boundary: - if(i_q1_end == self.N_q1 - 1): - self.f[:, :, -N_g:] = self.boundary_conditions.\ - f_right(*args)[:, :, -N_g:] - - if(self.physical_system.boundary_conditions.in_q2_bottom == 'dirichlet'): - # If local zone includes the bottom physical boundary: - if(i_q2_start == 0): - self.f[:, :, :, :N_g] = self.boundary_conditions.\ - f_bot(*args)[:, :, :, :N_g] - - if(self.physical_system.boundary_conditions.in_q2_top == 'dirichlet'): - # If local zone includes the top physical boundary: - if(i_q2_end == self.N_q2 - 1): - self.f[:, :, :, -N_g:] = self.boundary_conditions.\ - f_top(*args)[:, :, :, -N_g:] - - # Assigning the value to the PETSc Vecs(for dump at t = 0): - (af.flat(self.f)).to_ndarray(self._local_f_array) - (af.flat(self.f[:, :, N_g:-N_g, N_g:-N_g])).to_ndarray(self._glob_f_array) - # Assigning the function objects to methods of the solver: self._A_q = physical_system.A_q self._C_q = physical_system.C_q @@ -418,26 +416,22 @@ def _convert_to_q_expanded(self, array): which can be used such that the computations may carried out along all dimensions necessary: - q_expanded form:(N_p1 * N_p2 * N_p3, N_s, N_q1, N_q2) - p_expanded form:(N_p1, N_p2, N_p3, N_s * N_q1 * N_q2) + q_expanded form:(N_p1 * N_p2 * N_p3, N_species, N_q1, N_q2) + p_expanded form:(N_p1, N_p2, N_p3, N_species * N_q1 * N_q2) This function converts the input array from p_expanded to q_expanded form. """ - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_f.getCorners() array = af.moddims(array, self.N_p1 * self.N_p2 * self.N_p3, self.N_species, - (N_q1_local + 2 * self.N_ghost), - (N_q2_local + 2 * self.N_ghost) + self.N_q1_local_with_Ng, + self.N_q2_local_with_Ng ) - af.eval(array) return (array) def _convert_to_p_expanded(self, array): @@ -447,24 +441,20 @@ def _convert_to_p_expanded(self, array): which can be used such that the computations may carried out along all dimensions necessary: - q_expanded form:(N_p1 * N_p2 * N_p3, N_s, N_q1, N_q2) - p_expanded form:(N_p1, N_p2, N_p3, N_s * N_q1 * N_q2) + q_expanded form:(N_p1 * N_p2 * N_p3, N_species, N_q1, N_q2) + p_expanded form:(N_p1, N_p2, N_p3, N_species * N_q1 * N_q2) This function converts the input array from q_expanded to p_expanded form. """ - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_f.getCorners() - + array = af.moddims(array, self.N_p1, self.N_p2, self.N_p3, self.N_species - * (N_q1_local + 2 * self.N_ghost) - * (N_q2_local + 2 * self.N_ghost) + * self.N_q1_local_with_Ng + * self.N_q2_local_with_Ng ) - af.eval(array) return (array) def _initialize(self, params): @@ -506,8 +496,7 @@ def _initialize(self, params): ) # Injection of solver functions into class as methods: - _communicate_f = communicate.\ - communicate_f + _communicate_f = communicate.communicate_f _apply_bcs_f = boundaries.apply_bcs_f strang_timestep = timestep.strang_step diff --git a/bolt/lib/nonlinear/tests/test_petsc_IO.py b/bolt/lib/nonlinear/tests/test_petsc_IO.py new file mode 100644 index 00000000..9ec92f03 --- /dev/null +++ b/bolt/lib/nonlinear/tests/test_petsc_IO.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Importing dependencies: +import sys, petsc4py +petsc4py.init(sys.argv) + +from petsc4py import PETSc +import numpy as np + +N_p1 = 64 +N_p2 = 64 +N_p3 = 64 +N_q1 = 96 +N_q2 = 64 + +N_ghost = 3 + +da_dump_f = PETSc.DMDA().create([N_q1, N_q2], # Spatial resolution + dof = (N_p1*N_p2*N_p3), # number of variables + stencil_width = N_ghost + ) + +glob_f = da_dump_f.createGlobalVec() # PETSc vec +PETSc.Object.setName(glob_f, 'distribution_function') + +# Get a numpy array from the PETSc vec +glob_f_array = glob_f.getArray() + +# Work with the numpy array. For example, +# time_step(glob_f_array) + +# Now dump the data. First create a PETSc Binary MPIIO viewer. +viewer = PETSc.Viewer().createBinary('binary_using_petsc.bin', 'w', comm=PETSc.COMM_WORLD) + +# Finally dump. Note that glob_f_array is linked to glob_f. +viewer(glob_f) + +# Now try with a PETSc HDF5 viewer. +viewer = PETSc.Viewer().createHDF5('hdf5_using_petsc.h5', 'w', comm=PETSc.COMM_WORLD) +viewer(glob_f) + diff --git a/bolt/lib/physical_system.py b/bolt/lib/physical_system.py index e17d64da..9fc21738 100644 --- a/bolt/lib/physical_system.py +++ b/bolt/lib/physical_system.py @@ -111,6 +111,7 @@ def __init__(self, # Finding the number of species: N_species = len(params.charge) + self.N_species = N_species try: assert(len(params.mass) == len(params.charge)) diff --git a/bolt/lib/utils/af_petsc_conversion.py b/bolt/lib/utils/af_petsc_conversion.py new file mode 100644 index 00000000..7f59d624 --- /dev/null +++ b/bolt/lib/utils/af_petsc_conversion.py @@ -0,0 +1,38 @@ +import arrayfire as af + +def af_to_petsc_glob_array(domain_metadata, af_array, glob_array): + + # domaint_metadata obj should contain the following + i_q1_start = domain_metadata.i_q1_start # start index of bulk domain + i_q1_end = domain_metadata.i_q1_end # end index, before ghost zones + + i_q2_start = domain_metadata.i_q2_start + i_q2_end = domain_metadata.i_q2_end + + tmp_array = af.flat(af_array[:, :, + i_q1_start:i_q1_end, + i_q2_start:i_q2_end + ] + ) + + tmp_array.to_ndarray(glob_array) + + return + +def petsc_local_array_to_af(domain_metadata, + N_vars_axis_0, + N_vars_axis_1, + local_array + ): + + flat_af_array = af.to_array(local_array) + + #resize to the appropriate shape + af_array = af.moddims(flat_af_array, + N_vars_axis_0, + N_vars_axis_1, + domain_metadata.N_q1_local_with_Ng, + domain_metadata.N_q2_local_with_Ng + ) + + return(af_array) diff --git a/bolt/lib/utils/calculate_p.py b/bolt/lib/utils/calculate_p.py index a69f5ec4..79b3bfbb 100644 --- a/bolt/lib/utils/calculate_p.py +++ b/bolt/lib/utils/calculate_p.py @@ -4,6 +4,32 @@ import numpy as np import arrayfire as af + +def calculate_p_corner(p1_start, p2_start, p3_start, + N_p1, N_p2, N_p3, + dp1, dp2, dp3, + ): + """ + Initializes the cannonical variables p1, p2 and p3 at the corners of the + momentum space grid zone + """ + p1_corner = af.constant(0, N_p1 * N_p2 * N_p3, len(p1_start), dtype = af.Dtype.f64) + p2_corner = af.constant(0, N_p1 * N_p2 * N_p3, len(p2_start), dtype = af.Dtype.f64) + p3_corner = af.constant(0, N_p1 * N_p2 * N_p3, len(p3_start), dtype = af.Dtype.f64) + + # Assigning for each species: + for i in range(len(p1_start)): + + p1 = p1_start[i] + (np.arange(N_p1)) * dp1[i] + p2 = p2_start[i] + (np.arange(N_p2)) * dp2[i] + p3 = p3_start[i] + (np.arange(N_p3)) * dp3[i] + + p2_corner[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[0])) + p1_corner[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[1])) + p3_corner[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[2])) + + return (p1_corner, p2_corner, p3_corner) + def calculate_p_center(p1_start, p2_start, p3_start, N_p1, N_p2, N_p3, dp1, dp2, dp3, @@ -29,69 +55,3 @@ def calculate_p_center(p1_start, p2_start, p3_start, af.eval(p1_center, p2_center, p3_center) return (p1_center, p2_center, p3_center) - -def calculate_p_left(p1_start, p2_start, p3_start, - N_p1, N_p2, N_p3, - dp1, dp2, dp3, - ): - p1_left = af.constant(0, N_p1 * N_p2 * N_p3, len(p1_start), dtype = af.Dtype.f64) - p2_left = af.constant(0, N_p1 * N_p2 * N_p3, len(p2_start), dtype = af.Dtype.f64) - p3_left = af.constant(0, N_p1 * N_p2 * N_p3, len(p3_start), dtype = af.Dtype.f64) - - # Assigning for each species: - for i in range(len(p1_start)): - - p1 = p1_start[i] + np.arange(N_p1) * dp1[i] - p2 = p2_start[i] + (0.5 + np.arange(N_p2)) * dp2[i] - p3 = p3_start[i] + (0.5 + np.arange(N_p3)) * dp3[i] - - p2_left[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[0])) - p1_left[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[1])) - p3_left[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[2])) - - af.eval(p1_left, p2_left, p3_left) - return (p1_left, p2_left, p3_left) - -def calculate_p_bottom(p1_start, p2_start, p3_start, - N_p1, N_p2, N_p3, - dp1, dp2, dp3, - ): - p1_bottom = af.constant(0, N_p1 * N_p2 * N_p3, len(p1_start), dtype = af.Dtype.f64) - p2_bottom = af.constant(0, N_p1 * N_p2 * N_p3, len(p2_start), dtype = af.Dtype.f64) - p3_bottom = af.constant(0, N_p1 * N_p2 * N_p3, len(p3_start), dtype = af.Dtype.f64) - - # Assigning for each species: - for i in range(len(p1_start)): - - p1 = p1_start[i] + (0.5 + np.arange(N_p1)) * dp1[i] - p2 = p2_start[i] + np.arange(N_p2) * dp2[i] - p3 = p3_start[i] + (0.5 + np.arange(N_p3)) * dp3[i] - - p2_bottom[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[0])) - p1_bottom[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[1])) - p3_bottom[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[2])) - - af.eval(p1_bottom, p2_bottom, p3_bottom) - return (p1_bottom, p2_bottom, p3_bottom) - -def calculate_p_back(p1_start, p2_start, p3_start, - N_p1, N_p2, N_p3, - dp1, dp2, dp3, - ): - p2_back = af.constant(0, N_p1 * N_p2 * N_p3, len(p1_start), dtype = af.Dtype.f64) - p1_back = af.constant(0, N_p1 * N_p2 * N_p3, len(p2_start), dtype = af.Dtype.f64) - p3_back = af.constant(0, N_p1 * N_p2 * N_p3, len(p3_start), dtype = af.Dtype.f64) - - # Assigning for each species: - for i in range(len(p1_start)): - - p1 = p1_start[i] + (0.5 + np.arange(N_p1)) * dp1[i] - p2 = p2_start[i] + (0.5 + np.arange(N_p2)) * dp2[i] - p3 = p3_start[i] + np.arange(N_p3) * dp3[i] - - p2_back[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[0])) - p1_back[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[1])) - p3_back[:, i] = af.flat(af.to_array(np.meshgrid(p2, p1, p3)[2])) - - af.eval(p1_back, p2_back, p3_back) - return (p1_back, p2_back, p3_back) diff --git a/bolt/lib/utils/calculate_q.py b/bolt/lib/utils/calculate_q.py index 18a106d3..e6207aad 100644 --- a/bolt/lib/utils/calculate_q.py +++ b/bolt/lib/utils/calculate_q.py @@ -4,81 +4,14 @@ import numpy as np import arrayfire as af -def calculate_q_center(q1_start, q2_start, - N_q1, N_q2, N_g, - dq1, dq2 - ): - """ - Initializes the cannonical variables q1, q2 using a centered - formulation. +def calculate_q(q1_start, q2_start, + N_q1, N_q2, + N_g1, N_g2, + dq1, dq2 + ): - Returns in q_expanded form. - """ - i_q1 = (0.5 + np.arange(-N_g, N_q1 + N_g)) - i_q2 = (0.5 + np.arange(-N_g, N_q2 + N_g)) - - q1_center = q1_start + i_q1 * dq1 - q2_center = q2_start + i_q2 * dq2 - - q2_center, q1_center = np.meshgrid(q2_center, q1_center) - q1_center, q2_center = af.to_array(q1_center), af.to_array(q2_center) - - # To bring the data structure to the default form:(N_p, N_s, N_q1, N_q2) - q1_center = af.reorder(q1_center, 3, 2, 0, 1) - q2_center = af.reorder(q2_center, 3, 2, 0, 1) - - af.eval(q1_center, q2_center) - return (q1_center, q2_center) - -def calculate_q_left_center(q1_start, q2_start, - N_q1, N_q2, N_g, - dq1, dq2 - ): - - i_q1 = np.arange(-N_g, N_q1 + N_g) - i_q2 = (0.5 + np.arange(-N_g, N_q2 + N_g)) - - q1_left_center = q1_start + i_q1 * dq1 - q2_left_center = q2_start + i_q2 * dq2 - - q2_left_center, q1_left_center = np.meshgrid(q2_left_center, q1_left_center) - q2_left_center, q1_left_center = af.to_array(q2_left_center), af.to_array(q1_left_center) - - # To bring the data structure to the default form:(N_p, N_s, N_q1, N_q2) - q1_left_center = af.reorder(q1_left_center, 3, 2, 0, 1) - q2_left_center = af.reorder(q2_left_center, 3, 2, 0, 1) - - af.eval(q1_left_center, q2_left_center) - return (q1_left_center, q2_left_center) - -def calculate_q_center_bot(q1_start, q2_start, - N_q1, N_q2, N_g, - dq1, dq2 - ): - - i_q1 = (0.5 + np.arange(-N_g, N_q1 + N_g)) - i_q2 = np.arange(-N_g, N_q2 + N_g) - - q1_center_bot = q1_start + i_q1 * dq1 - q2_center_bot = q2_start + i_q2 * dq2 - - q2_center_bot, q1_center_bot = np.meshgrid(q2_center_bot, q1_center_bot) - q2_center_bot, q1_center_bot = af.to_array(q2_center_bot), af.to_array(q1_center_bot) - - # To bring the data structure to the default form:(N_p, N_s, N_q1, N_q2) - q1_center_bot = af.reorder(q1_center_bot, 3, 2, 0, 1) - q2_center_bot = af.reorder(q2_center_bot, 3, 2, 0, 1) - - af.eval(q1_center_bot, q2_center_bot) - return (q1_center_bot, q2_center_bot) - -def calculate_q_left_bot(q1_start, q2_start, - N_q1, N_q2, N_g, - dq1, dq2 - ): - - i_q1 = np.arange(-N_g, N_q1 + N_g) - i_q2 = np.arange(-N_g, N_q2 + N_g) + i_q1 = np.arange(-N_g1, N_q1 + N_g1) + i_q2 = np.arange(-N_g2, N_q2 + N_g2) q1_left_bot = q1_start + i_q1 * dq1 q2_left_bot = q2_start + i_q2 * dq2 @@ -90,5 +23,19 @@ def calculate_q_left_bot(q1_start, q2_start, q1_left_bot = af.reorder(q1_left_bot, 3, 2, 0, 1) q2_left_bot = af.reorder(q2_left_bot, 3, 2, 0, 1) - af.eval(q1_left_bot, q2_left_bot) - return (q1_left_bot, q2_left_bot) + q1_center_bot = q1_left_bot + 0.5*dq1 + q2_center_bot = q2_left_bot + + q1_left_center = q1_left_bot + q2_left_center = q2_left_bot + 0.5*dq2 + + q1_center = q1_left_bot + 0.5*dq1 + q2_center = q2_left_bot + 0.5*dq2 + + ans = [ [q1_left_bot, q2_left_bot ], + [q1_center_bot, q2_center_bot], + [q1_left_center, q2_center_bot], + [q1_center, q2_center ] + ] + + return(ans) diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/boundary_conditions.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/boundary_conditions.py index 50c18b3a..deed2e10 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/boundary_conditions.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/boundary_conditions.py @@ -1,5 +1,5 @@ -in_q1_left = 'periodic' -in_q1_right = 'periodic' +in_q1_left = 'none' +in_q1_right = 'none' in_q2_bottom = 'periodic' in_q2_top = 'periodic' diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/domain.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/domain.py index 6d376da1..3b6e1d5e 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/domain.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/domain.py @@ -2,7 +2,7 @@ q1_start = 0 q1_end = L_x -N_q1 = 3 +N_q1 = 1 q2_start = 0 q2_end = L_y @@ -20,4 +20,4 @@ p3_end = [ v_max_e, v_max_i] N_p3 = 32 -N_ghost = 3 +N_ghost = 2 diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/initialize.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/initialize.py index 8b7336a0..35ca8e28 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/initialize.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/initialize.py @@ -47,12 +47,9 @@ def initialize_E(q1, q2, params): return(E1, E2, E3) def initialize_B(q1, q2, params): - + # Seeding with random fluctuation: - B1 = params.B1 * af.randu(q1.shape[0], q1.shape[1], - q1.shape[2], q1.shape[3], - dtype = af.Dtype.f64 - ) + B1 = params.B1 * params.random_vals B2 = 0 * q1**0 B3 = 0 * q1**0 diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py index 552543d4..eaa00f21 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py @@ -70,6 +70,7 @@ print('For electrons:', np.mean(np.array(E[:, 0, :, :]))) print('For ions:', np.mean(np.array(E[:, 1, :, :]))) +#nls.strang_timestep(dt) timing_data = [] while(abs(time_elapsed - params.t_final) > 1e-12): @@ -93,13 +94,12 @@ if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): nls.dump_distribution_function('dump_f/t=' + '%.3f'%time_elapsed) - PETSc.Sys.Print('Computing For Time =', time_elapsed / params.t0, "|t0| units(t0)") - PETSc.Sys.Print('Time Taken For Timestep =', toc - tic) + PETSc.Sys.Print('Computing for time =', time_elapsed / params.t0, 't0, time taken = ', toc - tic, 'secs') timing_data.append(toc - tic) # Writing the timing data to file: -import h5py -h5f = h5py.File('timing_data.h5', 'w') -h5f.create_dataset('time_taken', data = np.array(timing_data)) -h5f.close() +#import h5py +#h5f = h5py.File('timing_data.h5', 'w') +#h5f.create_dataset('time_taken', data = np.array(timing_data)) +#h5f.close() diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py index 2790466f..2386185e 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py @@ -90,7 +90,7 @@ gamma = 5 / 3 # adiabatic factor # Number of devices(GPUs/Accelerators) on each node: -num_devices = 4 +num_devices = 6 # Mass of electron and ion: m_e = 1 * m0 @@ -139,7 +139,7 @@ # Time parameters: N_cfl = 0.125 -t_final = 400 * t0 +t_final = 500 * t0 PETSc.Sys.Print("==================================================") PETSc.Sys.Print(" Length Scales of the System ") @@ -194,7 +194,7 @@ dt_dump_moments = dt_dump_fields = 0.1 * t0 # Restart(Set to zero for no-restart): -t_restart = 200 * t0 +t_restart = 0 * t0 # Variation of collisional-timescale parameter through phase space: @af.broadcast diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py index 79b1e810..9b1ad579 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py @@ -42,7 +42,8 @@ pl.rcParams['ytick.labelsize'] = 'medium' pl.rcParams['ytick.direction'] = 'in' -time_array = np.arange(0, params.t_final + params.dt_dump_moments, +t_final = 284 * params.t0 +time_array = np.arange(0, t_final + params.dt_dump_moments, params.dt_dump_moments ) @@ -52,7 +53,7 @@ T_min, T_max = determine_min_max('temperature', time_array) B1_min, B1_max = determine_min_max('B1', time_array) -for time_index, t0 in enumerate(time_array[::-1]): +for time_index, t0 in enumerate(time_array): print("file = ", time_index) @@ -93,13 +94,6 @@ ax2 = fig.add_subplot(2, 2, 2) ax2.plot(q2[0, :], v1[0, :, 0] / params.v0, color = 'C0') ax2.plot(q2[0, :], v1[0, :, 1] / params.v0, '--', color = 'C3') - ax2.axvline(100/24, color='black', linestyle='--') - ax2.axvline(200/24, color='black', linestyle='--') - ax2.axvline(300/24, color='black', linestyle='--') - ax2.axvline(400/24, color='black', linestyle='--') - ax2.axvline(500/24, color='black', linestyle='--') - ax2.axvline(600/24, color='black', linestyle='--') - ax2.axvline(700/24, color='black', linestyle='--') ax2.set_xlabel(r'$y(l_s)$') ax2.set_ylabel(r'$v_x(v_0)$') ax2.set_ylim([1.05 * v1_min / params.v0, 1.05 * v1_max / params.v0]) From 611a45e14a5eeba5b38cd4d34fdcdcb56b7696ec Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 10 Jun 2019 07:04:58 -0400 Subject: [PATCH 16/58] post processing file seperated out --- .../graphene/post/momentum_space_movie.py | 112 ++++++++++++++ .../graphene/post/movie.py | 142 ++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 example_problems/electronic_boltzmann/graphene/post/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/post/movie.py diff --git a/example_problems/electronic_boltzmann/graphene/post/momentum_space_movie.py b/example_problems/electronic_boltzmann/graphene/post/momentum_space_movie.py new file mode 100644 index 00000000..f82105ea --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/post/momentum_space_movie.py @@ -0,0 +1,112 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - \ + domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - \ + domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +filepath = \ +'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +distribution_function_files = np.sort(glob.glob(filepath+'/f_*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +h5f = h5py.File(distribution_function_files[0], 'r') +dist_func_background = h5f['distribution_function'][:] +h5f.close() + +q1_position = 10 +q2_position = 100 + +for file_number, dump_file in yt.parallel_objects(enumerate(distribution_function_files)): + + print("file number = ", file_number, "of ", distribution_function_files.size) + + h5f = h5py.File(distribution_function_files[file_number], 'r') + dist_func = h5f['distribution_function'][:] + h5f.close() + + + f_at_desired_q = np.reshape((dist_func - dist_func_background)[q2_position, q1_position, :], + [N_p1, N_p2] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.colorbar() + pl.savefig('images/dist_func_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/post/movie.py b/example_problems/electronic_boltzmann/graphene/post/movie.py new file mode 100644 index 00000000..44c4aaee --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/post/movie.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + From 295de2c9d5d5b64d883baadc266970d1fd4b7198 Mon Sep 17 00:00:00 2001 From: Mani Chandra Date: Tue, 11 Jun 2019 09:27:28 -0400 Subject: [PATCH 17/58] (1) Faster matplotlib post processing (2) Added parallel reduction util file (3) Added batch submit file --- bolt/lib/nonlinear/finite_volume/df_dt_fvm.py | 6 +- bolt/lib/utils/parallel_reduction_ops.py | 28 +++ .../collisionless_shock/1D/fire_job_batch.py | 53 ++++++ .../collisionless_shock/1D/job_script_gpu3001 | 4 + .../collisionless_shock/1D/main.py | 50 +++--- .../collisionless_shock/1D/params.py | 11 +- .../collisionless_shock/1D/post.py | 4 +- .../collisionless_shock/1D/post_1d.py | 166 +++++++++++++----- 8 files changed, 238 insertions(+), 84 deletions(-) create mode 100644 bolt/lib/utils/parallel_reduction_ops.py create mode 100644 example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py create mode 100644 example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/job_script_gpu3001 diff --git a/bolt/lib/nonlinear/finite_volume/df_dt_fvm.py b/bolt/lib/nonlinear/finite_volume/df_dt_fvm.py index 6e70a642..78e29dc0 100644 --- a/bolt/lib/nonlinear/finite_volume/df_dt_fvm.py +++ b/bolt/lib/nonlinear/finite_volume/df_dt_fvm.py @@ -88,9 +88,7 @@ def df_dt_fvm(f, self, term_to_return = 'all'): df_dt += - (right_flux - left_flux) / self.dq1 \ - (top_flux - bot_flux ) / self.dq2 \ - if( self.physical_system.params.source_enabled == True - and self.physical_system.params.instantaneous_collisions != True - ): + if(self.physical_system.params.source_enabled == True): df_dt += self._source(f, self.time_elapsed, self.q1_center, self.q2_center, self.p1_center, self.p2_center, self.p3_center, @@ -104,7 +102,7 @@ def df_dt_fvm(f, self, term_to_return = 'all'): if( self.physical_system.params.fields_type == 'electrodynamic' and self.fields_solver.at_n == False ): - + #TODO: Remove hybrid_model from lib and put into src if(self.physical_system.params.hybrid_model_enabled == True): communicate_fields(self.fields_solver, True) diff --git a/bolt/lib/utils/parallel_reduction_ops.py b/bolt/lib/utils/parallel_reduction_ops.py new file mode 100644 index 00000000..68fb3bec --- /dev/null +++ b/bolt/lib/utils/parallel_reduction_ops.py @@ -0,0 +1,28 @@ +import numpy as np +from petsc4py import PETSc +from mpi4py import MPI + +def global_mean(af_array): + local_mean = np.mean(np.array(af_array)) + comm = PETSc.COMM_WORLD.tompi4py() + + global_mean = comm.allreduce(sendobj=local_mean, op=MPI.SUM) \ + / comm.size + + return global_mean + +def global_min(af_array): + local_min = np.min(np.array(af_array)) + comm = PETSc.COMM_WORLD.tompi4py() + + global_min = comm.allreduce(sendobj=local_min, op=MPI.MIN) + + return global_min + +def global_max(af_array): + local_max = np.min(np.array(af_array)) + comm = PETSc.COMM_WORLD.tompi4py() + + global_max = comm.allreduce(sendobj=local_min, op=MPI.MAX) + + return global_max diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py new file mode 100644 index 00000000..8ab9f9bd --- /dev/null +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py @@ -0,0 +1,53 @@ +import os +import numpy as np + +tau_start = 0.1 #* t0 +tau_end = 100. #* t0 +tau_step = 10. #* t0 + +source_filepath = \ + '/home/mchandra/bolt_master/bolt/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D' +job_script_file = 'job_script_gpu3001' # Can also be empty +run_filepath = \ + '/home/mchandra/bolt_master/bolt/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/tau_' + +submit_jobs = False # Be careful! + +for tau in np.arange(tau_start, tau_end, tau_step): + filepath = run_filepath + str(tau) + + # If folder does not exist, make one and add all files from source folder + + if not os.path.isdir(filepath): + os.mkdir(filepath) + os.mkdir(filepath+"/dump_f") + os.mkdir(filepath+"/dump_fields") + os.mkdir(filepath+"/dump_moments") + os.mkdir(filepath+"/images") + + os.system("cp " + (source_filepath + "/*.py ") + + (source_filepath + "/" + job_script_file) + + " " + filepath + "/." + ) + + # Change required files + # Code copied from here : + # https://stackoverflow.com/questions/4454298/prepend-a-line-to-an-existing-file-in-python + + f = open(filepath + "/params.py", "r") + old = f.read() # read everything in the file + f.close() + + f = open(filepath + "/params.py", "w") + f.write("tau_collisions = " + str(tau) + " \n") + f.write(old) + f.close() + + # Schedule job after changing to run directory so that generated slurm file + # is stored in that directory + os.chdir(filepath) + + if (submit_jobs): + os.system("sbatch " + job_script_file) + + os.chdir(source_filepath) # Return to job firing script's directory diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/job_script_gpu3001 b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/job_script_gpu3001 new file mode 100644 index 00000000..3c8976fe --- /dev/null +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/job_script_gpu3001 @@ -0,0 +1,4 @@ +#!/bin/bash +#SBATCH -p gpu -n 4 --gres=gpu:4 -c1 --hint=nomultithread -t 2-00:00 +# (Note: use one MPI process per gpu, update both gres and -n together; max 6) +time mpirun python main.py > output.txt diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py index eaa00f21..fe6eff5f 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/main.py @@ -7,6 +7,7 @@ from bolt.lib.physical_system import physical_system from bolt.lib.nonlinear.nonlinear_solver import nonlinear_solver +from bolt.lib.utils.parallel_reduction_ops import global_min, global_mean import domain import boundary_conditions @@ -42,35 +43,37 @@ if(params.t_restart == 0): time_elapsed = 0 - nls.dump_distribution_function('dump_f/t=0.000') - nls.dump_moments('dump_moments/t=0.000') - nls.dump_EM_fields('dump_fields/t=0.000') + nls.dump_distribution_function('dump_f/t=0.000000') + nls.dump_moments('dump_moments/t=0.000000') + nls.dump_EM_fields('dump_fields/t=0.000000') else: time_elapsed = params.t_restart - nls.load_distribution_function('dump_f/t=' + '%.3f'%time_elapsed) - nls.load_EM_fields('dump_fields/t=' + '%.3f'%time_elapsed) + nls.load_distribution_function('dump_f/t=' + '%.6f'%time_elapsed) + nls.load_EM_fields('dump_fields/t=' + '%.6f'%time_elapsed) # Checking that the file writing intervals are greater than dt: assert(params.dt_dump_f > dt) assert(params.dt_dump_moments > dt) assert(params.dt_dump_fields > dt) -print('Printing the minimum of the distribution functions for electrons and ions:') -print('f_min_electron:', af.min(nls.f[:, 0, :, :])) -print('f_min_ion:', af.min(nls.f[:, 1, :, :])) +PETSc.Sys.Print('\nMinimum of the distribution functions for electrons and ions:') +PETSc.Sys.Print('Electrons:', global_min(nls.f[:, 0, :, :])) +PETSc.Sys.Print('Ions :', global_min(nls.f[:, 1, :, :])) +PETSc.Sys.Print('\n') -print('MEAN DENSITY') +PETSc.Sys.Print('MEAN DENSITY') n = nls.compute_moments('density') -print('For electrons:', np.mean(np.array(n[:, 0, :, :]))) -print('For ions:', np.mean(np.array(n[:, 1, :, :]))) +PETSc.Sys.Print('Electrons:', global_mean(n[:, 0, :, :])) +PETSc.Sys.Print('Ions :', global_mean(n[:, 1, :, :])) +PETSc.Sys.Print('\n') -print('MEAN ENERGY(PER UNIT MASS)') +PETSc.Sys.Print('MEAN ENERGY (PER UNIT MASS)') E = nls.compute_moments('energy') -print('For electrons:', np.mean(np.array(E[:, 0, :, :]))) -print('For ions:', np.mean(np.array(E[:, 1, :, :]))) +PETSc.Sys.Print('Electrons:', global_mean(E[:, 0, :, :])) +PETSc.Sys.Print('Ions :', global_mean(E[:, 1, :, :])) +PETSc.Sys.Print('\n') -#nls.strang_timestep(dt) timing_data = [] while(abs(time_elapsed - params.t_final) > 1e-12): @@ -88,18 +91,15 @@ if((delta_dt-dt)<1e-5): nls.strang_timestep(delta_dt) time_elapsed += delta_dt - nls.dump_moments('dump_moments/t=' + '%.3f'%time_elapsed) - nls.dump_EM_fields('dump_fields/t=' + '%.3f'%time_elapsed) + nls.dump_moments('dump_moments/t=' + '%.6f'%time_elapsed) + nls.dump_EM_fields('dump_fields/t=' + '%.6f'%time_elapsed) if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): - nls.dump_distribution_function('dump_f/t=' + '%.3f'%time_elapsed) + nls.dump_distribution_function('dump_f/t=' + '%.6f'%time_elapsed) - PETSc.Sys.Print('Computing for time =', time_elapsed / params.t0, 't0, time taken = ', toc - tic, 'secs') + PETSc.Sys.Print('Time =', format(time_elapsed / params.t0, '.4f'), + 't0, dt = ', format(dt / params.t0, '.4f'), + 't0, time taken = ', format(toc - tic, '.4f'), 'secs' + ) timing_data.append(toc - tic) - -# Writing the timing data to file: -#import h5py -#h5f = h5py.File('timing_data.h5', 'w') -#h5f.create_dataset('time_taken', data = np.array(timing_data)) -#h5f.close() diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py index 2386185e..9a9750b2 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/params.py @@ -21,10 +21,10 @@ riemann_solver_in_q = 'upwind-flux' riemann_solver_in_p = 'upwind-flux' -# Alternate set of units to consider(from discussion with Mani): +# Alternate set of units to consider: # Temperature isn't a very good base unit # Set v0 = 1(that is velocity is a base unit) -# Set T0 = 1/2 m0 v0^2 / k_B, and set T = εT0; ε = small number +# Set T0 = 1/2 m0 v0^2 / k_B, and set T = eps * T0;eps = small number # B0 is set the same way as before; B0 = sqrt(n_background * m0) * u_b # Units: l0, t0, m0, e0, n0, T0, v0, B0, E0 @@ -90,7 +90,7 @@ gamma = 5 / 3 # adiabatic factor # Number of devices(GPUs/Accelerators) on each node: -num_devices = 6 +num_devices = 4 # Mass of electron and ion: m_e = 1 * m0 @@ -183,8 +183,7 @@ # Switch for solver components: fields_enabled = True -source_enabled = False -instantaneous_collisions = False +source_enabled = True hybrid_model_enabled = False # File-writing Parameters: @@ -199,4 +198,4 @@ # Variation of collisional-timescale parameter through phase space: @af.broadcast def tau(q1, q2, p1, p2, p3): - return (np.inf * t0 * p1**0 * q1**0) + return (tau_collisions * t0 * p1**0 * q1**0) diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py index 50b542a9..9a0e3b83 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py @@ -274,7 +274,7 @@ def determine_min_max(name, time_array): if(name in ['E1', 'E2', 'E3', 'B1', 'B2', 'B3']): - fields_file = 'dump_fields/t=%.3f'%(t0) + '.bin' + fields_file = 'dump_fields/t=%.6f'%(t0) + '.bin' # Load fields viewer = PETSc.Viewer().createBinary(fields_file, @@ -288,7 +288,7 @@ def determine_min_max(name, time_array): else: - moments_file = 'dump_moments/t=%.3f'%(t0) + '.bin' + moments_file = 'dump_moments/t=%.6f'%(t0) + '.bin' # Load moments viewer = PETSc.Viewer().createBinary(moments_file, diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py index 9b1ad579..efd061ab 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_1d.py @@ -1,4 +1,5 @@ import numpy as np +import time import matplotlib matplotlib.use('agg') import pylab as pl @@ -42,23 +43,94 @@ pl.rcParams['ytick.labelsize'] = 'medium' pl.rcParams['ytick.direction'] = 'in' -t_final = 284 * params.t0 +t_final = 180 * params.t0 time_array = np.arange(0, t_final + params.dt_dump_moments, params.dt_dump_moments ) print("Determining limits...") -n_min, n_max = determine_min_max('density', time_array) -v1_min, v1_max = determine_min_max('v1', time_array) +n_min, n_max = determine_min_max('density', time_array) +v1_min, v1_max = determine_min_max('v1', time_array) T_min, T_max = determine_min_max('temperature', time_array) -B1_min, B1_max = determine_min_max('B1', time_array) +B1_min, B1_max = determine_min_max('B1', time_array) -for time_index, t0 in enumerate(time_array): +def make_plot(moments, fields, time_sim=0, + fig=None, + line1_ax1=None, line2_ax1=None, + line1_ax2=None, line2_ax2=None, + line1_ax3=None, line2_ax3=None, + line1_ax4=None, file_name=None + ): - print("file = ", time_index) + n = return_moment_to_be_plotted('density', moments) + v1 = return_moment_to_be_plotted('v1', moments) + T = return_moment_to_be_plotted('temperature', moments) + B1 = return_field_to_be_plotted('B1', fields) + + if (fig==None): + fig = pl.figure() + + ax1 = fig.add_subplot(2, 2, 1) + line1_ax1, = ax1.plot(q2[0, :], n[0, :, 0], color = 'C0', label = 'Electrons') + line2_ax1, = ax1.plot(q2[0, :], n[0, :, 1], '--', color = 'C3', label = 'Ions') + ax1.legend() + ax1.set_ylabel(r'$n$') + ax1.set_ylim([0.95 * n_min, 1.05 * n_max]) + ax1.set_xticks([]) + + ax2 = fig.add_subplot(2, 2, 2) + line1_ax2, = ax2.plot(q2[0, :], v1[0, :, 0] / params.v0, color = 'C0') + line2_ax2, = ax2.plot(q2[0, :], v1[0, :, 1] / params.v0, '--', color = 'C3') + ax2.set_ylabel(r'$v_x$') + ax2.set_ylim([1.05 * v1_min / params.v0, 1.05 * v1_max / params.v0]) + ax2.set_xticks([]) + + ax3 = fig.add_subplot(2, 2, 3) + line1_ax3, = ax3.plot(q2[0, :], T[0, :, 0] / params.T0, color = 'C0') + line2_ax3, = ax3.plot(q2[0, :], T[0, :, 1] / params.T0, '--', color = 'C3') + ax3.set_xlabel(r'$y$') + ax3.set_ylabel(r'$T$') + ax3.set_ylim([0.95 * T_min / params.T0, 1.05 * T_max / params.T0]) + + ax4 = fig.add_subplot(2, 2, 4) + line1_ax4, = ax4.plot(q2[0, :], B1[0, :] / params.B0) + ax4.set_xlabel(r'$y$') + ax4.set_ylabel(r'$B_x$') + ax4.set_ylim([0.95 * B1_min / params.B0, 1.05 * B1_max / params.B0]) + + pl.subplots_adjust(hspace=0.01) + + return (fig, line1_ax1, line2_ax1, \ + line1_ax2, line2_ax2, \ + line1_ax3, line2_ax3, \ + line1_ax4 \ + ) + + else: + + line1_ax1.set_ydata(n[0, :, 0]) + line2_ax1.set_ydata(n[0, :, 1]) + + line1_ax2.set_ydata(v1[0, :, 0] / params.v0) + line2_ax2.set_ydata(v1[0, :, 1] / params.v0) + + line1_ax3.set_ydata(T[0, :, 0] / params.T0) + line2_ax3.set_ydata(T[0, :, 1] / params.T0) + + line1_ax4.set_ydata(B1[0, :] / params.B0) + + fig.suptitle('Time = %.2f'%(time_sim / + params.t0)+r'$\omega_c^{-1}$=%.2f'%(time_sim * params.plasma_frequency)+r'$\omega_p^{-1}$') + pl.savefig(file_name) + + + +for time_index, time_sim in enumerate(time_array[:1]): + + print("Setting the figure...") - moments_file = 'dump_moments/t=%.3f'%(t0) + '.bin' - fields_file = 'dump_fields/t=%.3f'%(t0) + '.bin' + moments_file = 'dump_moments/t=%.6f'%(time_sim) + '.bin' + fields_file = 'dump_fields/t=%.6f'%(time_sim) + '.bin' # Load moments viewer = PETSc.Viewer().createBinary(moments_file, @@ -76,43 +148,43 @@ fields_vec.load(viewer) fields = da_fields.getVecArray(fields_vec) # [N_q1, N_q2, N_fields] - n = return_moment_to_be_plotted('density', moments) - v1 = return_moment_to_be_plotted('v1', moments) - T = return_moment_to_be_plotted('temperature', moments) - B1 = return_field_to_be_plotted('B1', fields) + fig, line1_ax1, line2_ax1, \ + line1_ax2, line2_ax2, \ + line1_ax3, line2_ax3, \ + line1_ax4 = make_plot(moments, fields) + +for time_index, time_sim in enumerate(time_array): + + t_start = time.time() + + moments_file = 'dump_moments/t=%.6f'%(time_sim) + '.bin' + fields_file = 'dump_fields/t=%.6f'%(time_sim) + '.bin' + + # Load moments + viewer = PETSc.Viewer().createBinary(moments_file, + PETSc.Viewer.Mode.READ, + ) + + moments_vec.load(viewer) + moments = da_moments.getVecArray(moments_vec) # [N_q1, N_q2, N_moments] - fig = pl.figure() - - ax1 = fig.add_subplot(2, 2, 1) - ax1.plot(q2[0, :], n[0, :, 0], color = 'C0', label = 'Electrons') - ax1.plot(q2[0, :], n[0, :, 1], '--', color = 'C3', label = 'Ions') - ax1.legend() - ax1.set_xlabel(r'$y(l_s)$') - ax1.set_ylabel(r'$n(n_0)$') - ax1.set_ylim([0.95 * n_min, 1.05 * n_max]) - - ax2 = fig.add_subplot(2, 2, 2) - ax2.plot(q2[0, :], v1[0, :, 0] / params.v0, color = 'C0') - ax2.plot(q2[0, :], v1[0, :, 1] / params.v0, '--', color = 'C3') - ax2.set_xlabel(r'$y(l_s)$') - ax2.set_ylabel(r'$v_x(v_0)$') - ax2.set_ylim([1.05 * v1_min / params.v0, 1.05 * v1_max / params.v0]) - - ax3 = fig.add_subplot(2, 2, 3) - ax3.plot(q2[0, :], T[0, :, 0] / params.T0, color = 'C0') - ax3.plot(q2[0, :], T[0, :, 1] / params.T0, '--', color = 'C3') - ax3.set_xlabel(r'$y(l_s)$') - ax3.set_ylabel(r'$T(T_0)$') - ax3.set_ylim([0.95 * T_min / params.T0, 1.05 * T_max / params.T0]) - - ax4 = fig.add_subplot(2, 2, 4) - ax4.plot(q2[0, :], B1[0, :] / params.B0) - ax4.set_xlabel(r'$y(l_s)$') - ax4.set_ylabel(r'$B_x(\sqrt{n_0 m_0} v_0)$') - ax4.set_ylim([0.95 * B1_min / params.B0, 1.05 * B1_max / params.B0]) - - # fig.tight_layout() - fig.suptitle('Time = %.2f'%(t0 / params.t0)+r'$\omega_c^{-1}$=%.2f'%(t0 * params.plasma_frequency)+r'$\omega_p^{-1}$') - pl.savefig('images/%04d'%time_index + '.png') - pl.close(fig) - pl.clf() + # Load fields + viewer = PETSc.Viewer().createBinary(fields_file, + PETSc.Viewer.Mode.READ, + ) + + fields_vec.load(viewer) + fields = da_fields.getVecArray(fields_vec) # [N_q1, N_q2, N_fields] + + file_name = 'images/%06d'%time_index + '.png' + make_plot(moments, fields, time_sim, fig, + line1_ax1, line2_ax1, + line1_ax2, line2_ax2, + line1_ax3, line2_ax3, + line1_ax4, file_name + ) + + print("file = ", time_index, + ", time taken = ", format(time.time() - t_start, '.4f'), " secs" + ) + From c8cf5e48ef5a40eec36c82ed0e6a583a03e65bb4 Mon Sep 17 00:00:00 2001 From: Mani Chandra Date: Mon, 17 Jun 2019 06:33:14 -0400 Subject: [PATCH 18/58] Updated fire_job_script.py --- .../collisionless_shock/1D/fire_job_batch.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py index 8ab9f9bd..88e082bd 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/fire_job_batch.py @@ -19,11 +19,11 @@ # If folder does not exist, make one and add all files from source folder if not os.path.isdir(filepath): - os.mkdir(filepath) - os.mkdir(filepath+"/dump_f") - os.mkdir(filepath+"/dump_fields") - os.mkdir(filepath+"/dump_moments") - os.mkdir(filepath+"/images") + os.makedirs(filepath) + os.makedirs(filepath+"/dump_f") + os.makedirs(filepath+"/dump_fields") + os.makedirs(filepath+"/dump_moments") + os.makedirs(filepath+"/images") os.system("cp " + (source_filepath + "/*.py ") + (source_filepath + "/" + job_script_file) From 1a7ab6ada2e8e46e0823453c2bac48a157facc12 Mon Sep 17 00:00:00 2001 From: Mani Chandra Date: Mon, 17 Jun 2019 13:02:03 -0400 Subject: [PATCH 19/58] Prototype post processing script for f. --- .../collisionless_shock/1D/post.py | 60 +++++++- .../collisionless_shock/1D/post_f.py | 139 +++++++----------- 2 files changed, 110 insertions(+), 89 deletions(-) diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py index 9a0e3b83..ffd294e2 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post.py @@ -39,8 +39,14 @@ N_q1 = domain.N_q1 N_q2 = domain.N_q2 +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 N_g = domain.N_ghost +# Finding the number of species, by looking at the number of elements in mass: +N_s = len(params.mass) + dq1 = (domain.q1_end - domain.q1_start) / N_q1 dq2 = (domain.q2_end - domain.q2_start) / N_q2 @@ -49,6 +55,21 @@ q2, q1 = np.meshgrid(q2, q1) +dp1 = []; dp2 = []; dp3 = [] +p1 = []; p2 = []; p3 = [] +for s in range(N_s): + dp1.append((domain.p1_end[s] - domain.p1_start[s]) / domain.N_p1) + dp2.append((domain.p2_end[s] - domain.p2_start[s]) / domain.N_p2) + dp3.append((domain.p3_end[s] - domain.p3_start[s]) / domain.N_p3) + + p1.append(domain.p1_start[s] + (0.5 + np.arange(domain.N_p1)) * dp1[s]) + p2.append(domain.p2_start[s] + (0.5 + np.arange(domain.N_p2)) * dp2[s]) + p3.append(domain.p3_start[s] + (0.5 + np.arange(domain.N_p3)) * dp3[s]) + +p1 = np.array(p1) +p2 = np.array(p2) +p3 = np.array(p3) + da_fields = PETSc.DMDA().create([domain.N_q1, domain.N_q2], dof=(6), stencil_width=0 ) @@ -59,9 +80,44 @@ ) moments_vec = da_moments.createGlobalVec() +da_f = PETSc.DMDA().create([domain.N_q1, domain.N_q2], + dof=(N_s*N_p1*N_p2*N_p3), stencil_width=0 + ) +f_vec = da_f.createGlobalVec() -# Finding the number of species, by looking at the number of elements in mass: -N_s = len(params.mass) +def return_f(file_name): + """ + Returns the distribution function in the desired format of + (q1, q2, p1, p2, p3), when the file that is written by the + dump_distribution_function is passed as the argument + + Parameters + ---------- + + file_name : str + Pass the name of the file that needs to be read as + a string. This should be the file that is written by + dump_distribution_function + + N_s: int + Pass the species that is in consideration. For instance when + the run is carried out for 2 species, passing N_s = 0 returns + the distribution function for the first species while N_s = 1 + returns the distribution function of the second species. + """ + + # When written using the routine dump_distribution_function, + # distribution function gets written in the format (q2, q1, p1 * p2 * p3 * Ns) + viewer = PETSc.Viewer().createBinary(file_name, + PETSc.Viewer.Mode.READ, + ) + + f_vec.load(viewer) + f = da_f.getVecArray(f_vec) # [N_q1, N_q2, N_p1*N_p2*N_p3*N_s] + + f = np.array(f[:]).reshape([N_q1, N_q2, N_s, N_p3, N_p2, N_p1]) + + return f def return_moment_to_be_plotted(name, moments): """ diff --git a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_f.py b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_f.py index ce7584e5..2e388354 100644 --- a/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_f.py +++ b/example_problems/nonrelativistic_boltzmann/instabilities/collisionless_shock/1D/post_f.py @@ -3,13 +3,14 @@ matplotlib.use('agg') import pylab as pl -import h5py import domain import params +from post import p1, p2, p3, return_f + # Optimized plot parameters to make beautiful plots: pl.rcParams['figure.figsize'] = 15, 10 -pl.rcParams['figure.dpi'] = 300 +pl.rcParams['figure.dpi'] = 100 pl.rcParams['image.cmap'] = 'jet' pl.rcParams['lines.linewidth'] = 1.5 pl.rcParams['font.family'] = 'serif' @@ -37,94 +38,58 @@ pl.rcParams['ytick.labelsize'] = 'medium' pl.rcParams['ytick.direction'] = 'in' -N_q1 = domain.N_q1 -N_q2 = domain.N_q2 -N_p1 = domain.N_p1 -N_p2 = domain.N_p2 -N_p3 = domain.N_p3 -N_g = domain.N_ghost - -dq1 = (domain.q1_end - domain.q1_start) / N_q1 -dq2 = (domain.q2_end - domain.q2_start) / N_q2 - -q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * dq1 -q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * dq2 - -def return_f_species(file_name, N_s = 0): - """ - Returns the distribution function in the desired format of - (q1, q2, p1, p2, p3), when the file that is written by the - dump_distribution_function is passed as the argument - - Parameters - ---------- - - file_name : str - Pass the name of the file that needs to be read as - a string. This should be the file that is written by - dump_distribution_function - - N_s: int - Pass the species that is in consideration. For instance when - the run is carried out for 2 species, passing N_s = 0 returns - the distribution function for the first species while N_s = 1 - returns the distribution function of the second species. - """ - - # When written using the routine dump_distribution_function, - # distribution function gets written in the format (q2, q1, p1 * p2 * p3 * Ns) - h5f = h5py.File(file_name, 'r') - # Making this (q2, q1, p1 * p2 * p3 * Ns) --> (q1, q2, p1 * p2 * p3 * Ns) - f = np.swapaxes(h5f['distribution_function'][:], 0, 1) - h5f.close() - - # Finding the distribution function for the species in consideration: - f = f[:, :, N_s * N_p1 * N_p2 * N_p3:(N_s + 1) * N_p1 * N_p2 * N_p3] - # Reshaping this from (q1, q2, p1 * p2 * p3) --> (q1, q2, p1, p2, p3) - f = f.reshape(N_q1, N_q2, N_p1, N_p2, N_p3) - - return f - -# Set this to 0 for electrons, 1 for ions: -N_s = 0 - -dp1 = (domain.p1_end[N_s] - domain.p1_start[N_s]) / N_p1 -dp2 = (domain.p2_end[N_s] - domain.p2_start[N_s]) / N_p2 -dp3 = (domain.p3_end[N_s] - domain.p3_start[N_s]) / N_p3 - -p1 = domain.p1_start[N_s] + (0.5 + np.arange(N_p1)) * dp1 -p2 = domain.p2_start[N_s] + (0.5 + np.arange(N_p2)) * dp2 -p3 = domain.p3_start[N_s] + (0.5 + np.arange(N_p3)) * dp3 - -# We want to see the distribution function variation as a function of (p1, p2) -# Hence we take a meshgrid of (p1, p2) -p1, p2 = np.meshgrid(p1, p2) - -# Declaration of the time array: -time_array = np.arange(0, params.t_final + params.dt_dump_f, - params.dt_dump_f - ) # Getting the distribution function at t = 0: # Since we want to visualize variation in (p1, p2), we will be averaging all other quantities: # (q1, q2, p1, p2, p3) --> (p1, p2) # (0, 1 , 2 , 3 , 4 ) # Hence we need to average along axes 0, 1 and 4: -f0 = np.mean(return_f_species('dump_f/t=0.000.h5', N_s), (0, 1, 4)) - -for time_index, t0 in enumerate(time_array): - - # Getting the distribution function at t = 0: - # Since we want to visualize variation in (p1, p2), we will be averaging all other quantities: - # (q1, q2, p1, p2, p3) --> (p1, p2) - # (0, 1 , 2 , 3 , 4 ) - # Hence we need to average along axes 0, 1 and 4: - f = np.mean(return_f_species('dump_f/t=%.3f'%(t0) + '.h5', N_s), (0, 1, 4)) - - pl.contourf(p1 / params.v0, p2 / params.v0, abs(f - f0), 100) - pl.xlabel(r'$v_x / v_A$') - pl.ylabel(r'$v_y / v_A$') - pl.title('Time = %.2f'%(t0 / params.t0)+r'$\omega_c^{-1}$') - pl.savefig('images_f/%04d'%time_index + '.png') - pl.colorbar() - pl.clf() +f0 = return_f('dump_f/t=0.000000.bin') # [N_q1, N_q2, N_s, N_p3, N_p2, N_p1] + +species = 0 + +fig = pl.figure(figsize=(18, 6)) +ax1 = fig.add_subplot(131) +f0_avged = np.mean(f0, (0, 1, 3)) +p2_tmp, p1_tmp = np.meshgrid(p2[species], p1[species]) +ax1.contourf(p1_tmp/params.v0, p2_tmp/params.v0, f0_avged[species].transpose(), 100) +ax1.set_aspect('equal') +ax1.set_xlabel('$v_1$') +ax1.set_ylabel('$v_2$') + +ax2 = fig.add_subplot(132) +f0_avged = np.mean(f0, (0, 1, 4)) +p3_tmp, p1_tmp = np.meshgrid(p3[species], p1[species]) +ax2.contourf(p1_tmp/params.v0, p3_tmp/params.v0, f0_avged[species].transpose(), 100) +ax2.set_yticks([]) +ax2.set_aspect('equal') +ax2.set_xlabel('$v_1$') +ax2.set_ylabel('$v_3$') + +ax3 = fig.add_subplot(133) +f0_avged = np.mean(f0, (0, 1, 5)) +p2_tmp, p3_tmp = np.meshgrid(p2[species], p3[species]) +ax3.contourf(p3_tmp / params.v0, p2_tmp / params.v0, f0_avged[species], 100) +ax3.set_yticks([]) +ax3.set_aspect('equal') +ax3.set_xlabel('$v_3$') +ax3.set_ylabel('$v_2$') + +pl.savefig('images/test_f.png') + +#for time_index, t0 in enumerate(time_array): +# +# # Getting the distribution function at t = 0: +# # Since we want to visualize variation in (p1, p2), we will be averaging all other quantities: +# # (q1, q2, p1, p2, p3) --> (p1, p2) +# # (0, 1 , 2 , 3 , 4 ) +# # Hence we need to average along axes 0, 1 and 4: +# f = np.mean(return_f_species('dump_f/t=%.3f'%(t0) + '.h5', N_s), (0, 1, 4)) +# +# pl.contourf(p1 / params.v0, p2 / params.v0, abs(f - f0), 100) +# pl.xlabel(r'$v_x / v_A$') +# pl.ylabel(r'$v_y / v_A$') +# pl.title('Time = %.2f'%(t0 / params.t0)+r'$\omega_c^{-1}$') +# pl.savefig('images_f/%04d'%time_index + '.png') +# pl.colorbar() +# pl.clf() From 1436a652aa6857af630fcb2aa751c317398d4398 Mon Sep 17 00:00:00 2001 From: Mani Chandra Date: Tue, 18 Jun 2019 11:54:26 -0400 Subject: [PATCH 20/58] Forgot to fix load.py to load .bin files. Done now. --- bolt/lib/nonlinear/file_io/load.py | 31 +++++++++++++----------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/bolt/lib/nonlinear/file_io/load.py b/bolt/lib/nonlinear/file_io/load.py index cea0f2d8..aabbc60b 100644 --- a/bolt/lib/nonlinear/file_io/load.py +++ b/bolt/lib/nonlinear/file_io/load.py @@ -5,6 +5,8 @@ import numpy as np import arrayfire as af +from bolt.lib.utils.af_petsc_conversion import petsc_local_array_to_af + def load_distribution_function(self, file_name): """ This function is used to load the distribution function from the @@ -24,22 +26,19 @@ def load_distribution_function(self, file_name): The above statemant will load the distribution function data stored in the file distribution_function.h5 into self.f """ - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self._da_f.getCorners() viewer = PETSc.Viewer().createBinary(file_name + '.bin', PETSc.Viewer.Mode.READ, comm=self._comm ) self._glob_f.load(viewer) - N_g = self.N_ghost + self._da_f.globalToLocal(self._glob_f, self._local_f) - # Reassigning back the distribution function: - self.f[:, :, N_g:-N_g, N_g:-N_g] = af.moddims(af.to_array(self._glob_f_array), - self.N_p1 * self.N_p2 * self.N_p3, - self.N_species, N_q1_local, N_q2_local - ) + self.f = petsc_local_array_to_af(self, + self.N_p1*self.N_p2*self.N_p3, + self.N_species, + self._local_f_array + ) return @@ -69,16 +68,12 @@ def load_EM_fields(self, file_name): self.fields_solver._glob_fields.load(viewer) - # Obtaining start coordinates for the local zone - # Additionally, we also obtain the size of the local zone - ((i_q1_start, i_q2_start), (N_q1_local, N_q2_local)) = self.fields_solver._da_fields.getCorners() - - N_g = self.N_ghost + self.fields_solver._da_fields.globalToLocal(self.fields_solver._glob_fields, + self.fields_solver._local_fields + ) - self.fields_solver.yee_grid_EM_fields[:, :, N_g:-N_g, N_g:-N_g] = \ - af.moddims(af.to_array(self.fields_solver._glob_fields_array), - 6, 1, N_q1_local, N_q2_local - ) + self.fields_solver.yee_grid_EM_fields = \ + petsc_local_array_to_af(self, 6, 1, self.fields_solver._local_fields_array) self.fields_solver.yee_grid_to_cell_centered_grid() return From 8a43a2c269dd5cb17ba795710eef2147bb9c5a79 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Tue, 18 Jun 2019 14:24:31 -0400 Subject: [PATCH 21/58] Added docstrings to src functions --- .../electronic_boltzmann/advection_terms.py | 132 +++++++++++++++++- .../collision_operator.py | 117 +++++++++++++++- .../electronic_boltzmann/matrix_inverse.py | 20 ++- 3 files changed, 259 insertions(+), 10 deletions(-) diff --git a/bolt/src/electronic_boltzmann/advection_terms.py b/bolt/src/electronic_boltzmann/advection_terms.py index 246e27f4..46940cb9 100644 --- a/bolt/src/electronic_boltzmann/advection_terms.py +++ b/bolt/src/electronic_boltzmann/advection_terms.py @@ -1,17 +1,85 @@ #import numpy as np import arrayfire as af -#@af.broadcast +""" +Here we define the advection terms for the +nonrelativistic Boltzmann equation. + +The equation that we are solving is: + df/dt + v_x * df/dq1 + v_y * df/dy ++ e/m * (E + v X B)_x * df/dv_x ++ e/m * (E + v X B)_y * df/dv_y ++ e/m * (E + v X B)_y * df/dv_z = 0 + +In the solver framework this can be described using: + q1 = x ; q2 = y + p1 = v1 = v_x; p2 = v2 = v_y; p3 = v3 = v_z + A_q1 = C_q1 = v_x = v1 + A_q2 = C_q2 = v_y = v2 + A_v1 = C_v1 = e/m * (E_x + v_y * B_z - v_z * B_y) = e/m * (E1 + v2 * B3 - v3 * B2) + A_v2 = C_v2 = e/m * (E_y + v_z * B_x - v_x * B_z) = e/m * (E2 + v3 * B1 - v1 * B3) + A_v3 = C_v3 = e/m * (E_z + v_x * B_y - v_y * B_x) = e/m * (E3 + v1 * B2 - v2 * B1) + +""" + def A_q(t, q1, q2, p1, p2, p3, params): - """Return the terms A_q1, A_q2.""" + """ + Return the terms A_q1, A_q2. + + Parameters: + ----------- + t : Time elapsed + + q1 : The array that holds data for the q1 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + q2 : The array that holds data for the q2 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + v1 : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v2 : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v3 : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + """ A_q1, A_q2 = params.vel_band return (A_q1, A_q2) def C_q(t, q1, q2, p1, p2, p3, params): - """Return the terms A_q1, A_q2.""" + """ + Return the terms C_q1, C_q2. + + Parameters: + ----------- + t : Time elapsed + q1 : The array that holds data for the q1 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + q2 : The array that holds data for the q2 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + v1 : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v2 : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v3 : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ C_q1, C_q2 = params.vel_band return (C_q1, C_q2) @@ -23,7 +91,34 @@ def A_p(t, q1, q2, p1, p2, p3, E1, E2, E3, B1, B2, B3, params ): - """Return the terms A_p1, A_p2 and A_p3.""" + """ + Return the terms A_v1, A_v2 and A_v3. + + Parameters: + ----------- + t : Time elapsed + + q1 : The array that holds data for the q1 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + q2 : The array that holds data for the q2 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + v1 : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v2 : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v3 : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + fields_solver: The solver object whose method get_fields() is used to + obtain the EM field quantities + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + """ e = params.charge_electron c = params.speed_of_light B3_mean = params.B3_mean @@ -40,7 +135,34 @@ def C_p(t, q1, q2, p1, p2, p3, E1, E2, E3, B1, B2, B3, params ): - """Return the terms A_p1, A_p2 and A_p3.""" + """ + Return the terms C_v1, C_v2 and C_v3. + + Parameters: + ----------- + t : Time elapsed + + q1 : The array that holds data for the q1 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + q2 : The array that holds data for the q2 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + v1 : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v2 : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + v3 : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + fields_solver: The solver object whose method get_fields() is used to + obtain the EM field quantities + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + """ e = params.charge_electron c = params.speed_of_light B3_mean = params.B3_mean diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 725b2279..3d0c7f61 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -9,6 +9,27 @@ @af.broadcast def f0_defect_constant_T(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_D + relaxation time when lattice temperature, T, is set to constant. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ mu = params.mu T = params.T @@ -79,6 +100,27 @@ def f0_defect_constant_T(f, p_x, p_y, p_z, params): # on arrays of different sizes. @af.broadcast def f0_defect(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_D + relaxation time. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ # Initial guess mu = params.mu @@ -167,6 +209,27 @@ def f0_defect(f, p_x, p_y, p_z, params): @af.broadcast def f0_ee(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_ee + relaxation time. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ # Initial guess mu_ee = params.mu_ee @@ -337,6 +400,27 @@ def f0_ee(f, p_x, p_y, p_z, params): @af.broadcast def f0_ee_constant_T(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_ee + relaxation time when lattice temperature, T, is set to constant. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ # Initial guess mu_ee = params.mu_ee @@ -503,7 +587,38 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): return(fermi_dirac) def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): - """Return BGK operator -(f-f0)/tau.""" + """ + Return RTA (Relaxation Time Approximation) operator + - (f-f0_D)/tau_D - (f-f0_ee)/tau_ee + + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + t : Time elapsed + + q1 : The array that holds data for the q1 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + q2 : The array that holds data for the q2 dimension in q-space + shape:(1, 1, N_q1, N_q2) + + p1 : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p2 : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p3 : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + flag: Toggle used for evaluating tau = 0 cases need to be evaluated. When set to True, this + function is made to return f0, thus setting f = f0 wherever tau = 0 + """ if (params.p_space_grid == 'cartesian'): p_x = p1 diff --git a/bolt/src/electronic_boltzmann/matrix_inverse.py b/bolt/src/electronic_boltzmann/matrix_inverse.py index 2c8fce0b..ea1282a3 100644 --- a/bolt/src/electronic_boltzmann/matrix_inverse.py +++ b/bolt/src/electronic_boltzmann/matrix_inverse.py @@ -2,6 +2,14 @@ import arrayfire as af def inverse_4x4_matrix(A): + """ + Return the inverse of a 4x4 matrix. + Parameters: + ----------- + A : Array to be inverted + shape:(4, 4) + """ + # TO TEST: # A_test = np.random.rand(4, 4) # A_inv_test = np.linalg.inv(A_test) @@ -38,8 +46,6 @@ def inverse_4x4_matrix(A): af.eval(det) #TODO : Raise an exception if the matrix is singular - #print ('determinant : ') - #print (det) A_inv = [[0, 0, 0, 0], [0, 0, 0, 0], @@ -194,6 +200,14 @@ def inverse_4x4_matrix(A): def inverse_3x3_matrix(A): + """ + Return the inverse of a 3x3 matrix. + Parameters: + ----------- + A : Array to be inverted + shape:(3, 3) + """ + # TO TEST: # A_test = np.random.rand(3, 3) # A_inv_test = np.linalg.inv(A_test) @@ -212,8 +226,6 @@ def inverse_3x3_matrix(A): af.eval(det) #TODO : Raise an exception if the matrix is singular - #print ('determinant : ') - #print (det) A_inv = [[0, 0, 0], \ [0, 0, 0], \ From a186acdca1026b9c185ff5d0b4c3ca13c2d4cf25 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 21 Aug 2019 06:40:30 -0400 Subject: [PATCH 22/58] Prelim check for T=0 formulation done --- .../collision_operator.py | 10 ++-- .../README.txt | 9 +++ .../domain.py | 18 +++--- .../movie.py | 60 ++++++++++++------- 4 files changed, 64 insertions(+), 33 deletions(-) create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 3d0c7f61..443d6c06 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -577,10 +577,10 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): ) N_g = domain.N_ghost print(" rank = ", params.rank, - "mu_ee = ", af.mean(params.mu_ee[0, N_g:-N_g, N_g:-N_g]), - "T_ee = ", af.mean(params.T_ee[0, N_g:-N_g, N_g:-N_g]), - " = ", af.mean(params.vel_drift_x[0, N_g:-N_g, N_g:-N_g]), - " = ", af.mean(params.vel_drift_y[0, N_g:-N_g, N_g:-N_g]) + "mu_ee = ", af.mean(params.mu_ee[0, 0, N_g:-N_g, N_g:-N_g]), + "T_ee = ", af.mean(params.T_ee[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_x[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_y[0, 0, N_g:-N_g, N_g:-N_g]) ) PETSc.Sys.Print(" ------------------") @@ -643,7 +643,7 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): # operator C_f = -( f - f0_defect_constant_T(f, p_x, p_y, p_z, params) \ ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ - -( f - f0_ee(f, p_x, p_y, p_z, params) + -( f - f0_ee_constant_T(f, p_x, p_y, p_z, params) ) / params.tau_ee(q1, q2, p_x, p_y, p_z) # When (f - f0) is NaN. Dividing by np.inf doesn't give 0 diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt new file mode 100644 index 00000000..878cc5a4 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt @@ -0,0 +1,9 @@ +To switch between polar and cartesian momentum space, the following changes need +to be made : + + +1. domain +2. params +3. initialize +4. main +5. boundary_conditions diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py index 79d6cc62..ef008f29 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py @@ -3,17 +3,17 @@ q1_start = 0. q1_end = 5.0 -N_q1 = 10 +N_q1 = 20 q2_start = 0. q2_end = 10. -N_q2 = 20 +N_q2 = 40 # If N_p1 > 1, mirror boundary conditions require p1 to be # symmetric about zero # TODO : Check and fix discrepancy between this and the claim # that p1_center = mu in polar representation -N_p1 = 16 +N_p1 = 1 # In the cartesian representation of momentum space, # p1 = p_x (magnitude of momentum) @@ -25,16 +25,18 @@ # In the 2D polar representation of momentum space, # p1 = p_r (magnitude of momentum) # p1_start and p1_end are set such that p1_center is mu -p1_start = [params.initial_mu - \ - 16.*params.boltzmann_constant*params.initial_temperature] -p1_end = [params.initial_mu + \ - 16.*params.boltzmann_constant*params.initial_temperature] +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] +p1_start = [0.5*params.initial_mu] +p1_end = [1.5*params.initial_mu] # If N_p2 > 1, mirror boundary conditions require p2 to be # symmetric about zero -N_p2 = 16 +N_p2 = 1024 # In the cartesian representation of momentum space, # p2 = p_y (magnitude of momentum) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py index 44c4aaee..79ebbf0d 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py @@ -2,6 +2,7 @@ import numpy as np from scipy.signal import correlate import glob +import os import h5py import matplotlib import matplotlib.gridspec as gridspec @@ -13,6 +14,7 @@ import petsc4py, sys; petsc4py.init(sys.argv) from petsc4py import PETSc +import PetscBinaryIO import domain import boundary_conditions @@ -58,6 +60,16 @@ q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) + source_start = params.contact_start source_end = params.contact_end @@ -86,47 +98,55 @@ sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) -filepath = \ -'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' -moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +#filepath = \ +#'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) lagrange_multiplier_files = \ np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + dt = params.dt dump_interval = params.dump_steps time_array = np.loadtxt("dump_time_array.txt") +io = PetscBinaryIO.PetscBinaryIO() + for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): print("file number = ", file_number, "of ", moment_files.size) - h5f = h5py.File(dump_file, 'r') - moments = np.swapaxes(h5f['moments'][:], 0, 1) - h5f.close() - - + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + density = moments[:, :, 0] j_x = moments[:, :, 1] j_y = moments[:, :, 2] - pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') - pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") - - + #lagrange_multipliers = \ + # io.readBinaryFile(lagrange_multiplier_files[file_number]) + #lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') lagrange_multipliers = h5f['lagrange_multipliers'][:] h5f.close() - - mu = lagrange_multipliers[:, :, 0] - mu_ee = lagrange_multipliers[:, :, 1] - T_ee = lagrange_multipliers[:, :, 2] - vel_drift_x = lagrange_multipliers[:, :, 3] - vel_drift_y = lagrange_multipliers[:, :, 4] - + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + print (vel_drift_x.shape) + print (density.shape) + + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") pl.streamplot(q1, q2, vel_drift_x, vel_drift_y, - density=2, color='blue', + density=2, color='k', linewidth=0.7, arrowsize=1 ) From db72ead9fc839de871c64dd67465907b1396837c Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 21 Aug 2019 07:14:37 -0400 Subject: [PATCH 23/58] Injecting j_x, j_y into params through RTA; Added switches to disable collision op, and switch b/w f0_ee and f0_ee_constant_T in RTA --- .../collision_operator.py | 39 +++++++++++++++---- .../README.txt | 9 +++-- .../initialize.py | 2 + .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py | 3 +- .../params.py | 9 +++-- 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 443d6c06..291161fd 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -639,18 +639,41 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): return(f) - # Activate the following lines to enable normal operation of collision - # operator - C_f = -( f - f0_defect_constant_T(f, p_x, p_y, p_z, params) \ - ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ - -( f - f0_ee_constant_T(f, p_x, p_y, p_z, params) - ) / params.tau_ee(q1, q2, p_x, p_y, p_z) + if (params.disable_collision_op): + # Activate the following line to disable the collision operator + C_f = 0.*f + else: + # Activate the following lines to enable normal operation of collision + # operator + if (params.p_dim==1) + C_f = -( f - f0_defect_constant_T(f, p_x, p_y, p_z, params) \ + ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ + -( f - f0_ee_constant_T(f, p_x, p_y, p_z, params) + ) / params.tau_ee(q1, q2, p_x, p_y, p_z) + + elif (params.p_dim==2) + C_f = -( f - f0_defect(f, p_x, p_y, p_z, params) \ + ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ + -( f - f0_ee_constant_T(f, p_x, p_y, p_z, params) + ) / params.tau_ee(q1, q2, p_x, p_y, p_z) # When (f - f0) is NaN. Dividing by np.inf doesn't give 0 # TODO: WORKAROUND + + + # Inject j_x and j_y into params + + # TODO : Multiply by dp1*dp2 and the phase space degeneracy factor + # (4./(2.*np.pi*params.h_bar)**2.) + + multiply = lambda a, b:a*b + + print ('f : ',f.shape) + print ('p_x : ', p_x.shape) + + params.j_x = af.sum(af.broadcast(multiply, f, p_x), 0) + params.j_y = af.sum(af.broadcast(multiply, f, p_y), 0) - # Activate the following line to disable the collision operator - #C_f = 0.*f af.eval(C_f) return(C_f) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt index 878cc5a4..5df858c4 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt @@ -3,7 +3,10 @@ to be made : 1. domain + - Change p2_start, p2_end and N_p2 2. params -3. initialize -4. main -5. boundary_conditions + - Change p_space_grid + - Change p_dim +3. initialize : No change +4. main : No change +5. boundary_conditions : No change diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py index fd1a0ffb..fb8e8c88 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/initialize.py @@ -22,6 +22,8 @@ def initialize_f(q1, q2, p1, p2, p3, params): params.T_ee = params.T.copy() params.vel_drift_x = 0.*q1 + 0e-3 params.vel_drift_y = 0.*q1 + 0e-3 + params.j_x = 0.*q1 + params.j_y = 0.*q1 params.E_band = params.band_energy(p1, p2) params.vel_band = params.band_velocity(p1, p2) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py index e40356b1..bbb89313 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py @@ -97,7 +97,8 @@ nls.dump_aux_arrays([params.mu, params.mu_ee, params.T_ee, - params.vel_drift_x, params.vel_drift_y], + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], 'lagrange_multipliers', 'dumps/lagrange_multipliers_' + file_number ) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 525dc12f..1fdeb0ab 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -2,8 +2,9 @@ import arrayfire as af instantaneous_collisions = False #TODO : Remove from lib -hybrid_model_enabled = False #TODO : Remove from lib -source_enabled = True +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False fields_enabled = False # Can be defined as 'electrostatic', 'user-defined'. @@ -47,7 +48,7 @@ t_final = 200. # ps # Dimensionality considered in velocity space: -p_dim = 2 +p_dim = 1 p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids # Set p-space start and end points accordingly in domain.py @@ -89,6 +90,8 @@ T_ee = None # Electron temperature used in the e-e operator vel_drift_x = None vel_drift_y = None +j_x = None +j_y = None phi = None # Electric potential in the plane of graphene sheet # Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) From d15af885e88ac58a25feb33b7217a6b65a025692 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 28 Aug 2019 15:27:18 +0530 Subject: [PATCH 24/58] Bugfix in collision_operator.py --- bolt/src/electronic_boltzmann/collision_operator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 291161fd..0c55942c 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -645,13 +645,13 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): else: # Activate the following lines to enable normal operation of collision # operator - if (params.p_dim==1) + if (params.p_dim==1): C_f = -( f - f0_defect_constant_T(f, p_x, p_y, p_z, params) \ ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ -( f - f0_ee_constant_T(f, p_x, p_y, p_z, params) ) / params.tau_ee(q1, q2, p_x, p_y, p_z) - elif (params.p_dim==2) + elif (params.p_dim==2): C_f = -( f - f0_defect(f, p_x, p_y, p_z, params) \ ) / params.tau_defect(q1, q2, p_x, p_y, p_z) \ -( f - f0_ee_constant_T(f, p_x, p_y, p_z, params) From de62a04005625375c8fea4522e89901018b71390 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 9 Oct 2019 08:05:52 -0400 Subject: [PATCH 25/58] added distribution function script for binary output --- .../momentum_space_movie.py | 114 +++++++++++------- 1 file changed, 68 insertions(+), 46 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py index f82105ea..1de644d7 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie.py @@ -3,6 +3,7 @@ from scipy.signal import correlate import glob import h5py +import os import matplotlib import matplotlib.gridspec as gridspec import matplotlib.patches as patches @@ -13,12 +14,9 @@ import petsc4py, sys; petsc4py.init(sys.argv) from petsc4py import PETSc +import PetscBinaryIO import domain -import boundary_conditions -import params -import initialize - # Optimized plot parameters to make beautiful plots: pl.rcParams['figure.figsize'] = 8, 8 @@ -53,60 +51,84 @@ N_q1 = domain.N_q1 N_q2 = domain.N_q2 -q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - \ - domain.q1_start)/N_q1 -q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - \ - domain.q2_start)/N_q2 +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) N_p1 = domain.N_p1 N_p2 = domain.N_p2 -p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ - domain.p1_start[0])/N_p1 -p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ - domain.p2_start[0])/N_p2 +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end -p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 -filepath = \ -'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' -moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) -lagrange_multiplier_files = \ - np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) -distribution_function_files = np.sort(glob.glob(filepath+'/f_*.h5')) +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) -dt = params.dt -dump_interval = params.dump_steps +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) -time_array = np.loadtxt("dump_time_array.txt") +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) -h5f = h5py.File(distribution_function_files[0], 'r') -dist_func_background = h5f['distribution_function'][:] -h5f.close() +io = PetscBinaryIO.PetscBinaryIO() -q1_position = 10 -q2_position = 100 +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q1_position, q2_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') -for file_number, dump_file in yt.parallel_objects(enumerate(distribution_function_files)): + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) - print("file number = ", file_number, "of ", distribution_function_files.size) - - h5f = h5py.File(distribution_function_files[file_number], 'r') - dist_func = h5f['distribution_function'][:] - h5f.close() - - - f_at_desired_q = np.reshape((dist_func - dist_func_background)[q2_position, q1_position, :], - [N_p1, N_p2] - ) - pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') - pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") - pl.xlabel('$p_x$') - pl.ylabel('$p_y$') - pl.gca().set_aspect('equal') - pl.colorbar() - pl.savefig('images/dist_func_' + '%06d'%file_number + '.png') - pl.clf() + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() From a50c40ffdd253906cf6cebf820c94b43a9d4b60e Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 9 Oct 2019 08:11:17 -0400 Subject: [PATCH 26/58] Udated readme and domain for 1d polar --- .../graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt | 4 ++-- .../graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt index 5df858c4..ddb0d8b5 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/README.txt @@ -1,4 +1,4 @@ -To switch between polar and cartesian momentum space, the following changes need +To switch between 1D/2D polar and cartesian momentum space, the following changes need to be made : @@ -6,7 +6,7 @@ to be made : - Change p2_start, p2_end and N_p2 2. params - Change p_space_grid - - Change p_dim + - Change p_dim (if switching between 1D and 2D representation in p-space) 3. initialize : No change 4. main : No change 5. boundary_conditions : No change diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py index ef008f29..bb840d77 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/domain.py @@ -13,11 +13,13 @@ # symmetric about zero # TODO : Check and fix discrepancy between this and the claim # that p1_center = mu in polar representation -N_p1 = 1 +N_p1 = 1 # Set equal to 1 for 1D polar # In the cartesian representation of momentum space, # p1 = p_x (magnitude of momentum) # p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space #p1_start = [-0.04] #p1_end = [0.04] @@ -25,11 +27,14 @@ # In the 2D polar representation of momentum space, # p1 = p_r (magnitude of momentum) # p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space #p1_start = [params.initial_mu - \ # 16.*params.boltzmann_constant*params.initial_temperature] #p1_end = [params.initial_mu + \ # 16.*params.boltzmann_constant*params.initial_temperature] +# Uncomment the following for the 1D polar representation of momentum space p1_start = [0.5*params.initial_mu] p1_end = [1.5*params.initial_mu] From fb9fa4b362bc291a3e3535c975df28bdf264be55 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 9 Oct 2019 10:17:18 -0400 Subject: [PATCH 27/58] dump_aux_array in binary IO, zero T momentum space plot script added --- bolt/lib/nonlinear/file_io/dump.py | 2 +- .../momentum_space_movie_zero_T.py | 160 ++++++++++++++++++ .../movie.py | 14 +- 3 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index 72cc65c8..4efc19b7 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -35,7 +35,7 @@ def dump_aux_arrays(self, arrays, name, file_name): af.flat(array_to_dump).to_ndarray(self._glob_aux_array) PETSc.Object.setName(self._glob_aux, name) - viewer = PETSc.Viewer().createHDF5(file_name + '.h5', 'w', comm=self._comm) + viewer = PETSc.Viewer().createBinary(file_name + '.bin', 'w', comm=self._comm) viewer(self._glob_aux) def dump_moments(self, file_name): diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..74a2cdcb --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py @@ -0,0 +1,160 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q1_position, q2_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q1_position, q2_position, :, :])) + norm_factor = np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q1_position, q2_position, :, :],\ + [N_p2, N_p1])/norm_factor + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=2) + pl.plot(x_bg, y_bg, color='k', alpha=0.4, lw=2) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + #pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py index 79ebbf0d..dbae5848 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/movie.py @@ -103,7 +103,7 @@ filepath = os.getcwd() + "/dumps" moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) lagrange_multiplier_files = \ - np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + np.sort(glob.glob(filepath+'/lagrange_multipliers*.bin')) print ("moment files : ", moment_files.size) print ("lagrange multiplier files : ", lagrange_multiplier_files.size) @@ -126,12 +126,12 @@ j_x = moments[:, :, 1] j_y = moments[:, :, 2] - #lagrange_multipliers = \ - # io.readBinaryFile(lagrange_multiplier_files[file_number]) - #lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) - h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') - lagrange_multipliers = h5f['lagrange_multipliers'][:] - h5f.close() + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 7) + #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + #lagrange_multipliers = h5f['lagrange_multipliers'][:] + #h5f.close() mu = lagrange_multipliers[:, :, 0] mu_ee = lagrange_multipliers[:, :, 1] From aeae0fd20342daf65482af6c142991c418b5b0c9 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 10 Oct 2019 06:55:00 -0400 Subject: [PATCH 28/58] Fixed discrepancy in momentum space plot script --- .../momentum_space_movie_zero_T.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py index 74a2cdcb..664bb2ce 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/momentum_space_movie_zero_T.py @@ -96,12 +96,12 @@ dist_func_background = io.readBinaryFile(dist_func_bg_file) #dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) -dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) dist_func = io.readBinaryFile(dist_func_file) print (dist_func[0].shape) -dist_func = dist_func[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) N = 7 @@ -111,12 +111,12 @@ q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) - a = np.max((dist_func - dist_func_background)[q1_position, q2_position, :, :]) - b = np.abs(np.min((dist_func - dist_func_background)[q1_position, q2_position, :, :])) + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) norm_factor = np.maximum(a, b) f_at_desired_q = \ np.reshape((dist_func-\ - dist_func_background)[q1_position, q2_position, :, :],\ + dist_func_background)[q2_position, q1_position, :, :],\ [N_p2, N_p1])/norm_factor np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) @@ -127,7 +127,7 @@ # [N_p2, N_p1] # ) - print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) print ("norm : ", norm_factor) @@ -142,8 +142,8 @@ print ('p2 : ', p2.shape) #pl.plot(p2, f_at_desired_q) - pl.plot(x, y, color='r', linestyle = '-', lw=2) - pl.plot(x_bg, y_bg, color='k', alpha=0.4, lw=2) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) @@ -154,7 +154,11 @@ #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") pl.xlabel('$p_x$') pl.ylabel('$p_y$') - #pl.gca().set_aspect('equal') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) pl.clf() From f51fad51f9c0a3947c55a7aa529d7c2a4571f2b6 Mon Sep 17 00:00:00 2001 From: Manichandra Morampudi Date: Thu, 31 Oct 2019 12:37:07 -0600 Subject: [PATCH 29/58] Example height scaling folder with lanl submit file --- .../README.txt | 12 + .../boundary_conditions.py | 107 +++++ .../domain.py | 65 +++ .../dump_time_array.txt | 1 + .../edge_potential.py | 161 +++++++ .../enstrophy.py | 142 ++++++ .../initialize.py | 67 +++ .../job_script | 4 + .../main.py | 134 ++++++ .../momentum_space_movie.py | 134 ++++++ .../momentum_space_movie_zero_T.py | 160 +++++++ .../movie.py | 162 +++++++ .../params.py | 167 +++++++ .../phase_vs_y.py | 180 ++++++++ .../post.py | 422 ++++++++++++++++++ .../signals.py | 171 +++++++ .../submit_post | 29 ++ .../vorticity.py | 136 ++++++ 18 files changed, 2254 insertions(+) create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/submit_post create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt new file mode 100644 index 00000000..ddb0d8b5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt @@ -0,0 +1,12 @@ +To switch between 1D/2D polar and cartesian momentum space, the following changes need +to be made : + + +1. domain + - Change p2_start, p2_end and N_p2 +2. params + - Change p_space_grid + - Change p_dim (if switching between 1D and 2D representation in p-space) +3. initialize : No change +4. main : No change +5. boundary_conditions : No change diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py new file mode 100644 index 00000000..762f5e79 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py @@ -0,0 +1,107 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror+dirichlet' +in_q1_right = 'mirror+dirichlet' +in_q2_bottom = 'mirror' +in_q2_top = 'mirror' + +@af.broadcast +def f_left(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_in = params.vel_drift_x_in + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_right(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_out = params.vel_drift_x_out + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py new file mode 100644 index 00000000..7d095de5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py @@ -0,0 +1,65 @@ +import numpy as np +import params + +q1_start = 0. +q1_end = 1.0 +N_q1 = 72 + +q2_start = 0. +q2_end = 5.0 +N_q2 = 360 + +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation +N_p1 = 1 # Set equal to 1 for 1D polar + +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space +#p1_start = [-0.04] +#p1_end = [0.04] + + +# In the 2D polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] + +# Uncomment the following for the 1D polar representation of momentum space +p1_start = [0.5*params.initial_mu] +p1_end = [1.5*params.initial_mu] + + +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero +N_p2 = 8192 + +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +#p2_start = [-0.04] +#p2_end = [0.04] + +# In the 2D polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +p2_start = [-np.pi] +p2_end = [np.pi] + +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt new file mode 100644 index 00000000..05955907 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt @@ -0,0 +1 @@ +0.000000000000000000e+00 diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py new file mode 100644 index 00000000..b50b3bf5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py @@ -0,0 +1,161 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#print("Reading sensor signal...") +print("Loading data...") +density = [] +edge_density = [] +for file_number, dump_file in enumerate(moment_files): + + print("File number = ", file_number, ' of ', moment_files.size) + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density.append(moments[:, :, 0]) + edge_density.append(density[file_number][0, sensor_1_left_indices]) + +density = np.array(density) +edge_density = np.array(edge_density) + +mean_density = np.mean(density) +max_density = np.max(density) +min_density = np.min(density) + +np.savetxt("edge_density.txt", edge_density) + +print("Dumping data...") +for file_number in yt.parallel_objects(range(density.shape[0])): + + print("File number = ", file_number, ' of ', moment_files.size) + + pl.semilogy(q2[sensor_1_left_indices], + density[file_number][0, sensor_1_left_indices], + ) + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.title(r'Time = ' + "%.2f"%(file_number*dt*dump_interval) + " ps") + + pl.xlim([sensor_1_left_start, sensor_1_left_end]) + #pl.ylim([min_density-mean_density, max_density-mean_density]) + #pl.ylim([0., np.log(max_density)]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$ ps, $\\tau_\mathrm{mr} = 3.0$ ps') + #pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.savefig('images/density_' + '%06d'%file_number + '.png') + pl.clf() + + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py new file mode 100644 index 00000000..fb8e8c88 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py @@ -0,0 +1,67 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 0.*q1 + params.vel_drift_y = 0.*q1 + params.phi = 0.*q1 + + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + params.vel_drift_x = 0.*q1 + 0e-3 + params.vel_drift_y = 0.*q1 + 0e-3 + params.j_x = 0.*q1 + params.j_y = 0.*q1 + + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + E_upper = params.E_band + params.charge[0]*params.phi + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + f = (1./(af.exp( (E_upper - params.vel_drift_x*p_x + - params.vel_drift_y*p_y + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script new file mode 100644 index 00000000..75c49d28 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script @@ -0,0 +1,4 @@ +#!/bin/bash +#SBATCH -p gpu -n 4 --gres=gpu:4 -c1 --hint=nomultithread -t 2-00:00 +# (Note: use one MPI process per gpu, update both gres and -n together; max 6) +time mpirun python main.py -snes_monitor -snes_max_it 1 -snes_lag_jacobian_persists TRUE -snes_lag_jacobian 1000000 -snes_atol 1e-50 -snes_rtol 1e-50 > output.txt diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py new file mode 100644 index 00000000..3742ff81 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py @@ -0,0 +1,134 @@ +import sys +import arrayfire as af +import numpy as np +import pylab as pl +#import h5py +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +#from bolt.lib.nonlinear.fields.fields.fields \ +# import fields_solver.compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moment_defs + ) + +# Time parameters: +dt = params.dt +t_final = params.t_final +params.current_time = t0 = 0.0 +params.time_step = time_step = 0 +dump_counter = 0 +dump_time_array = [] + +N_g = domain.N_ghost + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +params.rank = nls._comm.rank + +if (params.restart): + nls.load_distribution_function(params.restart_file) + +density = nls.compute_moments('density') +print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + +nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) +while t0 < t_final: + + # Refine to machine error + if (time_step==0): + params.collision_nonlinear_iters = 10 + else: + params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters + + dump_steps = params.dump_steps + # Uncomment if need to dump more frequently during a desired time interval + #if (params.current_time > 149. and params.current_time < 154): + # dump_steps = 1 + #else: + # dump_steps = params.dump_steps + if (time_step%dump_steps==0): + file_number = '%06d'%dump_counter + dump_counter = dump_counter + 1 + dump_time_array.append(params.current_time) + PETSc.Sys.Print("=====================================================") + PETSc.Sys.Print("Dumping data at time step =", time_step, + ", file number =", file_number + ) + PETSc.Sys.Print("=====================================================") + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + + nls.dump_moments('dumps/moments_' + file_number) + + if (time_step==0): + nls.dump_distribution_function('dumps/f_' + file_number) + + #nls.dump_distribution_function('dumps/f_' + file_number) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], + 'lagrange_multipliers', + 'dumps/lagrange_multipliers_' + file_number + ) + + dt_force_constraint = 0. +# dt_force_constraint = \ +# 0.5 * np.min(nls.dp1, nls.dp2) \ +# / np.max((af.max(nls.cell_centered_EM_fields[0]), +# af.max(nls.cell_centered_EM_fields[1]) +# ) +# ) + + PETSc.Sys.Print("Time step =", time_step, ", Time =", t0) + + nls.strang_timestep(dt) + t0 = t0 + dt + time_step = time_step + 1 + params.time_step = time_step + params.current_time = t0 + + # Floors + nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) + + density = nls.compute_moments('density') + print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + PETSc.Sys.Print("--------------------\n") + +nls.dump_distribution_function('dumps/f_laststep') diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py new file mode 100644 index 00000000..1de644d7 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py @@ -0,0 +1,134 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q1_position, q2_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..74a2cdcb --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py @@ -0,0 +1,160 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q1_position, q2_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q1_position, q2_position, :, :])) + norm_factor = np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q1_position, q2_position, :, :],\ + [N_p2, N_p1])/norm_factor + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=2) + pl.plot(x_bg, y_bg, color='k', alpha=0.4, lw=2) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + #pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py new file mode 100644 index 00000000..dbae5848 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py @@ -0,0 +1,162 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#filepath = \ +#'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 7) + #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + #lagrange_multipliers = h5f['lagrange_multipliers'][:] + #h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + print (vel_drift_x.shape) + print (density.shape) + + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py new file mode 100644 index 00000000..62b9a907 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py @@ -0,0 +1,167 @@ +import numpy as np +import arrayfire as af + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +# Restart(Set to zero for no-restart): +restart = 0 +restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/f_eqbm.h5' +phi_restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/phi_eqbm.h5' +electrostatic_solver_every_nth_step = 1000000 +solve_for_equilibrium = 0 + + +# File-writing Parameters: +dump_steps = 5 + +# Time parameters: +dt = 0.025/4 # ps +t_final = 300. # ps + +# Dimensionality considered in velocity space: +p_dim = 1 +p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 4 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 0.0 # um +contact_end = 0.25 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 12e-5 +initial_mu = 0.015 +vel_drift_x_in = 1e-3*fermi_velocity +vel_drift_x_out = 1e-3*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +j_x = None +j_y = None +phi = None # Electric potential in the plane of graphene sheet + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + +def band_energy(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + + E_upper = p*fermi_velocity + + af.eval(E_upper) + return(E_upper) + +def band_velocity(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + v_f = fermi_velocity + + upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] + + af.eval(upper_band_velocity[0], upper_band_velocity[1]) + return(upper_band_velocity) + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py new file mode 100644 index 00000000..62104908 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py @@ -0,0 +1,171 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +# Calculate the phase difference between input_signal_array and sensor_normalized +# Code copied from : +# https:/stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves + +corr = correlate(input_normalized, sensor_normalized) +nsamples = input_normalized.size +time_corr = time_array[half_time:] +dt_corr = np.linspace(-time_corr[-1] + time_corr[0], + time_corr[-1] - time_corr[0], 2*nsamples-1) +time_shift = dt_corr[corr.argmax()] + +#Force the phase shift to be in [-pi:pi] +period = 1./AC_freq +phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) + +pl.plot(time_array, input_signal_array) +pl.plot(time_array, sensor_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=1) +pl.text(135, 1.14, '$\phi : %.2f \; rad$' %phase_diff) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-1.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 0.5$ ps') +pl.savefig('images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/submit_post b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/submit_post new file mode 100644 index 00000000..f27a05ef --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/submit_post @@ -0,0 +1,29 @@ +#!/bin/bash +#SBATCH -t 16:00:00 # walltime +#SBATCH -N 8 # Number of nodes +#SBATCH -n 32 # Number of MPI ranks +#SBATCH -o out_%j # Pathname of stdout +#SBATCH -e err_%j # Pathname of stderr +#SBATCH -A w19_mcpgpu # Allocation +#SBATCH --qos=standard # QoS (standard, interactive, standby, large*, long*, high*) + # See https://hpc.lanl.gov/scheduling_policies +#SBATCH --mail-user=mc0710@gmail.com +#SBATCH --mail-type=BEGIN +#SBATCH --mail-type=END +#SBATCH --mail-type=FAIL + +module list +pwd +date + +# Arrayfire library +export AF_PATH=/usr/projects/p18_ebhlight3d/arrayfire/arrayfire_install +export PETSC_DIR=/usr/projects/p18_ebhlight3d/petsc_3.10.0_install +export LD_LIBRARY_PATH=$AF_PATH/lib64:$LD_LIBRARY_PATH + +# Bolt as library +export PYTHONPATH=$PYTHONPATH:/users/manic/bolt_master + +source activate /usr/projects/p18_ebhlight3d/bolt_env_2019.1/ + +srun python main.py diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.0_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() + From a90d0958f7ed5f924835a6f0068f99fcf2e5add1 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 6 Feb 2020 13:07:38 +0530 Subject: [PATCH 30/58] Added Ben's auto restart code to main. Util files to be updated --- .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py | 125 +++++++++++------- .../params.py | 9 ++ 2 files changed, 87 insertions(+), 47 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py index bbb89313..f65ebb15 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py @@ -1,10 +1,11 @@ -import sys +import os import arrayfire as af import numpy as np -import pylab as pl -import h5py +import math import petsc4py, sys; petsc4py.init(sys.argv) from petsc4py import PETSc +from mpi4py import MPI +MPI.WTIME_IS_GLOBAL=True from bolt.lib.physical_system import physical_system @@ -12,18 +13,30 @@ import nonlinear_solver #from bolt.lib.nonlinear.fields.fields.fields \ # import fields_solver.compute_electrostatic_fields +from bolt.lib.utils.restart_latest import latest_output, format_time import domain import boundary_conditions -import params import initialize +import params -import bolt.src.electronic_boltzmann.advection_terms as advection_terms - +import bolt.src.electronic_boltzmann.advection_terms \ + as advection_terms import bolt.src.electronic_boltzmann.collision_operator \ as collision_operator +import bolt.src.electronic_boltzmann.moment_defs \ + as moment_defs + -import bolt.src.electronic_boltzmann.moment_defs as moment_defs +# Create required folders if they do not exist already +if not os.path.isdir("dump_f"): + os.system("mkdir dump_f") +if not os.path.isdir("dump_moments"): + os.system("mkdir dump_moments") +if not os.path.isdir("dump_lagrange_multipliers"): + os.system("mkdir dump_lagrange_multipliers") +if not os.path.isdir("images"): + os.system("mkdir images") # Defining the physical system to be solved: @@ -36,6 +49,11 @@ moment_defs ) +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +N_g = domain.N_ghost +params.rank = nls._comm.rank + # Time parameters: dt = params.dt t_final = params.t_final @@ -44,14 +62,43 @@ dump_counter = 0 dump_time_array = [] -N_g = domain.N_ghost -# Declaring a nonlinear system object which will evolve the defined physical system: -nls = nonlinear_solver(system) -params.rank = nls._comm.rank +using_latest_restart = False +if(params.latest_restart == True): + latest_f, time_elapsed = latest_output('') + print(time_elapsed) + if(latest_f is not None and time_elapsed is not None): + nls.load_distribution_function(latest_f) + using_latest_restart = True -if (params.restart): - nls.load_distribution_function(params.restart_file) + +if using_latest_restart == False: + if(params.t_restart == 0 or params.latest_restart == True): + time_elapsed = 0 + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + else: + time_elapsed = params.t_restart + formatted_time = format_time(time_elapsed) + nls.load_distribution_function('dump_f/t=' + formatted_time) + +# Checking that the file writing intervals are greater than dt: +assert(params.dt_dump_f > dt) +assert(params.dt_dump_moments > dt) +assert(params.dt_dump_fields > dt) + + +#if (params.restart): +# nls.load_distribution_function(params.restart_file) density = nls.compute_moments('density') print("rank = ", params.rank, "\n", @@ -62,7 +109,7 @@ ) nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) -while t0 < t_final: +while(t0 < t_final): # Refine to machine error if (time_step==0): @@ -71,46 +118,30 @@ params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters dump_steps = params.dump_steps - # Uncomment if need to dump more frequently during a desired time interval - #if (params.current_time > 149. and params.current_time < 154): - # dump_steps = 1 - #else: - # dump_steps = params.dump_steps - if (time_step%dump_steps==0): - file_number = '%06d'%dump_counter - dump_counter = dump_counter + 1 - dump_time_array.append(params.current_time) - PETSc.Sys.Print("=====================================================") - PETSc.Sys.Print("Dumping data at time step =", time_step, - ", file number =", file_number - ) - PETSc.Sys.Print("=====================================================") - if (params.rank==0): - np.savetxt("dump_time_array.txt", dump_time_array) - - nls.dump_moments('dumps/moments_' + file_number) - - if (time_step==0): - nls.dump_distribution_function('dumps/f_' + file_number) - - #nls.dump_distribution_function('dumps/f_' + file_number) + + if(params.dt_dump_moments != 0): + # We step by delta_dt to get the values at dt_dump + delta_dt = (1 - math.modf(time_elapsed/params.dt_dump_moments)[0]) \ + * params.dt_dump_moments + + if((delta_dt-dt)<1e-5): + nls.strang_timestep(delta_dt) + time_elapsed += delta_dt + formatted_time = format_time(time_elapsed) + nls.dump_moments('dump_moments/t=' + formatted_time) + + if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) nls.dump_aux_arrays([params.mu, params.mu_ee, params.T_ee, params.vel_drift_x, params.vel_drift_y, params.j_x, params.j_y], 'lagrange_multipliers', - 'dumps/lagrange_multipliers_' + file_number + 'dump_lagrange_multipliers/t=' + formatted_time ) - dt_force_constraint = 0. -# dt_force_constraint = \ -# 0.5 * np.min(nls.dp1, nls.dp2) \ -# / np.max((af.max(nls.cell_centered_EM_fields[0]), -# af.max(nls.cell_centered_EM_fields[1]) -# ) -# ) - PETSc.Sys.Print("Time step =", time_step, ", Time =", t0) nls.strang_timestep(dt) @@ -131,4 +162,4 @@ ) PETSc.Sys.Print("--------------------\n") -nls.dump_distribution_function('dumps/f_laststep') +nls.dump_distribution_function('dump_f/f_laststep') diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 1fdeb0ab..633de285 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -42,6 +42,11 @@ # File-writing Parameters: dump_steps = 10 +# Set to zero for no file-writing +dt_dump_f = 100 #ps +# ALWAYS set dump moments and dump fields at same frequency: +dt_dump_moments = dt_dump_fields = 10 #ps + # Time parameters: dt = 0.025/2 # ps @@ -151,6 +156,10 @@ def band_velocity(p1, p2): af.eval(upper_band_velocity[0], upper_band_velocity[1]) return(upper_band_velocity) +# Restart(Set to zero for no-restart): +latest_restart = True +t_restart = 0 + @af.broadcast def fermi_dirac(mu, E_band): From c66818724c5d59ec4552b06d7a244518ff1c9c34 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 6 Feb 2020 13:21:24 +0530 Subject: [PATCH 31/58] Added utils required for latest_restart --- bolt/lib/utils/restart_latest.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 bolt/lib/utils/restart_latest.py diff --git a/bolt/lib/utils/restart_latest.py b/bolt/lib/utils/restart_latest.py new file mode 100644 index 00000000..5ca2ed51 --- /dev/null +++ b/bolt/lib/utils/restart_latest.py @@ -0,0 +1,32 @@ +# The following function is used to return _f for the latest output +def latest_output(path): + """ + This function looks in the dump_f folder in the provided path + directory and identifies the latest dump file. + WARNING this function is currently unsafe for corrupted dump files, which + can occur in particular if an allocation expires while the code is writing + to disk. + """ + import numpy as np + import glob + import os + dump_f_names = np.sort(glob.glob(os.path.join(path, 'dump_f/t=*.bin'))) + + ndumps = dump_f_names.size + + if(ndumps > 0): + latest_f = dump_f_names[ndumps-1].rsplit('.',1)[0] + time_elapsed = float(latest_f.rsplit('/',1)[1][2:]) + return latest_f, time_elapsed + else: + return None, None + +def format_time(time): + """ + This function formats a time value given as an integer or a float and + returns a string appropriately padded with zeros. + Right now format is [8].[6]. + """ + x = float(time) + return (str(x).split('.')[0].zfill(8) + '.' + + str(x).split('.')[1].ljust(6, '0')) From 3d35b4fe4e746ec372c10b8b8ee5f55bc0fe0872 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Fri, 7 Feb 2020 05:37:07 -0700 Subject: [PATCH 32/58] Added recursive batch script. fixed bugs --gitansh --- .../README.txt | 12 + .../boundary_conditions.py | 107 +++++ .../domain.py | 65 +++ .../dump_time_array.txt | 135 ++++++ .../edge_potential.py | 161 +++++++ .../enstrophy.py | 142 ++++++ .../initialize.py | 67 +++ .../job_script | 4 + .../main.py | 173 +++++++ .../momentum_space_movie.py | 134 ++++++ .../momentum_space_movie_zero_T.py | 160 +++++++ .../movie.py | 162 +++++++ .../params.py | 174 ++++++++ .../phase_vs_y.py | 180 ++++++++ .../post.py | 422 ++++++++++++++++++ .../signals.py | 171 +++++++ .../vorticity.py | 136 ++++++ 17 files changed, 2405 insertions(+) create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt new file mode 100644 index 00000000..ddb0d8b5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/README.txt @@ -0,0 +1,12 @@ +To switch between 1D/2D polar and cartesian momentum space, the following changes need +to be made : + + +1. domain + - Change p2_start, p2_end and N_p2 +2. params + - Change p_space_grid + - Change p_dim (if switching between 1D and 2D representation in p-space) +3. initialize : No change +4. main : No change +5. boundary_conditions : No change diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py new file mode 100644 index 00000000..762f5e79 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/boundary_conditions.py @@ -0,0 +1,107 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror+dirichlet' +in_q1_right = 'mirror+dirichlet' +in_q2_bottom = 'mirror' +in_q2_top = 'mirror' + +@af.broadcast +def f_left(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_in = params.vel_drift_x_in + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_right(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_out = params.vel_drift_x_out + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py new file mode 100644 index 00000000..7d095de5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py @@ -0,0 +1,65 @@ +import numpy as np +import params + +q1_start = 0. +q1_end = 1.0 +N_q1 = 72 + +q2_start = 0. +q2_end = 5.0 +N_q2 = 360 + +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation +N_p1 = 1 # Set equal to 1 for 1D polar + +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space +#p1_start = [-0.04] +#p1_end = [0.04] + + +# In the 2D polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] + +# Uncomment the following for the 1D polar representation of momentum space +p1_start = [0.5*params.initial_mu] +p1_end = [1.5*params.initial_mu] + + +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero +N_p2 = 8192 + +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +#p2_start = [-0.04] +#p2_end = [0.04] + +# In the 2D polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +p2_start = [-np.pi] +p2_end = [np.pi] + +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt new file mode 100644 index 00000000..fbfd5621 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/dump_time_array.txt @@ -0,0 +1,135 @@ +2.344375000000000497e+01 +2.345625000000000426e+01 +2.346875000000000355e+01 +2.348125000000000284e+01 +2.349375000000000213e+01 +2.350625000000000497e+01 +2.351875000000000426e+01 +2.353125000000000355e+01 +2.354375000000000284e+01 +2.355625000000000213e+01 +2.356875000000000497e+01 +2.358125000000000426e+01 +2.359375000000000355e+01 +2.360625000000000284e+01 +2.361875000000000213e+01 +2.363125000000000497e+01 +2.364375000000000426e+01 +2.365625000000000355e+01 +2.366875000000000284e+01 +2.368125000000000213e+01 +2.369375000000000497e+01 +2.370625000000000426e+01 +2.371875000000000355e+01 +2.373125000000000284e+01 +2.374375000000000213e+01 +2.375625000000000497e+01 +2.376875000000000426e+01 +2.378125000000000355e+01 +2.379375000000000284e+01 +2.380625000000000213e+01 +2.381875000000000497e+01 +2.383125000000000426e+01 +2.384375000000000355e+01 +2.385625000000000284e+01 +2.386875000000000213e+01 +2.388125000000000497e+01 +2.389375000000000426e+01 +2.390625000000000355e+01 +2.391875000000000284e+01 +2.393125000000000213e+01 +2.394375000000000497e+01 +2.395625000000000426e+01 +2.396875000000000355e+01 +2.398125000000000284e+01 +2.399375000000000213e+01 +2.400625000000000497e+01 +2.401875000000000426e+01 +2.403125000000000355e+01 +2.404375000000000284e+01 +2.405625000000000213e+01 +2.406875000000000497e+01 +2.408125000000000426e+01 +2.409375000000000355e+01 +2.410625000000000284e+01 +2.411875000000000213e+01 +2.413125000000000497e+01 +2.414375000000000426e+01 +2.415625000000000355e+01 +2.416875000000000284e+01 +2.418125000000000213e+01 +2.419375000000000497e+01 +2.420625000000000426e+01 +2.421875000000000355e+01 +2.423125000000000284e+01 +2.424375000000000213e+01 +2.425625000000000497e+01 +2.426875000000000426e+01 +2.428125000000000355e+01 +2.429375000000000284e+01 +2.430625000000000213e+01 +2.431875000000000497e+01 +2.433125000000000426e+01 +2.434375000000000355e+01 +2.435625000000000284e+01 +2.436875000000000213e+01 +2.438125000000000497e+01 +2.439375000000000426e+01 +2.440625000000000355e+01 +2.441875000000000284e+01 +2.443125000000000213e+01 +2.444375000000000497e+01 +2.445625000000000426e+01 +2.446875000000000355e+01 +2.448125000000000284e+01 +2.449375000000000213e+01 +2.450625000000000497e+01 +2.451875000000000426e+01 +2.453125000000000355e+01 +2.454375000000000284e+01 +2.455625000000000213e+01 +2.456875000000000497e+01 +2.458125000000000426e+01 +2.459375000000000355e+01 +2.460625000000000284e+01 +2.461875000000000213e+01 +2.463125000000000497e+01 +2.464375000000000426e+01 +2.465625000000000355e+01 +2.466875000000000284e+01 +2.468125000000000213e+01 +2.469375000000000497e+01 +2.470625000000000426e+01 +2.471875000000000355e+01 +2.473125000000000284e+01 +2.474375000000000213e+01 +2.475625000000000497e+01 +2.476875000000000426e+01 +2.478125000000000355e+01 +2.479375000000000284e+01 +2.480625000000000213e+01 +2.481875000000000497e+01 +2.483125000000000426e+01 +2.484375000000000355e+01 +2.485625000000000284e+01 +2.486875000000000213e+01 +2.488125000000000497e+01 +2.489375000000000426e+01 +2.490625000000000355e+01 +2.491875000000000284e+01 +2.493125000000000213e+01 +2.494375000000000497e+01 +2.495625000000000426e+01 +2.496875000000000355e+01 +2.498125000000000284e+01 +2.499375000000000213e+01 +2.500625000000000497e+01 +2.501875000000000426e+01 +2.503125000000000355e+01 +2.504375000000000284e+01 +2.505625000000000213e+01 +2.506875000000000497e+01 +2.508125000000000426e+01 +2.509375000000000355e+01 +2.510625000000000284e+01 +2.511875000000000213e+01 diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py new file mode 100644 index 00000000..b50b3bf5 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/edge_potential.py @@ -0,0 +1,161 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#print("Reading sensor signal...") +print("Loading data...") +density = [] +edge_density = [] +for file_number, dump_file in enumerate(moment_files): + + print("File number = ", file_number, ' of ', moment_files.size) + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density.append(moments[:, :, 0]) + edge_density.append(density[file_number][0, sensor_1_left_indices]) + +density = np.array(density) +edge_density = np.array(edge_density) + +mean_density = np.mean(density) +max_density = np.max(density) +min_density = np.min(density) + +np.savetxt("edge_density.txt", edge_density) + +print("Dumping data...") +for file_number in yt.parallel_objects(range(density.shape[0])): + + print("File number = ", file_number, ' of ', moment_files.size) + + pl.semilogy(q2[sensor_1_left_indices], + density[file_number][0, sensor_1_left_indices], + ) + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.title(r'Time = ' + "%.2f"%(file_number*dt*dump_interval) + " ps") + + pl.xlim([sensor_1_left_start, sensor_1_left_end]) + #pl.ylim([min_density-mean_density, max_density-mean_density]) + #pl.ylim([0., np.log(max_density)]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$ ps, $\\tau_\mathrm{mr} = 3.0$ ps') + #pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.savefig('images/density_' + '%06d'%file_number + '.png') + pl.clf() + + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py new file mode 100644 index 00000000..fb8e8c88 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/initialize.py @@ -0,0 +1,67 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 0.*q1 + params.vel_drift_y = 0.*q1 + params.phi = 0.*q1 + + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + params.vel_drift_x = 0.*q1 + 0e-3 + params.vel_drift_y = 0.*q1 + 0e-3 + params.j_x = 0.*q1 + params.j_y = 0.*q1 + + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + E_upper = params.E_band + params.charge[0]*params.phi + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + f = (1./(af.exp( (E_upper - params.vel_drift_x*p_x + - params.vel_drift_y*p_y + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script new file mode 100644 index 00000000..75c49d28 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/job_script @@ -0,0 +1,4 @@ +#!/bin/bash +#SBATCH -p gpu -n 4 --gres=gpu:4 -c1 --hint=nomultithread -t 2-00:00 +# (Note: use one MPI process per gpu, update both gres and -n together; max 6) +time mpirun python main.py -snes_monitor -snes_max_it 1 -snes_lag_jacobian_persists TRUE -snes_lag_jacobian 1000000 -snes_atol 1e-50 -snes_rtol 1e-50 > output.txt diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py new file mode 100644 index 00000000..53340b02 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/main.py @@ -0,0 +1,173 @@ +import os +import arrayfire as af +import numpy as np +import math +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +from mpi4py import MPI +MPI.WTIME_IS_GLOBAL=True + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +#from bolt.lib.nonlinear.fields.fields.fields \ +# import fields_solver.compute_electrostatic_fields +from bolt.lib.utils.restart_latest import latest_output, format_time + +import domain +import boundary_conditions +import initialize +import params + +import bolt.src.electronic_boltzmann.advection_terms \ + as advection_terms +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator +import bolt.src.electronic_boltzmann.moment_defs \ + as moment_defs + + +# Create required folders if they do not exist already +#if not os.path.isdir("dump_f"): +# os.system("mkdir dump_f") +#if not os.path.isdir("dump_moments"): +# os.system("mkdir dump_moments") +#if not os.path.isdir("dump_lagrange_multipliers"): +# os.system("mkdir dump_lagrange_multipliers") +#if not os.path.isdir("images"): +# os.system("mkdir images") + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moment_defs + ) + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +N_g = domain.N_ghost +params.rank = nls._comm.rank + +# Time parameters: +dt = params.dt +t_final = params.t_final +params.current_time = t0 = 0.0 +params.time_step = time_step = 0 +dump_counter = 0 +dump_time_array = [] + + +using_latest_restart = False +if(params.latest_restart == True): + latest_f, time_elapsed = latest_output('') + print("Latest restart time elapsed : ", time_elapsed, latest_f) + if(latest_f is not None and time_elapsed is not None): + nls.load_distribution_function(latest_f) + using_latest_restart = True + + +if using_latest_restart == False: + if(params.t_restart == 0 or params.latest_restart == True): + time_elapsed = 0 + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + else: + time_elapsed = params.t_restart + formatted_time = format_time(time_elapsed) + nls.load_distribution_function('dump_f/t=' + formatted_time) + +# Checking that the file writing intervals are greater than dt: +assert(params.dt_dump_f > dt) +assert(params.dt_dump_moments > dt) +assert(params.dt_dump_fields > dt) + + +#if (params.restart): +# nls.load_distribution_function(params.restart_file) + +density = nls.compute_moments('density') +print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + +nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) +while(time_elapsed < t_final): + + # Refine to machine error + if (time_step==0): + params.collision_nonlinear_iters = 10 + else: + params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters + + dump_steps = params.dump_steps + + if(params.dt_dump_moments != 0): + # We step by delta_dt to get the values at dt_dump + delta_dt = (1 - math.modf(time_elapsed/params.dt_dump_moments)[0]) \ + * params.dt_dump_moments + + print ("delta_dt - dt : ", delta_dt, dt) + + if((delta_dt-dt)<1e-5): + nls.strang_timestep(delta_dt) + time_elapsed += delta_dt + formatted_time = format_time(time_elapsed) + dump_time_array.append(params.current_time) + PETSc.Sys.Print("=====================================================") + PETSc.Sys.Print("Dumping data at time step =", time_step) + PETSc.Sys.Print("=====================================================") + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + + if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + + PETSc.Sys.Print("Time step =", time_step, ", Time =", time_elapsed) + + nls.strang_timestep(dt) + time_elapsed = time_elapsed + dt + time_step = time_step + 1 + params.time_step = time_step + params.current_time = time_elapsed + + # Floors + nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) + + density = nls.compute_moments('density') + print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + PETSc.Sys.Print("--------------------\n") + +nls.dump_distribution_function('dump_f/f_laststep') diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py new file mode 100644 index 00000000..1de644d7 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie.py @@ -0,0 +1,134 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q1_position, q2_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..74a2cdcb --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/momentum_space_movie_zero_T.py @@ -0,0 +1,160 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, N_s, N_p3, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q1_position, q2_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q1_position, q2_position, :, :])) + norm_factor = np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q1_position, q2_position, :, :],\ + [N_p2, N_p1])/norm_factor + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=2) + pl.plot(x_bg, y_bg, color='k', alpha=0.4, lw=2) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + #pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py new file mode 100644 index 00000000..dbae5848 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py @@ -0,0 +1,162 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#filepath = \ +#'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 7) + #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + #lagrange_multipliers = h5f['lagrange_multipliers'][:] + #h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + print (vel_drift_x.shape) + print (density.shape) + + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py new file mode 100644 index 00000000..a8db2e70 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py @@ -0,0 +1,174 @@ +import numpy as np +import arrayfire as af + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +# Restart(Set to zero for no-restart): +restart = 0 +restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/f_eqbm.h5' +phi_restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/phi_eqbm.h5' +electrostatic_solver_every_nth_step = 1000000 +solve_for_equilibrium = 0 + + +# Time parameters: +dt = 0.025/4 # ps +t_final = 40. # ps + +# File-writing Parameters: +dump_steps = 1 +# Set to zero for no file-writing +dt_dump_f = 10*dt #ps +# ALWAYS set dump moments and dump fields at same frequency: +dt_dump_moments = dt_dump_fields = 2*dt #ps + +# Dimensionality considered in velocity space: +p_dim = 1 +p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 4 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 0.0 # um +contact_end = 0.25 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 12e-4 +initial_mu = 0.015 +vel_drift_x_in = 1e-4*fermi_velocity +vel_drift_x_out = 1e-4*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +j_x = None +j_y = None +phi = None # Electric potential in the plane of graphene sheet + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +latest_restart = True +t_restart = 0 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + +def band_energy(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + + E_upper = p*fermi_velocity + + af.eval(E_upper) + return(E_upper) + +def band_velocity(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + v_f = fermi_velocity + + upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] + + af.eval(upper_band_velocity[0], upper_band_velocity[1]) + return(upper_band_velocity) + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py new file mode 100644 index 00000000..62104908 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/signals.py @@ -0,0 +1,171 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +# Calculate the phase difference between input_signal_array and sensor_normalized +# Code copied from : +# https:/stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves + +corr = correlate(input_normalized, sensor_normalized) +nsamples = input_normalized.size +time_corr = time_array[half_time:] +dt_corr = np.linspace(-time_corr[-1] + time_corr[0], + time_corr[-1] - time_corr[0], 2*nsamples-1) +time_shift = dt_corr[corr.argmax()] + +#Force the phase shift to be in [-pi:pi] +period = 1./AC_freq +phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) + +pl.plot(time_array, input_signal_array) +pl.plot(time_array, sensor_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=1) +pl.text(135, 1.14, '$\phi : %.2f \; rad$' %phase_diff) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-1.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 0.5$ ps') +pl.savefig('images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() + From 64fa44e6886d1e9bb0f2a56de7d7b876470216b3 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 17 Feb 2020 05:42:20 -0700 Subject: [PATCH 33/58] Bug fixes in 1 x 5.25 example with tasu inf --- .../PetscBinaryIO.py | 479 ++++++++++++++++++ .../domain.py | 6 +- .../fft.py | 177 +++++++ .../movie.py | 70 ++- .../params.py | 12 +- .../petsc_conf.py | 74 +++ 6 files changed, 787 insertions(+), 31 deletions(-) create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/PetscBinaryIO.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/fft.py create mode 100644 example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/petsc_conf.py diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/PetscBinaryIO.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/PetscBinaryIO.py new file mode 100644 index 00000000..fd0e48e9 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/PetscBinaryIO.py @@ -0,0 +1,479 @@ +"""PetscBinaryIO +=============== + +Provides + 1. PETSc-named objects Vec, Mat, and IS that inherit numpy.ndarray + 2. A class to read and write these objects from PETSc binary files. + +The standard usage of this module should look like: + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> objects = io.readBinaryFile('file.dat') + +or + + >>> import PetscBinaryIO + >>> import numpy + >>> vec = numpy.array([1., 2., 3.]).view(PetscBinaryIO.Vec) + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> io.writeBinaryFile('file.dat', [vec,]) + +to read in objects one at a time use such as + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> fh = open('file.dat') + >>> objecttype = io.readObjectType(fh) + >>> if objecttype == 'Vec': + >>> v = io.readVec(fh) + + Note that one must read in the object type first and then call readVec(), readMat() etc. + + +See also PetscBinaryIO.__doc__ and methods therein. +""" + +import numpy as np +import functools + +try: + basestring # Python-2 has basestring as a common parent of unicode and str +except NameError: + basestring = str # Python-3 is unicode through and through + +def update_wrapper_with_doc(wrapper, wrapped): + """Similar to functools.update_wrapper, but also gets the wrapper's __doc__ string""" + wdoc = wrapper.__doc__ + + functools.update_wrapper(wrapper, wrapped) + if wdoc is not None: + if wrapper.__doc__ is None: + wrapper.__doc__ = wdoc + else: + wrapper.__doc__ = wrapper.__doc__ + wdoc + return wrapper + +def wraps_with_doc(wrapped): + """Similar to functools.wraps, but also gets the wrapper's __doc__ string""" + return functools.partial(update_wrapper_with_doc, wrapped=wrapped) + +def decorate_with_conf(f): + """Decorates methods to take kwargs for precisions.""" + @wraps_with_doc(f) + def decorated_f(self, *args, **kwargs): + """ + Additional kwargs: + precision: 'single', 'double', 'longlong' for scalars + indices: '32bit', '64bit' integer size + complexscalars: True/False + + Note these are set in order of preference: + 1. kwargs if given here + 2. PetscBinaryIO class __init__ arguments + 3. PETSC_DIR/PETSC_ARCH defaults + """ + + changed = False + old_precision = self.precision + old_indices = self.indices + old_complexscalars = self.complexscalars + + try: + self.precision = kwargs.pop('precision') + except KeyError: + pass + else: + changed = True + + try: + self.indices = kwargs.pop('indices') + except KeyError: + pass + else: + changed = True + + try: + self.complexscalars = kwargs.pop('complexscalars') + except KeyError: + pass + else: + changed = True + + if changed: + self._update_dtypes() + + result = f(self, *args, **kwargs) + + if changed: + self.precision = old_precision + self.indices = old_indices + self.complexscalars = old_complexscalars + self._update_dtypes() + + return result + return decorated_f + + +class DoneWithFile(Exception): pass + + +class Vec(np.ndarray): + """Vec represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + vec = numpy.array([1,2,3]).view(Vec) + """ + _classid = 1211214 + + +class MatDense(np.matrix): + """Mat represented as 2D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + mat = numpy.array([[1,0],[0,1]]).view(Mat) + """ + _classid = 1211216 + + +class MatSparse(tuple): + """Mat represented as CSR tuple ((M, N), (rowindices, col, val)) + + This should be instantiated from a tuple: + + mat = MatSparse( ((M,N), (rowindices,col,val)) ) + """ + _classid = 1211216 + def __repr__(self): + return 'MatSparse: %s'%super(MatSparse, self).__repr__() + + +class IS(np.ndarray): + """IS represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy "view" method: + + an_is = numpy.array([3,4,5]).view(IS) + """ + _classid = 1211218 + + +class PetscBinaryIO(object): + """Reader/Writer class for PETSc binary files. + + Note that by default, precisions for both scalars and indices, as well as + complex scalars, are picked up from the PETSC_DIR/PETSC_ARCH configuration + as set by environmental variables. + + Alternatively, defaults can be overridden at class instantiation, or for + a given method call. + """ + + _classid = {1211216:'Mat', + 1211214:'Vec', + 1211218:'IS', + 1211219:'Bag'} + + def __init__(self, precision=None, indices=None, complexscalars=None): + if (precision is None) or (indices is None) or (complexscalars is None): + import petsc_conf + defaultprecision, defaultindices, defaultcomplexscalars = petsc_conf.get_conf() + if precision is None: + if defaultprecision is None: + precision = 'double' + else: + precision = defaultprecision + + if indices is None: + if defaultindices is None: + indices = '32bit' + else: + indices = defaultindices + + if complexscalars is None: + if defaultcomplexscalars is None: + complexscalars = False + else: + complexscalars = defaultcomplexscalars + + self.precision = precision + self.indices = indices + self.complexscalars = complexscalars + self._update_dtypes() + + def _update_dtypes(self): + if self.indices == '64bit': + self._inttype = np.dtype('>i8') + else: + self._inttype = np.dtype('>i4') + + if self.precision == 'longlong': + nbyte = 16 + elif self.precision == 'single': + nbyte = 4 + else: + nbyte = 8 + + if self.complexscalars: + name = 'c' + nbyte = nbyte * 2 # complex scalar takes twice as many bytes + else: + name = 'f' + + self._scalartype = '>{0}{1}'.format(name, nbyte) + + @decorate_with_conf + def readVec(self, fh): + """Reads a PETSc Vec from a binary file handle, must be called after readObjectType().""" + + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + try: + vals = np.fromfile(fh, dtype=self._scalartype, count=nz) + except MemoryError: + raise IOError('Inconsistent or invalid Vec data in file') + if (len(vals) is 0): + raise IOError('Inconsistent or invalid Vec data in file') + return vals.view(Vec) + + @decorate_with_conf + def writeVec(self, fh, vec): + """Writes a PETSc Vec to a binary file handle.""" + + metadata = np.array([Vec._classid, len(vec)], dtype=self._inttype) + metadata.tofile(fh) + vec.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatSparse(self, fh): + """Reads a PETSc Mat, returning a sparse representation of the data. Must be called after readObjectType() + + (M,N), (I,J,V) = readMatSparse(fid) + + Input: + fid : file handle to open binary file. + Output: + M,N : matrix size + I,J : arrays of row and column for each nonzero + V: nonzero value + """ + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + return MatSparse(((M, N), (I, J, V))) + + @decorate_with_conf + def writeMatSparse(self, fh, mat): + """Writes a Mat into a PETSc binary file handle""" + + ((M,N), (I,J,V)) = mat + metadata = np.array([MatSparse._classid,M,N,I[-1]], dtype=self._inttype) + rownz = I[1:] - I[:-1] + + assert len(J.shape) == len(V.shape) == len(I.shape) == 1 + assert len(J) == len(V) == I[-1] == rownz.sum() + assert (rownz > -1).all() + + metadata.tofile(fh) + rownz.astype(self._inttype).tofile(fh) + J.astype(self._inttype).tofile(fh) + V.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatDense(self, fh): + """Reads a PETSc Mat, returning a dense represention of the data, must be called after readObjectType()""" + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + mat = np.zeros((M,N), dtype=self._scalartype) + for row in range(M): + rstart, rend = I[row:row+2] + mat[row, J[rstart:rend]] = V[rstart:rend] + return mat.view(MatDense) + + @decorate_with_conf + def readMatSciPy(self, fh): + from scipy.sparse import csr_matrix + (M, N), (I, J, V) = self.readMatSparse(fh) + return csr_matrix((V, J, I), shape=(M, N)) + + @decorate_with_conf + def writeMatSciPy(self, fh, mat): + from scipy.sparse import csr_matrix + if hasattr(mat, 'tocsr'): + mat = mat.tocsr() + assert isinstance(mat, csr_matrix) + V = mat.data + M,N = mat.shape + J = mat.indices + I = mat.indptr + return self.writeMatSparse(fh, (mat.shape, (mat.indptr,mat.indices,mat.data))) + + @decorate_with_conf + def readMat(self, fh, mattype='sparse'): + """Reads a PETSc Mat from binary file handle, must be called after readObjectType() + + optional mattype: 'sparse" or 'dense' + + See also: readMatSparse, readMatDense + """ + + if mattype == 'sparse': + return self.readMatSparse(fh) + elif mattype == 'dense': + return self.readMatDense(fh) + elif mattype == 'scipy.sparse': + return self.readMatSciPy(fh) + else: + raise RuntimeError('Invalid matrix type requested: choose sparse/dense/scipy.sparse') + + @decorate_with_conf + def readIS(self, fh): + """Reads a PETSc Index Set from binary file handle, must be called after readObjectType()""" + + try: + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + v = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(v) == nz + except (MemoryError,IndexError): + raise IOError('Inconsistent or invalid IS data in file') + return v.view(IS) + + @decorate_with_conf + def writeIS(self, fh, anis): + """Writes a PETSc IS to binary file handle.""" + + metadata = np.array([IS._classid, len(anis)], dtype=self._inttype) + metadata.tofile(fh) + anis.astype(self._inttype).tofile(fh) + return + + @decorate_with_conf + def readObjectType(self, fid): + """Returns the next object type as a string in the file""" + try: + header = np.fromfile(fid, dtype=self._inttype, count=1)[0] + except (MemoryError, IndexError): + raise DoneWithFile + try: + objecttype = self._classid[header] + except KeyError: + raise IOError('Invalid PetscObject CLASSID or object not implemented for python') + return objecttype + + @decorate_with_conf + def readBinaryFile(self, fid, mattype='sparse'): + """Reads a PETSc binary file, returning a tuple of the contained objects. + + objects = self.readBinaryFile(fid, **kwargs) + + Input: + fid : either file name or handle to an open binary file. + + Output: + objects : tuple of objects representing the data in numpy arrays. + + Optional: + mattype : + 'sparse': Return matrices as raw CSR: (M, N), (row, col, val). + 'dense': Return matrices as MxN numpy arrays. + 'scipy.sparse': Return matrices as scipy.sparse objects. + """ + + close = False + + if isinstance(fid, basestring): + fid = open(fid, 'rb') + close = True + + objects = [] + try: + while True: + objecttype = self.readObjectType(fid) + + if objecttype == 'Vec': + objects.append(self.readVec(fid)) + elif objecttype == 'IS': + objects.append(self.readIS(fid)) + elif objecttype == 'Mat': + objects.append(self.readMat(fid,mattype)) + elif objecttype == 'Bag': + raise NotImplementedError('Bag Reader not yet implemented') + except DoneWithFile: + pass + finally: + if close: + fid.close() + + return tuple(objects) + + @decorate_with_conf + def writeBinaryFile(self, fid, objects): + """Writes a PETSc binary file containing the objects given. + + readBinaryFile(fid, objects) + + Input: + fid : either file handle to an open binary file, or filename. + objects : list of objects representing the data in numpy arrays, + which must be of type Vec, IS, MatSparse, or MatSciPy. + """ + close = False + if isinstance(fid, basestring): + fid = open(fid, 'wb') + close = True + + for petscobj in objects: + if (isinstance(petscobj, Vec)): + self.writeVec(fid, petscobj) + elif (isinstance(petscobj, IS)): + self.writeIS(fid, petscobj) + elif (isinstance(petscobj, MatSparse)): + self.writeMatSparse(fid, petscobj) + elif (isinstance(petscobj, MatDense)): + if close: + fid.close() + raise NotImplementedError('Writing a dense matrix is not yet supported') + else: + try: + self.writeMatSciPy(fid, petscobj) + except AssertionError: + if close: + fid.close() + raise TypeError('Object %s is not a valid PETSc object'%(petscobj.__repr__())) + if close: + fid.close() + return diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py index 7d095de5..816e0075 100644 --- a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/domain.py @@ -6,8 +6,8 @@ N_q1 = 72 q2_start = 0. -q2_end = 5.0 -N_q2 = 360 +q2_end = 5.25 +N_q2 = 378 # If N_p1 > 1, mirror boundary conditions require p1 to be # symmetric about zero @@ -41,7 +41,7 @@ # If N_p2 > 1, mirror boundary conditions require p2 to be # symmetric about zero -N_p2 = 8192 +N_p2 = 4096 # In the cartesian representation of momentum space, # p2 = p_y (magnitude of momentum) diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/fft.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/fft.py new file mode 100644 index 00000000..88fd9e17 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/fft.py @@ -0,0 +1,177 @@ +print ("Execution started, loading libs...") + +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +#from bolt.lib.physical_system import physical_system + +#from bolt.lib.nonlinear_solver.nonlinear_solver \ +# import nonlinear_solver +#from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ +# import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +#import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +#import bolt.src.electronic_boltzmann.collision_operator \ +# as collision_operator + +#import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +print ("Loaded libs") + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +probe_1_indices = (q2 < source_end) + + +#Dump files +filepath = '.' +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + + +print ("Moment files size : ", moment_files.size) +skip_files = 60000 + +moment_files = moment_files[skip_files:] +lagrange_multiplier_files = lagrange_multiplier_files[skip_files:] + +dt = params.dt +dump_interval = params.dump_steps + +#time_array = np.loadtxt("dump_time_array.txt") + +time_array = dump_interval * dt * np.arange(0, moment_files.size, 1) + +io = PetscBinaryIO.PetscBinaryIO() + +left_edge_density = [] +right_edge_density = [] +left_edge_current = [] + +for file_number, dump_file in enumerate(moment_files): + + dump_file = moment_files[file_number] + print (dump_file) + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + print("file number = ", file_number, "of ", moment_files.size, "shape = ", moments.shape) + + density = moments[:, :, 0] + + + left_edge_density.append(density[:, 0]) + right_edge_density.append(density[:, -1]) + + +# lagrange_multipliers = \ +# io.readBinaryFile(lagrange_multiplier_files[file_number]) +# lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 7) + +# print("file number = ", file_number, "of ", lagrange_multiplier_files.size, +# "shape = ", lagrange_multipliers.shape) + +# j_x = lagrange_multipliers[:, :, 5] +# j_y = lagrange_multipliers[:, :, 6] + +# j_mag = (j_x**2. + j_y**2.)**0.5 + +# left_edge_current.append(j_mag[:, 0]) + + +voltage_left = np.array(left_edge_density) +voltage_right = np.array(right_edge_density) +#current_left = np.array(left_edge_current) + +print("Left : ", voltage_left.shape) + +np.savez_compressed("voltages_L_1.0_5.25_tau_ee_inf_tau_eph_inf.txt", + left=voltage_left, right=voltage_right) +#np.savez_compressed('current_L_1.0_5.25_tau_ee_inf_tau_eph_inf.txt', +# current=current_left) + diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py index dbae5848..98c072e5 100644 --- a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/movie.py @@ -7,10 +7,11 @@ import matplotlib import matplotlib.gridspec as gridspec import matplotlib.patches as patches +from matplotlib import transforms, colors matplotlib.use('agg') import pylab as pl -import yt -yt.enable_parallelism() +#import yt +#yt.enable_parallelism() import petsc4py, sys; petsc4py.init(sys.argv) from petsc4py import PETSc @@ -100,10 +101,10 @@ #filepath = \ #'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' -filepath = os.getcwd() + "/dumps" -moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +filepath = "." +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) lagrange_multiplier_files = \ - np.sort(glob.glob(filepath+'/lagrange_multipliers*.bin')) + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) print ("moment files : ", moment_files.size) print ("lagrange multiplier files : ", lagrange_multiplier_files.size) @@ -115,11 +116,12 @@ io = PetscBinaryIO.PetscBinaryIO() -for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): +for file_number, dump_file in enumerate(moment_files): + file_number = -1 print("file number = ", file_number, "of ", moment_files.size) - moments = io.readBinaryFile(dump_file) + moments = io.readBinaryFile(moment_files[file_number]) moments = moments[0].reshape(N_q2, N_q1, 3) density = moments[:, :, 0] @@ -136,27 +138,51 @@ mu = lagrange_multipliers[:, :, 0] mu_ee = lagrange_multipliers[:, :, 1] T_ee = lagrange_multipliers[:, :, 2] - vel_drift_x = lagrange_multipliers[:, :, 3] - vel_drift_y = lagrange_multipliers[:, :, 4] + vel_drift_x = lagrange_multipliers[:, :, 5] + vel_drift_y = lagrange_multipliers[:, :, 6] print (vel_drift_x.shape) print (density.shape) - - pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') - pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") - pl.streamplot(q1, q2, - vel_drift_x, vel_drift_y, - density=2, color='k', - linewidth=0.7, arrowsize=1 - ) - + + l = 5.25 + pl.figure(figsize=(7.5*1.5, 1.5*25.0*l/6.5)) + base = pl.gca().transData + rot = transforms.Affine2D().rotate_deg(0) + + delta_n = density - np.mean(density) + + pl.contourf(q1, q2, delta_n, 200, + norm=colors.SymLogNorm(linthresh=delta_n.max()/20), cmap='bwr', + transform = rot + base) + + pl.streamplot(q1, q2, vel_drift_x, vel_drift_y, + density=1.4*l, color='black', + linewidth=1, arrowsize=1.5, transform = rot + base + ) + + pl.yticks([0, 5.]) + pl.xticks([]) + pl.xlim([q1[0], q1[-1]]) pl.ylim([q2[0], q2[-1]]) - + pl.gca().set_aspect('equal') - pl.xlabel(r'$x\;(\mu \mathrm{m})$') - pl.ylabel(r'$y\;(\mu \mathrm{m})$') - pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + + #pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.streamplot(q1, q2, + # vel_drift_x, vel_drift_y, + # density=2, color='k', + # linewidth=0.7, arrowsize=1 + # ) + + #pl.xlim([q1[0], q1[-1]]) + #pl.ylim([q2[0], q2[-1]]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') pl.savefig('images/dump_' + '%06d'%file_number + '.png') pl.clf() diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py index a8db2e70..cdc54d17 100644 --- a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/params.py @@ -42,14 +42,14 @@ # Time parameters: dt = 0.025/4 # ps -t_final = 40. # ps +t_final = 5000. # ps # File-writing Parameters: dump_steps = 1 # Set to zero for no file-writing -dt_dump_f = 10*dt #ps +dt_dump_f = 100*dt #ps # ALWAYS set dump moments and dump fields at same frequency: -dt_dump_moments = dt_dump_fields = 2*dt #ps +dt_dump_moments = dt_dump_fields = 5*dt #ps # Dimensionality considered in velocity space: p_dim = 1 @@ -79,10 +79,10 @@ # For contacts on the same side, use # contact_geometry = "turn_around" -initial_temperature = 12e-4 +initial_temperature = 12e-5 initial_mu = 0.015 -vel_drift_x_in = 1e-4*fermi_velocity -vel_drift_x_out = 1e-4*fermi_velocity +vel_drift_x_in = 1e-3*fermi_velocity +vel_drift_x_out = 1e-3*fermi_velocity AC_freq = 1./100 # ps^-1 B3_mean = 1. # T diff --git a/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/petsc_conf.py b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/petsc_conf.py new file mode 100644 index 00000000..fe935a3c --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_vel_1e-3/petsc_conf.py @@ -0,0 +1,74 @@ +import warnings + +def get_conf(): + """Parses various PETSc configuration/include files to get data types. + + precision, indices, complexscalars = get_conf() + + Output: + precision: 'single', 'double', 'longlong' indicates precision of PetscScalar + indices: '32', '64' indicates bit-size of PetscInt + complex: True/False indicates whether PetscScalar is complex or not. + """ + + import sys, os + precision = None + indices = None + complexscalars = None + + if 'PETSC_DIR' in os.environ: + petscdir = os.environ['PETSC_DIR'] + else: + warnings.warn('PETSC_DIR env not set - unable to locate PETSc installation, using defaults') + return None, None, None + + if os.path.isfile(os.path.join(petscdir,'lib','petsc','conf','petscrules')): + # found prefix install + petscvariables = os.path.join(petscdir,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,'include','petscconf.h') + else: + if 'PETSC_ARCH' in os.environ: + petscarch = os.environ['PETSC_ARCH'] + if os.path.isfile(os.path.join(petscdir,petscarch,'lib','petsc','conf','petscrules')): + # found legacy install + petscvariables = os.path.join(petscdir,petscarch,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,petscarch,'include','petscconf.h') + else: + warnings.warn('Unable to locate PETSc installation in specified PETSC_DIR/PETSC_ARCH, using defaults') + return None, None, None + else: + warnings.warn('PETSC_ARCH env not set or incorrect PETSC_DIR is given - unable to locate PETSc installation, using defaults') + return None, None, None + + try: + fid = open(petscvariables, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('PETSC_PRECISION'): + precision = line.strip().split('=')[1].strip('\n').strip() + + fid.close() + + try: + fid = open(petscconfinclude, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('#define PETSC_USE_64BIT_INDICES 1'): + indices = '64bit' + elif line.startswith('#define PETSC_USE_COMPLEX 1'): + complexscalars = True + + if indices is None: + indices = '32bit' + if complexscalars is None: + complexscalars = False + fid.close() + + return precision, indices, complexscalars + From 0496b26a40a5952690482b325eeb30f21cdf6a93 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 17 Feb 2020 18:29:17 +0530 Subject: [PATCH 34/58] Fixed integral measure in the computation of density --- bolt/lib/nonlinear/compute_moments.py | 10 ++++++++-- bolt/src/electronic_boltzmann/moment_defs.py | 8 ++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/bolt/lib/nonlinear/compute_moments.py b/bolt/lib/nonlinear/compute_moments.py index cac25188..e82f05a0 100644 --- a/bolt/lib/nonlinear/compute_moments.py +++ b/bolt/lib/nonlinear/compute_moments.py @@ -40,16 +40,22 @@ def compute_moments(self, moment_name, f=None): f = self.f if (self.physical_system.params.p_space_grid == 'cartesian'): + + measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 + moment = af.broadcast(getattr(self.physical_system.moments, moment_name - ), f, p1, p2, p3, self.dp3 * self.dp2 * self.dp1 + ), f, p1, p2, p3, measure ) elif (self.physical_system.params.p_space_grid == 'polar2D'): + + measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp2 * self.dp1 + moment = self.physical_system.params.initial_mu * \ af.broadcast(getattr(self.physical_system.moments, moment_name - ), f, p1, p2, p3, self.dp3 * self.dp2 * self.dp1 + ), f, p1, p2, p3, measure ) else: diff --git a/bolt/src/electronic_boltzmann/moment_defs.py b/bolt/src/electronic_boltzmann/moment_defs.py index 6f5a9357..d72ff03e 100644 --- a/bolt/src/electronic_boltzmann/moment_defs.py +++ b/bolt/src/electronic_boltzmann/moment_defs.py @@ -3,15 +3,11 @@ from bolt.src.utils.integral_over_v import integral_over_v -#TODO : Import required constants from libraries -# : pi = 3.1415926535 -# : h_bar = 1.0545718e-4 - def density(f, v1, v2, v3, integral_measure): return(integral_over_v(f, integral_measure)) def j_x(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * (4./(2.*3.1415926535*1.0545718e-4)**2) * v1, integral_measure)) + return(integral_over_v(f * v1, integral_measure)) def j_y(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * (4./(2.*3.1415926535*1.0545718e-4)**2) * v2, integral_measure)) + return(integral_over_v(f * v2, integral_measure)) From efcab6d9ec17b92c59d13b0d3c25f326286408a9 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 21 Mar 2020 16:28:25 -0400 Subject: [PATCH 35/58] Added dump time array, and other fixes to main --- .../L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py index f65ebb15..87233fcd 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/main.py @@ -29,14 +29,14 @@ # Create required folders if they do not exist already -if not os.path.isdir("dump_f"): - os.system("mkdir dump_f") -if not os.path.isdir("dump_moments"): - os.system("mkdir dump_moments") -if not os.path.isdir("dump_lagrange_multipliers"): - os.system("mkdir dump_lagrange_multipliers") -if not os.path.isdir("images"): - os.system("mkdir images") +#if not os.path.isdir("dump_f"): +# os.system("mkdir dump_f") +#if not os.path.isdir("dump_moments"): +# os.system("mkdir dump_moments") +#if not os.path.isdir("dump_lagrange_multipliers"): +# os.system("mkdir dump_lagrange_multipliers") +#if not os.path.isdir("images"): +# os.system("mkdir images") # Defining the physical system to be solved: @@ -57,7 +57,7 @@ # Time parameters: dt = params.dt t_final = params.t_final -params.current_time = t0 = 0.0 +params.current_time = time_elapsed = 0.0 params.time_step = time_step = 0 dump_counter = 0 dump_time_array = [] @@ -86,6 +86,9 @@ 'lagrange_multipliers', 'dump_lagrange_multipliers/t=' + formatted_time ) + dump_time_array.append(time_elapsed) + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) else: time_elapsed = params.t_restart formatted_time = format_time(time_elapsed) @@ -104,12 +107,12 @@ print("rank = ", params.rank, "\n", " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", - " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "i\n", " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" ) nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) -while(t0 < t_final): +while(time_elapsed < t_final): # Refine to machine error if (time_step==0): @@ -119,7 +122,7 @@ dump_steps = params.dump_steps - if(params.dt_dump_moments != 0): + if(params.dt_dump_moments != 0): # We step by delta_dt to get the values at dt_dump delta_dt = (1 - math.modf(time_elapsed/params.dt_dump_moments)[0]) \ * params.dt_dump_moments @@ -129,11 +132,7 @@ time_elapsed += delta_dt formatted_time = format_time(time_elapsed) nls.dump_moments('dump_moments/t=' + formatted_time) - - if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): - formatted_time = format_time(time_elapsed) - nls.dump_distribution_function('dump_f/t=' + formatted_time) - nls.dump_aux_arrays([params.mu, + nls.dump_aux_arrays([params.mu, params.mu_ee, params.T_ee, params.vel_drift_x, params.vel_drift_y, @@ -141,14 +140,21 @@ 'lagrange_multipliers', 'dump_lagrange_multipliers/t=' + formatted_time ) + dump_time_array.append(time_elapsed) + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + + if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) - PETSc.Sys.Print("Time step =", time_step, ", Time =", t0) + PETSc.Sys.Print("Time step =", time_step, ", Time =", time_elapsed) nls.strang_timestep(dt) - t0 = t0 + dt + time_elapsed = time_elapsed + dt time_step = time_step + 1 params.time_step = time_step - params.current_time = t0 + params.current_time = time_elapsed # Floors nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) From 90e6eb428b0c748c724e0ba86e06106eebf13a04 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sun, 22 Mar 2020 10:08:09 -0400 Subject: [PATCH 36/58] Added Petsc_BinaryIO and petsc_conf --- .../PetscBinaryIO.py | 479 ++++++++++++++++++ .../petsc_conf.py | 73 +++ 2 files changed, 552 insertions(+) create mode 100755 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/PetscBinaryIO.py create mode 100755 example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/petsc_conf.py diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/PetscBinaryIO.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/PetscBinaryIO.py new file mode 100755 index 00000000..fd0e48e9 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/PetscBinaryIO.py @@ -0,0 +1,479 @@ +"""PetscBinaryIO +=============== + +Provides + 1. PETSc-named objects Vec, Mat, and IS that inherit numpy.ndarray + 2. A class to read and write these objects from PETSc binary files. + +The standard usage of this module should look like: + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> objects = io.readBinaryFile('file.dat') + +or + + >>> import PetscBinaryIO + >>> import numpy + >>> vec = numpy.array([1., 2., 3.]).view(PetscBinaryIO.Vec) + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> io.writeBinaryFile('file.dat', [vec,]) + +to read in objects one at a time use such as + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> fh = open('file.dat') + >>> objecttype = io.readObjectType(fh) + >>> if objecttype == 'Vec': + >>> v = io.readVec(fh) + + Note that one must read in the object type first and then call readVec(), readMat() etc. + + +See also PetscBinaryIO.__doc__ and methods therein. +""" + +import numpy as np +import functools + +try: + basestring # Python-2 has basestring as a common parent of unicode and str +except NameError: + basestring = str # Python-3 is unicode through and through + +def update_wrapper_with_doc(wrapper, wrapped): + """Similar to functools.update_wrapper, but also gets the wrapper's __doc__ string""" + wdoc = wrapper.__doc__ + + functools.update_wrapper(wrapper, wrapped) + if wdoc is not None: + if wrapper.__doc__ is None: + wrapper.__doc__ = wdoc + else: + wrapper.__doc__ = wrapper.__doc__ + wdoc + return wrapper + +def wraps_with_doc(wrapped): + """Similar to functools.wraps, but also gets the wrapper's __doc__ string""" + return functools.partial(update_wrapper_with_doc, wrapped=wrapped) + +def decorate_with_conf(f): + """Decorates methods to take kwargs for precisions.""" + @wraps_with_doc(f) + def decorated_f(self, *args, **kwargs): + """ + Additional kwargs: + precision: 'single', 'double', 'longlong' for scalars + indices: '32bit', '64bit' integer size + complexscalars: True/False + + Note these are set in order of preference: + 1. kwargs if given here + 2. PetscBinaryIO class __init__ arguments + 3. PETSC_DIR/PETSC_ARCH defaults + """ + + changed = False + old_precision = self.precision + old_indices = self.indices + old_complexscalars = self.complexscalars + + try: + self.precision = kwargs.pop('precision') + except KeyError: + pass + else: + changed = True + + try: + self.indices = kwargs.pop('indices') + except KeyError: + pass + else: + changed = True + + try: + self.complexscalars = kwargs.pop('complexscalars') + except KeyError: + pass + else: + changed = True + + if changed: + self._update_dtypes() + + result = f(self, *args, **kwargs) + + if changed: + self.precision = old_precision + self.indices = old_indices + self.complexscalars = old_complexscalars + self._update_dtypes() + + return result + return decorated_f + + +class DoneWithFile(Exception): pass + + +class Vec(np.ndarray): + """Vec represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + vec = numpy.array([1,2,3]).view(Vec) + """ + _classid = 1211214 + + +class MatDense(np.matrix): + """Mat represented as 2D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + mat = numpy.array([[1,0],[0,1]]).view(Mat) + """ + _classid = 1211216 + + +class MatSparse(tuple): + """Mat represented as CSR tuple ((M, N), (rowindices, col, val)) + + This should be instantiated from a tuple: + + mat = MatSparse( ((M,N), (rowindices,col,val)) ) + """ + _classid = 1211216 + def __repr__(self): + return 'MatSparse: %s'%super(MatSparse, self).__repr__() + + +class IS(np.ndarray): + """IS represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy "view" method: + + an_is = numpy.array([3,4,5]).view(IS) + """ + _classid = 1211218 + + +class PetscBinaryIO(object): + """Reader/Writer class for PETSc binary files. + + Note that by default, precisions for both scalars and indices, as well as + complex scalars, are picked up from the PETSC_DIR/PETSC_ARCH configuration + as set by environmental variables. + + Alternatively, defaults can be overridden at class instantiation, or for + a given method call. + """ + + _classid = {1211216:'Mat', + 1211214:'Vec', + 1211218:'IS', + 1211219:'Bag'} + + def __init__(self, precision=None, indices=None, complexscalars=None): + if (precision is None) or (indices is None) or (complexscalars is None): + import petsc_conf + defaultprecision, defaultindices, defaultcomplexscalars = petsc_conf.get_conf() + if precision is None: + if defaultprecision is None: + precision = 'double' + else: + precision = defaultprecision + + if indices is None: + if defaultindices is None: + indices = '32bit' + else: + indices = defaultindices + + if complexscalars is None: + if defaultcomplexscalars is None: + complexscalars = False + else: + complexscalars = defaultcomplexscalars + + self.precision = precision + self.indices = indices + self.complexscalars = complexscalars + self._update_dtypes() + + def _update_dtypes(self): + if self.indices == '64bit': + self._inttype = np.dtype('>i8') + else: + self._inttype = np.dtype('>i4') + + if self.precision == 'longlong': + nbyte = 16 + elif self.precision == 'single': + nbyte = 4 + else: + nbyte = 8 + + if self.complexscalars: + name = 'c' + nbyte = nbyte * 2 # complex scalar takes twice as many bytes + else: + name = 'f' + + self._scalartype = '>{0}{1}'.format(name, nbyte) + + @decorate_with_conf + def readVec(self, fh): + """Reads a PETSc Vec from a binary file handle, must be called after readObjectType().""" + + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + try: + vals = np.fromfile(fh, dtype=self._scalartype, count=nz) + except MemoryError: + raise IOError('Inconsistent or invalid Vec data in file') + if (len(vals) is 0): + raise IOError('Inconsistent or invalid Vec data in file') + return vals.view(Vec) + + @decorate_with_conf + def writeVec(self, fh, vec): + """Writes a PETSc Vec to a binary file handle.""" + + metadata = np.array([Vec._classid, len(vec)], dtype=self._inttype) + metadata.tofile(fh) + vec.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatSparse(self, fh): + """Reads a PETSc Mat, returning a sparse representation of the data. Must be called after readObjectType() + + (M,N), (I,J,V) = readMatSparse(fid) + + Input: + fid : file handle to open binary file. + Output: + M,N : matrix size + I,J : arrays of row and column for each nonzero + V: nonzero value + """ + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + return MatSparse(((M, N), (I, J, V))) + + @decorate_with_conf + def writeMatSparse(self, fh, mat): + """Writes a Mat into a PETSc binary file handle""" + + ((M,N), (I,J,V)) = mat + metadata = np.array([MatSparse._classid,M,N,I[-1]], dtype=self._inttype) + rownz = I[1:] - I[:-1] + + assert len(J.shape) == len(V.shape) == len(I.shape) == 1 + assert len(J) == len(V) == I[-1] == rownz.sum() + assert (rownz > -1).all() + + metadata.tofile(fh) + rownz.astype(self._inttype).tofile(fh) + J.astype(self._inttype).tofile(fh) + V.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatDense(self, fh): + """Reads a PETSc Mat, returning a dense represention of the data, must be called after readObjectType()""" + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + mat = np.zeros((M,N), dtype=self._scalartype) + for row in range(M): + rstart, rend = I[row:row+2] + mat[row, J[rstart:rend]] = V[rstart:rend] + return mat.view(MatDense) + + @decorate_with_conf + def readMatSciPy(self, fh): + from scipy.sparse import csr_matrix + (M, N), (I, J, V) = self.readMatSparse(fh) + return csr_matrix((V, J, I), shape=(M, N)) + + @decorate_with_conf + def writeMatSciPy(self, fh, mat): + from scipy.sparse import csr_matrix + if hasattr(mat, 'tocsr'): + mat = mat.tocsr() + assert isinstance(mat, csr_matrix) + V = mat.data + M,N = mat.shape + J = mat.indices + I = mat.indptr + return self.writeMatSparse(fh, (mat.shape, (mat.indptr,mat.indices,mat.data))) + + @decorate_with_conf + def readMat(self, fh, mattype='sparse'): + """Reads a PETSc Mat from binary file handle, must be called after readObjectType() + + optional mattype: 'sparse" or 'dense' + + See also: readMatSparse, readMatDense + """ + + if mattype == 'sparse': + return self.readMatSparse(fh) + elif mattype == 'dense': + return self.readMatDense(fh) + elif mattype == 'scipy.sparse': + return self.readMatSciPy(fh) + else: + raise RuntimeError('Invalid matrix type requested: choose sparse/dense/scipy.sparse') + + @decorate_with_conf + def readIS(self, fh): + """Reads a PETSc Index Set from binary file handle, must be called after readObjectType()""" + + try: + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + v = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(v) == nz + except (MemoryError,IndexError): + raise IOError('Inconsistent or invalid IS data in file') + return v.view(IS) + + @decorate_with_conf + def writeIS(self, fh, anis): + """Writes a PETSc IS to binary file handle.""" + + metadata = np.array([IS._classid, len(anis)], dtype=self._inttype) + metadata.tofile(fh) + anis.astype(self._inttype).tofile(fh) + return + + @decorate_with_conf + def readObjectType(self, fid): + """Returns the next object type as a string in the file""" + try: + header = np.fromfile(fid, dtype=self._inttype, count=1)[0] + except (MemoryError, IndexError): + raise DoneWithFile + try: + objecttype = self._classid[header] + except KeyError: + raise IOError('Invalid PetscObject CLASSID or object not implemented for python') + return objecttype + + @decorate_with_conf + def readBinaryFile(self, fid, mattype='sparse'): + """Reads a PETSc binary file, returning a tuple of the contained objects. + + objects = self.readBinaryFile(fid, **kwargs) + + Input: + fid : either file name or handle to an open binary file. + + Output: + objects : tuple of objects representing the data in numpy arrays. + + Optional: + mattype : + 'sparse': Return matrices as raw CSR: (M, N), (row, col, val). + 'dense': Return matrices as MxN numpy arrays. + 'scipy.sparse': Return matrices as scipy.sparse objects. + """ + + close = False + + if isinstance(fid, basestring): + fid = open(fid, 'rb') + close = True + + objects = [] + try: + while True: + objecttype = self.readObjectType(fid) + + if objecttype == 'Vec': + objects.append(self.readVec(fid)) + elif objecttype == 'IS': + objects.append(self.readIS(fid)) + elif objecttype == 'Mat': + objects.append(self.readMat(fid,mattype)) + elif objecttype == 'Bag': + raise NotImplementedError('Bag Reader not yet implemented') + except DoneWithFile: + pass + finally: + if close: + fid.close() + + return tuple(objects) + + @decorate_with_conf + def writeBinaryFile(self, fid, objects): + """Writes a PETSc binary file containing the objects given. + + readBinaryFile(fid, objects) + + Input: + fid : either file handle to an open binary file, or filename. + objects : list of objects representing the data in numpy arrays, + which must be of type Vec, IS, MatSparse, or MatSciPy. + """ + close = False + if isinstance(fid, basestring): + fid = open(fid, 'wb') + close = True + + for petscobj in objects: + if (isinstance(petscobj, Vec)): + self.writeVec(fid, petscobj) + elif (isinstance(petscobj, IS)): + self.writeIS(fid, petscobj) + elif (isinstance(petscobj, MatSparse)): + self.writeMatSparse(fid, petscobj) + elif (isinstance(petscobj, MatDense)): + if close: + fid.close() + raise NotImplementedError('Writing a dense matrix is not yet supported') + else: + try: + self.writeMatSciPy(fid, petscobj) + except AssertionError: + if close: + fid.close() + raise TypeError('Object %s is not a valid PETSc object'%(petscobj.__repr__())) + if close: + fid.close() + return diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/petsc_conf.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/petsc_conf.py new file mode 100755 index 00000000..22781ed2 --- /dev/null +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/petsc_conf.py @@ -0,0 +1,73 @@ +import warnings + +def get_conf(): + """Parses various PETSc configuration/include files to get data types. + + precision, indices, complexscalars = get_conf() + + Output: + precision: 'single', 'double', 'longlong' indicates precision of PetscScalar + indices: '32', '64' indicates bit-size of PetscInt + complex: True/False indicates whether PetscScalar is complex or not. + """ + + import sys, os + precision = None + indices = None + complexscalars = None + + if 'PETSC_DIR' in os.environ: + petscdir = os.environ['PETSC_DIR'] + else: + warnings.warn('PETSC_DIR env not set - unable to locate PETSc installation, using defaults') + return None, None, None + + if os.path.isfile(os.path.join(petscdir,'lib','petsc','conf','petscrules')): + # found prefix install + petscvariables = os.path.join(petscdir,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,'include','petscconf.h') + else: + if 'PETSC_ARCH' in os.environ: + petscarch = os.environ['PETSC_ARCH'] + if os.path.isfile(os.path.join(petscdir,petscarch,'lib','petsc','conf','petscrules')): + # found legacy install + petscvariables = os.path.join(petscdir,petscarch,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,petscarch,'include','petscconf.h') + else: + warnings.warn('Unable to locate PETSc installation in specified PETSC_DIR/PETSC_ARCH, using defaults') + return None, None, None + else: + warnings.warn('PETSC_ARCH env not set or incorrect PETSC_DIR is given - unable to locate PETSc installation, using defaults') + return None, None, None + + try: + fid = open(petscvariables, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('PETSC_PRECISION'): + precision = line.strip().split('=')[1].strip('\n').strip() + + fid.close() + + try: + fid = open(petscconfinclude, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('#define PETSC_USE_64BIT_INDICES 1'): + indices = '64bit' + elif line.startswith('#define PETSC_USE_COMPLEX 1'): + complexscalars = True + + if indices is None: + indices = '32bit' + if complexscalars is None: + complexscalars = False + fid.close() + + return precision, indices, complexscalars From 551e0b8082956b2a9392b2df3245f5a5beea3b41 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 23 Mar 2020 13:19:53 -0400 Subject: [PATCH 37/58] Bugfix, Cleaned up compute_moments --- bolt/lib/nonlinear/compute_moments.py | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/bolt/lib/nonlinear/compute_moments.py b/bolt/lib/nonlinear/compute_moments.py index e82f05a0..d3997bdc 100644 --- a/bolt/lib/nonlinear/compute_moments.py +++ b/bolt/lib/nonlinear/compute_moments.py @@ -39,24 +39,12 @@ def compute_moments(self, moment_name, f=None): if(f is None): f = self.f - if (self.physical_system.params.p_space_grid == 'cartesian'): + measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 - measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 - - moment = af.broadcast(getattr(self.physical_system.moments, - moment_name - ), f, p1, p2, p3, measure - ) - - elif (self.physical_system.params.p_space_grid == 'polar2D'): - - measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp2 * self.dp1 - - moment = self.physical_system.params.initial_mu * \ - af.broadcast(getattr(self.physical_system.moments, - moment_name - ), f, p1, p2, p3, measure - ) + moment = af.broadcast(getattr(self.physical_system.moments, + moment_name + ), f, p1, p2, p3, measure + ) else: raise NotImplementedError('Unsupported coordinate system in p_space') From eee8865910ae299b455a432450e46bbca5ea2b82 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 23 Mar 2020 13:34:13 -0400 Subject: [PATCH 38/58] Fix error in compute_moments --- bolt/lib/nonlinear/compute_moments.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bolt/lib/nonlinear/compute_moments.py b/bolt/lib/nonlinear/compute_moments.py index d3997bdc..fcea88cc 100644 --- a/bolt/lib/nonlinear/compute_moments.py +++ b/bolt/lib/nonlinear/compute_moments.py @@ -46,8 +46,5 @@ def compute_moments(self, moment_name, f=None): ), f, p1, p2, p3, measure ) - else: - raise NotImplementedError('Unsupported coordinate system in p_space') - af.eval(moment) return (moment) From f4fb6cc6d8a9444b3f68c8832b1854054546cb4d Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 09:37:39 -0400 Subject: [PATCH 39/58] Added AC/DC switch in params --- .../boundary_conditions.py | 22 ++++++++++++++++--- .../params.py | 3 ++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py index 24d0598b..d0c61e57 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/boundary_conditions.py @@ -17,7 +17,13 @@ def f_left(f, t, q1, q2, p1, p2, p3, params): t = params.current_time omega = 2. * np.pi * params.AC_freq - vel_drift_x_in = params.vel_drift_x_in * np.sin(omega*t) + + if (params.source_type == 'AC'): + vel_drift_x_in = params.vel_drift_x_in * np.sin(omega*t) + elif (params.source_type == 'DC'): + vel_drift_x_in = params.vel_drift_x_in + else: + raise NotImplementedError('Unsupported source_type') if (params.p_space_grid == 'cartesian'): p_x = p1 @@ -47,7 +53,12 @@ def f_left(f, t, q1, q2, p1, p2, p3, params): elif (params.contact_geometry=="turn_around"): # Contacts on the same side of the device - vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + if (params.source_type == 'AC'): + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + elif (params.source_type == 'DC'): + vel_drift_x_out = -params.vel_drift_x_in + else: + raise NotImplementedError('Unsupported source_type') fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) ) @@ -72,7 +83,12 @@ def f_right(f, t, q1, q2, p1, p2, p3, params): t = params.current_time omega = 2. * np.pi * params.AC_freq - vel_drift_x_out = params.vel_drift_x_out * np.sin(omega*t) + if (params.source_type == 'AC'): + vel_drift_x_out = params.vel_drift_x_out * np.sin(omega*t) + elif (params.source_type == 'DC'): + vel_drift_x_out = params.vel_drift_x_out + else: + raise NotImplementedError('Unsupported source_type') if (params.p_space_grid == 'cartesian'): p_x = p1 diff --git a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py index 633de285..09e1298f 100644 --- a/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py +++ b/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/params.py @@ -84,7 +84,8 @@ initial_mu = 0.015 vel_drift_x_in = 1e-4*fermi_velocity vel_drift_x_out = 1e-4*fermi_velocity -AC_freq = 1./100 # ps^-1 +source_type = 'AC' # Select 'AC' or 'DC' +AC_freq = 1./100 # ps^-1 (only for AC) B3_mean = 1. # T From b86aa986c6d2229be82eae6d95c630418e5ceadb Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 13:36:37 -0400 Subject: [PATCH 40/58] Example folder for PdCoO2 --- .../PetscBinaryIO.py | 479 ++++++++++++++++++ .../README.txt | 12 + .../boundary_conditions.py | 107 ++++ .../check.py | 14 + .../domain.py | 67 +++ .../edge_density.py | 122 +++++ .../edge_potential.py | 161 ++++++ .../enstrophy.py | 142 ++++++ .../initialize.py | 67 +++ .../job_script | 4 + .../main.py | 171 +++++++ .../momentum_space_movie.py | 134 +++++ .../momentum_space_movie_debug.py | 182 +++++++ .../momentum_space_movie_zero_T.py | 182 +++++++ .../movie.py | 163 ++++++ .../params.py | 234 +++++++++ .../petsc_conf.py | 73 +++ .../phase_vs_y.py | 180 +++++++ .../post.py | 422 +++++++++++++++ .../signals.py | 166 ++++++ .../vorticity.py | 136 +++++ 21 files changed, 3218 insertions(+) create mode 100755 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/PetscBinaryIO.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_density.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/job_script create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_debug.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_zero_T.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py create mode 100755 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/petsc_conf.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/post.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/signals.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/vorticity.py diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/PetscBinaryIO.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/PetscBinaryIO.py new file mode 100755 index 00000000..fd0e48e9 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/PetscBinaryIO.py @@ -0,0 +1,479 @@ +"""PetscBinaryIO +=============== + +Provides + 1. PETSc-named objects Vec, Mat, and IS that inherit numpy.ndarray + 2. A class to read and write these objects from PETSc binary files. + +The standard usage of this module should look like: + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> objects = io.readBinaryFile('file.dat') + +or + + >>> import PetscBinaryIO + >>> import numpy + >>> vec = numpy.array([1., 2., 3.]).view(PetscBinaryIO.Vec) + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> io.writeBinaryFile('file.dat', [vec,]) + +to read in objects one at a time use such as + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> fh = open('file.dat') + >>> objecttype = io.readObjectType(fh) + >>> if objecttype == 'Vec': + >>> v = io.readVec(fh) + + Note that one must read in the object type first and then call readVec(), readMat() etc. + + +See also PetscBinaryIO.__doc__ and methods therein. +""" + +import numpy as np +import functools + +try: + basestring # Python-2 has basestring as a common parent of unicode and str +except NameError: + basestring = str # Python-3 is unicode through and through + +def update_wrapper_with_doc(wrapper, wrapped): + """Similar to functools.update_wrapper, but also gets the wrapper's __doc__ string""" + wdoc = wrapper.__doc__ + + functools.update_wrapper(wrapper, wrapped) + if wdoc is not None: + if wrapper.__doc__ is None: + wrapper.__doc__ = wdoc + else: + wrapper.__doc__ = wrapper.__doc__ + wdoc + return wrapper + +def wraps_with_doc(wrapped): + """Similar to functools.wraps, but also gets the wrapper's __doc__ string""" + return functools.partial(update_wrapper_with_doc, wrapped=wrapped) + +def decorate_with_conf(f): + """Decorates methods to take kwargs for precisions.""" + @wraps_with_doc(f) + def decorated_f(self, *args, **kwargs): + """ + Additional kwargs: + precision: 'single', 'double', 'longlong' for scalars + indices: '32bit', '64bit' integer size + complexscalars: True/False + + Note these are set in order of preference: + 1. kwargs if given here + 2. PetscBinaryIO class __init__ arguments + 3. PETSC_DIR/PETSC_ARCH defaults + """ + + changed = False + old_precision = self.precision + old_indices = self.indices + old_complexscalars = self.complexscalars + + try: + self.precision = kwargs.pop('precision') + except KeyError: + pass + else: + changed = True + + try: + self.indices = kwargs.pop('indices') + except KeyError: + pass + else: + changed = True + + try: + self.complexscalars = kwargs.pop('complexscalars') + except KeyError: + pass + else: + changed = True + + if changed: + self._update_dtypes() + + result = f(self, *args, **kwargs) + + if changed: + self.precision = old_precision + self.indices = old_indices + self.complexscalars = old_complexscalars + self._update_dtypes() + + return result + return decorated_f + + +class DoneWithFile(Exception): pass + + +class Vec(np.ndarray): + """Vec represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + vec = numpy.array([1,2,3]).view(Vec) + """ + _classid = 1211214 + + +class MatDense(np.matrix): + """Mat represented as 2D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + mat = numpy.array([[1,0],[0,1]]).view(Mat) + """ + _classid = 1211216 + + +class MatSparse(tuple): + """Mat represented as CSR tuple ((M, N), (rowindices, col, val)) + + This should be instantiated from a tuple: + + mat = MatSparse( ((M,N), (rowindices,col,val)) ) + """ + _classid = 1211216 + def __repr__(self): + return 'MatSparse: %s'%super(MatSparse, self).__repr__() + + +class IS(np.ndarray): + """IS represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy "view" method: + + an_is = numpy.array([3,4,5]).view(IS) + """ + _classid = 1211218 + + +class PetscBinaryIO(object): + """Reader/Writer class for PETSc binary files. + + Note that by default, precisions for both scalars and indices, as well as + complex scalars, are picked up from the PETSC_DIR/PETSC_ARCH configuration + as set by environmental variables. + + Alternatively, defaults can be overridden at class instantiation, or for + a given method call. + """ + + _classid = {1211216:'Mat', + 1211214:'Vec', + 1211218:'IS', + 1211219:'Bag'} + + def __init__(self, precision=None, indices=None, complexscalars=None): + if (precision is None) or (indices is None) or (complexscalars is None): + import petsc_conf + defaultprecision, defaultindices, defaultcomplexscalars = petsc_conf.get_conf() + if precision is None: + if defaultprecision is None: + precision = 'double' + else: + precision = defaultprecision + + if indices is None: + if defaultindices is None: + indices = '32bit' + else: + indices = defaultindices + + if complexscalars is None: + if defaultcomplexscalars is None: + complexscalars = False + else: + complexscalars = defaultcomplexscalars + + self.precision = precision + self.indices = indices + self.complexscalars = complexscalars + self._update_dtypes() + + def _update_dtypes(self): + if self.indices == '64bit': + self._inttype = np.dtype('>i8') + else: + self._inttype = np.dtype('>i4') + + if self.precision == 'longlong': + nbyte = 16 + elif self.precision == 'single': + nbyte = 4 + else: + nbyte = 8 + + if self.complexscalars: + name = 'c' + nbyte = nbyte * 2 # complex scalar takes twice as many bytes + else: + name = 'f' + + self._scalartype = '>{0}{1}'.format(name, nbyte) + + @decorate_with_conf + def readVec(self, fh): + """Reads a PETSc Vec from a binary file handle, must be called after readObjectType().""" + + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + try: + vals = np.fromfile(fh, dtype=self._scalartype, count=nz) + except MemoryError: + raise IOError('Inconsistent or invalid Vec data in file') + if (len(vals) is 0): + raise IOError('Inconsistent or invalid Vec data in file') + return vals.view(Vec) + + @decorate_with_conf + def writeVec(self, fh, vec): + """Writes a PETSc Vec to a binary file handle.""" + + metadata = np.array([Vec._classid, len(vec)], dtype=self._inttype) + metadata.tofile(fh) + vec.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatSparse(self, fh): + """Reads a PETSc Mat, returning a sparse representation of the data. Must be called after readObjectType() + + (M,N), (I,J,V) = readMatSparse(fid) + + Input: + fid : file handle to open binary file. + Output: + M,N : matrix size + I,J : arrays of row and column for each nonzero + V: nonzero value + """ + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + return MatSparse(((M, N), (I, J, V))) + + @decorate_with_conf + def writeMatSparse(self, fh, mat): + """Writes a Mat into a PETSc binary file handle""" + + ((M,N), (I,J,V)) = mat + metadata = np.array([MatSparse._classid,M,N,I[-1]], dtype=self._inttype) + rownz = I[1:] - I[:-1] + + assert len(J.shape) == len(V.shape) == len(I.shape) == 1 + assert len(J) == len(V) == I[-1] == rownz.sum() + assert (rownz > -1).all() + + metadata.tofile(fh) + rownz.astype(self._inttype).tofile(fh) + J.astype(self._inttype).tofile(fh) + V.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatDense(self, fh): + """Reads a PETSc Mat, returning a dense represention of the data, must be called after readObjectType()""" + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + mat = np.zeros((M,N), dtype=self._scalartype) + for row in range(M): + rstart, rend = I[row:row+2] + mat[row, J[rstart:rend]] = V[rstart:rend] + return mat.view(MatDense) + + @decorate_with_conf + def readMatSciPy(self, fh): + from scipy.sparse import csr_matrix + (M, N), (I, J, V) = self.readMatSparse(fh) + return csr_matrix((V, J, I), shape=(M, N)) + + @decorate_with_conf + def writeMatSciPy(self, fh, mat): + from scipy.sparse import csr_matrix + if hasattr(mat, 'tocsr'): + mat = mat.tocsr() + assert isinstance(mat, csr_matrix) + V = mat.data + M,N = mat.shape + J = mat.indices + I = mat.indptr + return self.writeMatSparse(fh, (mat.shape, (mat.indptr,mat.indices,mat.data))) + + @decorate_with_conf + def readMat(self, fh, mattype='sparse'): + """Reads a PETSc Mat from binary file handle, must be called after readObjectType() + + optional mattype: 'sparse" or 'dense' + + See also: readMatSparse, readMatDense + """ + + if mattype == 'sparse': + return self.readMatSparse(fh) + elif mattype == 'dense': + return self.readMatDense(fh) + elif mattype == 'scipy.sparse': + return self.readMatSciPy(fh) + else: + raise RuntimeError('Invalid matrix type requested: choose sparse/dense/scipy.sparse') + + @decorate_with_conf + def readIS(self, fh): + """Reads a PETSc Index Set from binary file handle, must be called after readObjectType()""" + + try: + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + v = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(v) == nz + except (MemoryError,IndexError): + raise IOError('Inconsistent or invalid IS data in file') + return v.view(IS) + + @decorate_with_conf + def writeIS(self, fh, anis): + """Writes a PETSc IS to binary file handle.""" + + metadata = np.array([IS._classid, len(anis)], dtype=self._inttype) + metadata.tofile(fh) + anis.astype(self._inttype).tofile(fh) + return + + @decorate_with_conf + def readObjectType(self, fid): + """Returns the next object type as a string in the file""" + try: + header = np.fromfile(fid, dtype=self._inttype, count=1)[0] + except (MemoryError, IndexError): + raise DoneWithFile + try: + objecttype = self._classid[header] + except KeyError: + raise IOError('Invalid PetscObject CLASSID or object not implemented for python') + return objecttype + + @decorate_with_conf + def readBinaryFile(self, fid, mattype='sparse'): + """Reads a PETSc binary file, returning a tuple of the contained objects. + + objects = self.readBinaryFile(fid, **kwargs) + + Input: + fid : either file name or handle to an open binary file. + + Output: + objects : tuple of objects representing the data in numpy arrays. + + Optional: + mattype : + 'sparse': Return matrices as raw CSR: (M, N), (row, col, val). + 'dense': Return matrices as MxN numpy arrays. + 'scipy.sparse': Return matrices as scipy.sparse objects. + """ + + close = False + + if isinstance(fid, basestring): + fid = open(fid, 'rb') + close = True + + objects = [] + try: + while True: + objecttype = self.readObjectType(fid) + + if objecttype == 'Vec': + objects.append(self.readVec(fid)) + elif objecttype == 'IS': + objects.append(self.readIS(fid)) + elif objecttype == 'Mat': + objects.append(self.readMat(fid,mattype)) + elif objecttype == 'Bag': + raise NotImplementedError('Bag Reader not yet implemented') + except DoneWithFile: + pass + finally: + if close: + fid.close() + + return tuple(objects) + + @decorate_with_conf + def writeBinaryFile(self, fid, objects): + """Writes a PETSc binary file containing the objects given. + + readBinaryFile(fid, objects) + + Input: + fid : either file handle to an open binary file, or filename. + objects : list of objects representing the data in numpy arrays, + which must be of type Vec, IS, MatSparse, or MatSciPy. + """ + close = False + if isinstance(fid, basestring): + fid = open(fid, 'wb') + close = True + + for petscobj in objects: + if (isinstance(petscobj, Vec)): + self.writeVec(fid, petscobj) + elif (isinstance(petscobj, IS)): + self.writeIS(fid, petscobj) + elif (isinstance(petscobj, MatSparse)): + self.writeMatSparse(fid, petscobj) + elif (isinstance(petscobj, MatDense)): + if close: + fid.close() + raise NotImplementedError('Writing a dense matrix is not yet supported') + else: + try: + self.writeMatSciPy(fid, petscobj) + except AssertionError: + if close: + fid.close() + raise TypeError('Object %s is not a valid PETSc object'%(petscobj.__repr__())) + if close: + fid.close() + return diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt new file mode 100644 index 00000000..ddb0d8b5 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt @@ -0,0 +1,12 @@ +To switch between 1D/2D polar and cartesian momentum space, the following changes need +to be made : + + +1. domain + - Change p2_start, p2_end and N_p2 +2. params + - Change p_space_grid + - Change p_dim (if switching between 1D and 2D representation in p-space) +3. initialize : No change +4. main : No change +5. boundary_conditions : No change diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/boundary_conditions.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/boundary_conditions.py new file mode 100644 index 00000000..762f5e79 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/boundary_conditions.py @@ -0,0 +1,107 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror+dirichlet' +in_q1_right = 'mirror+dirichlet' +in_q2_bottom = 'mirror' +in_q2_top = 'mirror' + +@af.broadcast +def f_left(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_in = params.vel_drift_x_in + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_right(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_out = params.vel_drift_x_out + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py new file mode 100644 index 00000000..9ebfec07 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py @@ -0,0 +1,14 @@ +import numpy as np +import params +import arrayfire as af + + +p2_start = -np.pi +p2_end = np.pi +N_p2 = 1024 +theta = \ + p2_start + (0.5 + np.arange(N_p2))*(p2_end - p2_start)/N_p2 + +theta = af.from_ndarray(theta) + +print (params.polygon (6, theta)) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py new file mode 100644 index 00000000..f22b4a55 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py @@ -0,0 +1,67 @@ +import numpy as np +import params + +q1_start = 0. +q1_end = 1.0 +N_q1 = 20 + +q2_start = 0. +q2_end = 1.25 +N_q2 = 25 + +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation +N_p1 = 1 # Set equal to 1 for 1D polar + +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space +#p1_start = [-0.04] +#p1_end = [0.04] + + +# In the 2D polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] + +# Uncomment the following for the 1D polar representation of momentum space +p1_start = [0.5*params.initial_mu] +p1_end = [1.5*params.initial_mu] + + +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero +N_p2 = 2048 + +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +#p2_start = [-0.04] +#p2_end = [0.04] + +# In the 2D polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +#p2_start = [-np.pi] +#p2_end = [np.pi] +p2_start = [-3.14159265359] +p2_end = [3.14159265359] + +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_density.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_density.py new file mode 100644 index 00000000..3697590e --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_density.py @@ -0,0 +1,122 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_potential.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_potential.py new file mode 100644 index 00000000..b50b3bf5 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/edge_potential.py @@ -0,0 +1,161 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#print("Reading sensor signal...") +print("Loading data...") +density = [] +edge_density = [] +for file_number, dump_file in enumerate(moment_files): + + print("File number = ", file_number, ' of ', moment_files.size) + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density.append(moments[:, :, 0]) + edge_density.append(density[file_number][0, sensor_1_left_indices]) + +density = np.array(density) +edge_density = np.array(edge_density) + +mean_density = np.mean(density) +max_density = np.max(density) +min_density = np.min(density) + +np.savetxt("edge_density.txt", edge_density) + +print("Dumping data...") +for file_number in yt.parallel_objects(range(density.shape[0])): + + print("File number = ", file_number, ' of ', moment_files.size) + + pl.semilogy(q2[sensor_1_left_indices], + density[file_number][0, sensor_1_left_indices], + ) + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.title(r'Time = ' + "%.2f"%(file_number*dt*dump_interval) + " ps") + + pl.xlim([sensor_1_left_start, sensor_1_left_end]) + #pl.ylim([min_density-mean_density, max_density-mean_density]) + #pl.ylim([0., np.log(max_density)]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$ ps, $\\tau_\mathrm{mr} = 3.0$ ps') + #pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.savefig('images/density_' + '%06d'%file_number + '.png') + pl.clf() + + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/enstrophy.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py new file mode 100644 index 00000000..fb8e8c88 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py @@ -0,0 +1,67 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 0.*q1 + params.vel_drift_y = 0.*q1 + params.phi = 0.*q1 + + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + params.vel_drift_x = 0.*q1 + 0e-3 + params.vel_drift_y = 0.*q1 + 0e-3 + params.j_x = 0.*q1 + params.j_y = 0.*q1 + + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + E_upper = params.E_band + params.charge[0]*params.phi + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + f = (1./(af.exp( (E_upper - params.vel_drift_x*p_x + - params.vel_drift_y*p_y + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/job_script b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/job_script new file mode 100644 index 00000000..c99c662e --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/job_script @@ -0,0 +1,4 @@ +#!/bin/bash +#SBATCH -p gpu -n 1 --gres=gpu:1 -c1 --hint=nomultithread -t 2-00:00 +# (Note: use one MPI process per gpu, update both gres and -n together; max 6) +time mpirun python main.py -snes_monitor -snes_max_it 1 -snes_lag_jacobian_persists TRUE -snes_lag_jacobian 1000000 -snes_atol 1e-50 -snes_rtol 1e-50 > output.txt diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py new file mode 100644 index 00000000..b9069f22 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py @@ -0,0 +1,171 @@ +import os +import arrayfire as af +import numpy as np +import math +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +from mpi4py import MPI +MPI.WTIME_IS_GLOBAL=True + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +#from bolt.lib.nonlinear.fields.fields.fields \ +# import fields_solver.compute_electrostatic_fields +from bolt.lib.utils.restart_latest import latest_output, format_time + +import domain +import boundary_conditions +import initialize +import params + +import bolt.src.electronic_boltzmann.advection_terms \ + as advection_terms +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator +import bolt.src.electronic_boltzmann.moment_defs \ + as moment_defs + + +# Create required folders if they do not exist already +#if not os.path.isdir("dump_f"): +# os.system("mkdir dump_f") +#if not os.path.isdir("dump_moments"): +# os.system("mkdir dump_moments") +#if not os.path.isdir("dump_lagrange_multipliers"): +# os.system("mkdir dump_lagrange_multipliers") +#if not os.path.isdir("images"): +# os.system("mkdir images") + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moment_defs + ) + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +N_g = domain.N_ghost +params.rank = nls._comm.rank + +# Time parameters: +dt = params.dt +t_final = params.t_final +params.current_time = time_elapsed = 0.0 +params.time_step = time_step = 0 +dump_counter = 0 +dump_time_array = [] + + +using_latest_restart = False +if(params.latest_restart == True): + latest_f, time_elapsed = latest_output('') + print(time_elapsed) + if(latest_f is not None and time_elapsed is not None): + nls.load_distribution_function(latest_f) + using_latest_restart = True + + +if using_latest_restart == False: + if(params.t_restart == 0 or params.latest_restart == True): + time_elapsed = 0 + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + dump_time_array.append(time_elapsed) + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + else: + time_elapsed = params.t_restart + formatted_time = format_time(time_elapsed) + nls.load_distribution_function('dump_f/t=' + formatted_time) + +# Checking that the file writing intervals are greater than dt: +assert(params.dt_dump_f >= dt) +assert(params.dt_dump_moments >= dt) +assert(params.dt_dump_fields >= dt) + + +#if (params.restart): +# nls.load_distribution_function(params.restart_file) + +density = nls.compute_moments('density') +print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "i\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + +nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) +while(time_elapsed < t_final): + + # Refine to machine error + if (time_step==0): + params.collision_nonlinear_iters = 10 + else: + params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters + + dump_steps = params.dump_steps + + if(params.dt_dump_moments != 0): + # We step by delta_dt to get the values at dt_dump + delta_dt = (1 - math.modf(time_elapsed/params.dt_dump_moments)[0]) \ + * params.dt_dump_moments + + if((delta_dt-dt)<1e-5): + nls.strang_timestep(delta_dt) + time_elapsed += delta_dt + formatted_time = format_time(time_elapsed) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y, + params.j_x, params.j_y], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + dump_time_array.append(time_elapsed) + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + + if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + + PETSc.Sys.Print("Time step =", time_step, ", Time =", time_elapsed) + + nls.strang_timestep(dt) + time_elapsed = time_elapsed + dt + time_step = time_step + 1 + params.time_step = time_step + params.current_time = time_elapsed + + # Floors + nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) + + density = nls.compute_moments('density') + print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + PETSc.Sys.Print("--------------------\n") + +nls.dump_distribution_function('dump_f/f_laststep') diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie.py new file mode 100644 index 00000000..1de644d7 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie.py @@ -0,0 +1,134 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q1_position, q2_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_debug.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_debug.py new file mode 100644 index 00000000..0b2c719d --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_debug.py @@ -0,0 +1,182 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(1): + for index_2 in range(N_q2): + + q1_position = index_1 + q2_position = index_2 + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = 1.#np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func - \ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..0d9b3d71 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/momentum_space_movie_zero_T.py @@ -0,0 +1,182 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = 1.#np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py new file mode 100644 index 00000000..dd4ca043 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py @@ -0,0 +1,163 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) + +source_start = 0.0#params.contact_start +source_end = 0.25#params.contact_end + +drain_start = 0.0#params.contact_start +drain_end = 0.25#params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#filepath = \ +#'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + +dt = 0.025/4#params.dt +#dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[:]): + + #file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 7) + #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + #lagrange_multipliers = h5f['lagrange_multipliers'][:] + #h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + print (vel_drift_x.shape) + print (density.shape) + + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py new file mode 100644 index 00000000..ad9e037f --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -0,0 +1,234 @@ +import numpy as np +import arrayfire as af + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +# Restart(Set to zero for no-restart): +restart = 0 +restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/f_eqbm.h5' +phi_restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/phi_eqbm.h5' +electrostatic_solver_every_nth_step = 1000000 +solve_for_equilibrium = 0 + + +# Time parameters: +dt = 0.025/4 # ps +t_final = 10. # ps + + +# File-writing Parameters: +dump_steps = 5 +dump_dist_after = 1600 +# Set to zero for no file-writing +dt_dump_f = dt #ps +# ALWAYS set dump moments and dump fields at same frequency: +dt_dump_moments = dt_dump_fields = 5*dt #ps + + +# Dimensionality considered in velocity space: +p_dim = 1 +p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 6 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 0.0 # um +contact_end = 0.25 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 12e-4 +initial_mu = 0.015 +vel_drift_x_in = 1e-4*fermi_velocity +vel_drift_x_out = 1e-4*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +j_x = None +j_y = None +phi = None # Electric potential in the plane of graphene sheet + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + +def band_energy(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + + E_upper = p*fermi_velocity + + af.eval(E_upper) + return(E_upper) + +def band_velocity(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # Here, p1 = radius and p2 = theta + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = hex_vel(p2) + #p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + v_f = fermi_velocity + + upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] + + af.eval(upper_band_velocity[0], upper_band_velocity[1]) + return(upper_band_velocity) + +def hex_vel (theta): + + res_x = np.zeros(theta.shape) + res_y = np.zeros(theta.shape) + + indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) + res_x[indices] = 1./2. + res_y[indices] = -np.sqrt(3)/2. + + indices = ((theta >= -2*np.pi/3) & (theta < -np.pi/3)) + res_x[indices] = 0. + res_y[indices] = -1. + + indices = ((theta >= -np.pi/3) & (theta < 0)) + res_x[indices] = -1./2 + res_y[indices] = np.sqrt(3)/2. + + indices = ((theta >= 0) & (theta < np.pi/3)) + res_x[indices] = -1./2. + res_y[indices] = np.sqrt(3)/2. + + indices = ((theta >= np.pi/3) & (theta < 2*np.pi/3)) + res_x[indices] = 0. + res_y[indices] = 1. + + indices = ((theta >= 2*np.pi/3) & (theta < np.pi)) + res_x[indices] = 1./2. + res_y[indices] = np.sqrt(3)/2. + + res_x = af.from_ndarray(res_x) + res_y = af.from_ndarray(res_y) + + return ([res_x, res_y]) + +def polygon(n, theta, rotation = 0, shift = 0): + ''' + Returns a polygon of unit side length on a polar coordinate system. + Inputs : + + n : number of sides of the polygon + thera : the angle grid + rotation : initial rotation + shift : initial shift in center ##TODO + ''' + + numerator = radius * np.cos(np.pi/n) + denominator = af.cos((theta - rotation) - (2*np.pi/n)*af.floor((n*(theta - rotation) + np.pi)/(2*np.pi))) + + result = numerator/denominator + + return (result) + + + +# Restart(Set to zero for no-restart): +latest_restart = True +t_restart = 0 + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/petsc_conf.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/petsc_conf.py new file mode 100755 index 00000000..22781ed2 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/petsc_conf.py @@ -0,0 +1,73 @@ +import warnings + +def get_conf(): + """Parses various PETSc configuration/include files to get data types. + + precision, indices, complexscalars = get_conf() + + Output: + precision: 'single', 'double', 'longlong' indicates precision of PetscScalar + indices: '32', '64' indicates bit-size of PetscInt + complex: True/False indicates whether PetscScalar is complex or not. + """ + + import sys, os + precision = None + indices = None + complexscalars = None + + if 'PETSC_DIR' in os.environ: + petscdir = os.environ['PETSC_DIR'] + else: + warnings.warn('PETSC_DIR env not set - unable to locate PETSc installation, using defaults') + return None, None, None + + if os.path.isfile(os.path.join(petscdir,'lib','petsc','conf','petscrules')): + # found prefix install + petscvariables = os.path.join(petscdir,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,'include','petscconf.h') + else: + if 'PETSC_ARCH' in os.environ: + petscarch = os.environ['PETSC_ARCH'] + if os.path.isfile(os.path.join(petscdir,petscarch,'lib','petsc','conf','petscrules')): + # found legacy install + petscvariables = os.path.join(petscdir,petscarch,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,petscarch,'include','petscconf.h') + else: + warnings.warn('Unable to locate PETSc installation in specified PETSC_DIR/PETSC_ARCH, using defaults') + return None, None, None + else: + warnings.warn('PETSC_ARCH env not set or incorrect PETSC_DIR is given - unable to locate PETSc installation, using defaults') + return None, None, None + + try: + fid = open(petscvariables, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('PETSC_PRECISION'): + precision = line.strip().split('=')[1].strip('\n').strip() + + fid.close() + + try: + fid = open(petscconfinclude, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('#define PETSC_USE_64BIT_INDICES 1'): + indices = '64bit' + elif line.startswith('#define PETSC_USE_COMPLEX 1'): + complexscalars = True + + if indices is None: + indices = '32bit' + if complexscalars is None: + complexscalars = False + fid.close() + + return precision, indices, complexscalars diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/phase_vs_y.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/post.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/signals.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/signals.py new file mode 100644 index 00000000..979640c3 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/signals.py @@ -0,0 +1,166 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +#filepath = '/home/mchandra/gitansh/zero_T/example_problems/electronic_boltzmann/graphene/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC' +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + +# Calculate the phase difference between input_signal_array and sensor_normalized +# Code copied from : +# https:/stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves + +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] + +#Force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) + +#pl.plot(time_array, input_signal_array) +pl.plot(time_array, sensor_normalized) +#pl.axhline(0, color='black', linestyle='--') + +#pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=1) +#pl.text(135, 1.14, '$\phi : %.2f \; rad$' %phase_diff) +pl.xlabel(r'Time (ps)') +#pl.xlim([0, 200]) +#pl.ylim([-1.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 0.5$ ps') +pl.savefig('images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/vorticity.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() + From bf7f3072f4527a02f684a812c8b03ed4b786f603 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 14:18:47 -0400 Subject: [PATCH 41/58] Improved readability of hexagon unit vector function --- .../params.py | 72 ++++++++++++------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index ad9e037f..984f57e5 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -150,8 +150,10 @@ def band_velocity(p1, p2): raise NotImplementedError('Unsupported coordinate system in p_space') p = af.sqrt(p_x**2. + p_y**2.) - p_hat = hex_vel(p2) - #p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + #TODO : Store the return value of hexagon_unit_vel in a variable + p_hat = hexagon_unit_vec(p2) + +#p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] v_f = fermi_velocity @@ -160,39 +162,61 @@ def band_velocity(p1, p2): af.eval(upper_band_velocity[0], upper_band_velocity[1]) return(upper_band_velocity) -def hex_vel (theta): - - res_x = np.zeros(theta.shape) - res_y = np.zeros(theta.shape) - +def hexagon_unit_vec (theta): + + vel_x = np.zeros(theta.shape) + vel_y = np.zeros(theta.shape) + +# #%%%%%%%%%%%%%%%%%%%* +# . . , * +# ( & (2) # . +# . . . ( +# / & # +# , (1) , . (3) ( +# -pi / & & +# /------------------/------------------( 0 +# pi . # # . +# / (6) / (4) # +# * % # +# * , # # +# * ( (5) / +# ,, %( +# ##################### + + # (1) indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) - res_x[indices] = 1./2. - res_y[indices] = -np.sqrt(3)/2. + vel_x[indices] = 1./2. + vel_y[indices] = -np.sqrt(3)/2. + # (2) indices = ((theta >= -2*np.pi/3) & (theta < -np.pi/3)) - res_x[indices] = 0. - res_y[indices] = -1. + vel_x[indices] = 0. + vel_y[indices] = -1. + # (3) indices = ((theta >= -np.pi/3) & (theta < 0)) - res_x[indices] = -1./2 - res_y[indices] = np.sqrt(3)/2. + vel_x[indices] = -1./2 + vel_y[indices] = np.sqrt(3)/2. + # (4) indices = ((theta >= 0) & (theta < np.pi/3)) - res_x[indices] = -1./2. - res_y[indices] = np.sqrt(3)/2. - + vel_x[indices] = -1./2. + vel_y[indices] = np.sqrt(3)/2. + + # (5) indices = ((theta >= np.pi/3) & (theta < 2*np.pi/3)) - res_x[indices] = 0. - res_y[indices] = 1. - + vel_x[indices] = 0. + vel_y[indices] = 1. + + # (6) indices = ((theta >= 2*np.pi/3) & (theta < np.pi)) - res_x[indices] = 1./2. - res_y[indices] = np.sqrt(3)/2. + vel_x[indices] = 1./2. + vel_y[indices] = np.sqrt(3)/2. - res_x = af.from_ndarray(res_x) - res_y = af.from_ndarray(res_y) + vel_x = af.from_ndarray(vel_x) + vel_y = af.from_ndarray(vel_y) - return ([res_x, res_y]) + return ([vel_x, vel_y]) def polygon(n, theta, rotation = 0, shift = 0): ''' From 9cdbfee02e113b4c703579ec2e0946c888eca417 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 15:04:27 -0400 Subject: [PATCH 42/58] Fixed hexagon ascii image --- .../params.py | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 984f57e5..3fdaed20 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -138,6 +138,7 @@ def band_energy(p1, p2): return(E_upper) def band_velocity(p1, p2): + # TODO :This function is only meant to be called once to initialize the vel vectors if (p_space_grid == 'cartesian'): p_x = p1 @@ -149,39 +150,44 @@ def band_velocity(p1, p2): else : raise NotImplementedError('Unsupported coordinate system in p_space') - p = af.sqrt(p_x**2. + p_y**2.) - #TODO : Store the return value of hexagon_unit_vel in a variable - p_hat = hexagon_unit_vec(p2) - -#p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] - +# p = af.sqrt(p_x**2. + p_y**2.) +# p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] +# v_f = fermi_velocity +# +# upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] +# +# af.eval(upper_band_velocity[0], upper_band_velocity[1]) - upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] + v_f_hat = normal_to_hexagon_unit_vec(p2) + upper_band_velocity = [v_f * v_f_hat[0], v_f * v_f_hat[1]] - af.eval(upper_band_velocity[0], upper_band_velocity[1]) return(upper_band_velocity) -def hexagon_unit_vec (theta): +def normal_to_hexagon_unit_vec(theta): vel_x = np.zeros(theta.shape) vel_y = np.zeros(theta.shape) +# +# 2*pi/3 pi/3 # #%%%%%%%%%%%%%%%%%%%* # . . , * -# ( & (2) # . +# ( & (5) # . # . . . ( # / & # -# , (1) , . (3) ( -# -pi / & & +# , (6) , . (4) ( +# pi / & & # /------------------/------------------( 0 -# pi . # # . -# / (6) / (4) # +# -pi . # # . +# / (1) / (3) # # * % # # * , # # -# * ( (5) / +# * ( (2) / # ,, %( # ##################### +# -2*pi/3 -pi/3 +# # (1) indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) From dbd975702ff68de1c15c4aa7acf0b2dc5f202222 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 15:18:09 -0400 Subject: [PATCH 43/58] Reorder sectors in hexagon --- .../params.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 3fdaed20..6fd983d2 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -173,51 +173,51 @@ def normal_to_hexagon_unit_vec(theta): # 2*pi/3 pi/3 # #%%%%%%%%%%%%%%%%%%%* # . . , * -# ( & (5) # . +# ( & (2) # . # . . . ( # / & # -# , (6) , . (4) ( +# , (3) , . (1) ( # pi / & & # /------------------/------------------( 0 # -pi . # # . -# / (1) / (3) # +# / (4) / (6) # # * % # # * , # # -# * ( (2) / +# * ( (5) / # ,, %( # ##################### # -2*pi/3 -pi/3 # # (1) - indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) - vel_x[indices] = 1./2. - vel_y[indices] = -np.sqrt(3)/2. - - # (2) - indices = ((theta >= -2*np.pi/3) & (theta < -np.pi/3)) - vel_x[indices] = 0. - vel_y[indices] = -1. - - # (3) - indices = ((theta >= -np.pi/3) & (theta < 0)) - vel_x[indices] = -1./2 - vel_y[indices] = np.sqrt(3)/2. - - # (4) indices = ((theta >= 0) & (theta < np.pi/3)) vel_x[indices] = -1./2. vel_y[indices] = np.sqrt(3)/2. - # (5) + # (2) indices = ((theta >= np.pi/3) & (theta < 2*np.pi/3)) vel_x[indices] = 0. vel_y[indices] = 1. - # (6) + # (3) indices = ((theta >= 2*np.pi/3) & (theta < np.pi)) vel_x[indices] = 1./2. vel_y[indices] = np.sqrt(3)/2. + + # (4) + indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) + vel_x[indices] = 1./2. + vel_y[indices] = -np.sqrt(3)/2. + + # (5) + indices = ((theta >= -2*np.pi/3) & (theta < -np.pi/3)) + vel_x[indices] = 0. + vel_y[indices] = -1. + + # (6) + indices = ((theta >= -np.pi/3) & (theta < 0)) + vel_x[indices] = -1./2 + vel_y[indices] = np.sqrt(3)/2. vel_x = af.from_ndarray(vel_x) vel_y = af.from_ndarray(vel_y) From f1b33035badc598a84dc0a991958bbefad898f86 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 15:43:10 -0400 Subject: [PATCH 44/58] Bugfix, normal to hexagon unit vector --- .../params.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 6fd983d2..c18c8958 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -191,8 +191,8 @@ def normal_to_hexagon_unit_vec(theta): # (1) indices = ((theta >= 0) & (theta < np.pi/3)) - vel_x[indices] = -1./2. - vel_y[indices] = np.sqrt(3)/2. + vel_x[indices] = np.cos(np.pi/6) + vel_y[indices] = np.sin(np.pi/6) # (2) indices = ((theta >= np.pi/3) & (theta < 2*np.pi/3)) @@ -201,13 +201,13 @@ def normal_to_hexagon_unit_vec(theta): # (3) indices = ((theta >= 2*np.pi/3) & (theta < np.pi)) - vel_x[indices] = 1./2. - vel_y[indices] = np.sqrt(3)/2. + vel_x[indices] = -np.cos(np.pi/6) + vel_y[indices] = np.sin(np.pi/6) # (4) indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) - vel_x[indices] = 1./2. - vel_y[indices] = -np.sqrt(3)/2. + vel_x[indices] = -np.cos(np.pi/6) + vel_y[indices] = -np.sin(np.pi/6) # (5) indices = ((theta >= -2*np.pi/3) & (theta < -np.pi/3)) @@ -216,8 +216,8 @@ def normal_to_hexagon_unit_vec(theta): # (6) indices = ((theta >= -np.pi/3) & (theta < 0)) - vel_x[indices] = -1./2 - vel_y[indices] = np.sqrt(3)/2. + vel_x[indices] = np.cos(np.pi/6) + vel_y[indices] = -np.sin(np.pi/6) vel_x = af.from_ndarray(vel_x) vel_y = af.from_ndarray(vel_y) From 667dfe7122ce32d5117357a6936fb3e10371b96b Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 17:25:45 -0400 Subject: [PATCH 45/58] Hexagonal band_energy --- .../params.py | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index c18c8958..e6e41c6a 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -132,7 +132,8 @@ def band_energy(p1, p2): p = af.sqrt(p_x**2. + p_y**2.) - E_upper = p*fermi_velocity + #E_upper = p*fermi_velocity + E_upper = initial_mu * polygon(6, p2, rotation = np.pi/6) af.eval(E_upper) return(E_upper) @@ -190,35 +191,54 @@ def normal_to_hexagon_unit_vec(theta): # # (1) - indices = ((theta >= 0) & (theta < np.pi/3)) - vel_x[indices] = np.cos(np.pi/6) - vel_y[indices] = np.sin(np.pi/6) + start_theta = 0.0 + end_theta = np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x[indices] = np.cos(mid_theta) + vel_y[indices] = np.sin(mid_theta) # (2) - indices = ((theta >= np.pi/3) & (theta < 2*np.pi/3)) - vel_x[indices] = 0. - vel_y[indices] = 1. + start_theta = np.pi/3 + end_theta = 2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x[indices] = np.cos(mid_theta) + vel_y[indices] = np.sin(mid_theta) # (3) - indices = ((theta >= 2*np.pi/3) & (theta < np.pi)) - vel_x[indices] = -np.cos(np.pi/6) - vel_y[indices] = np.sin(np.pi/6) + start_theta = 2*np.pi/3 + end_theta = np.pi + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x[indices] = np.cos(mid_theta) + vel_y[indices] = np.sin(mid_theta) # (4) - indices = ((theta >= -np.pi) & (theta < -2*np.pi/3)) - vel_x[indices] = -np.cos(np.pi/6) - vel_y[indices] = -np.sin(np.pi/6) + start_theta = -np.pi + end_theta = -2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x[indices] = np.cos(mid_theta) + vel_y[indices] = np.sin(mid_theta) # (5) - indices = ((theta >= -2*np.pi/3) & (theta < -np.pi/3)) - vel_x[indices] = 0. - vel_y[indices] = -1. + start_theta = -2*np.pi/3 + end_theta = -np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x[indices] = np.cos(mid_theta) + vel_y[indices] = np.sin(mid_theta) # (6) - indices = ((theta >= -np.pi/3) & (theta < 0)) - vel_x[indices] = np.cos(np.pi/6) - vel_y[indices] = -np.sin(np.pi/6) - + start_theta = -np.pi/3 + end_theta = 0 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x[indices] = np.cos(mid_theta) + vel_y[indices] = np.sin(mid_theta) + + # Convert to arrayfire arrays vel_x = af.from_ndarray(vel_x) vel_y = af.from_ndarray(vel_y) @@ -226,7 +246,7 @@ def normal_to_hexagon_unit_vec(theta): def polygon(n, theta, rotation = 0, shift = 0): ''' - Returns a polygon of unit side length on a polar coordinate system. + Returns a polygon of unit edge length on a polar coordinate system. Inputs : n : number of sides of the polygon @@ -235,7 +255,7 @@ def polygon(n, theta, rotation = 0, shift = 0): shift : initial shift in center ##TODO ''' - numerator = radius * np.cos(np.pi/n) + numerator = np.cos(np.pi/n) denominator = af.cos((theta - rotation) - (2*np.pi/n)*af.floor((n*(theta - rotation) + np.pi)/(2*np.pi))) result = numerator/denominator From e7cbfccbdae3087365be20e7598dcb7dd07cbb26 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sat, 28 Mar 2020 17:26:54 -0400 Subject: [PATCH 46/58] check updated to output a plot --- .../pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py index 9ebfec07..50bdf0af 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py @@ -1,6 +1,7 @@ import numpy as np import params import arrayfire as af +import pylab as pl p2_start = -np.pi @@ -11,4 +12,8 @@ theta = af.from_ndarray(theta) -print (params.polygon (6, theta)) +hexa = params.polygon(6, theta, rotation = np.pi/6) +hexa = hexa.to_ndarray() + +pl.polar(theta, hexa) +pl.savefig("images/test.png") From dbbc9f1ff6ef4776f71100d1032946f7028e028d Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sun, 29 Mar 2020 10:46:50 -0400 Subject: [PATCH 47/58] Fixed indices issue, added test funcs, working version --- .../params.py | 87 +++++++++++++++---- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index e6e41c6a..3c3af250 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -165,10 +165,65 @@ def band_velocity(p1, p2): return(upper_band_velocity) +def normal_to_circle_unit_vec(theta): + + vel_x = 0.*theta + vel_y = 0.*theta + + # (1) + start_theta = 0.0 + end_theta = np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (2) + start_theta = np.pi/3 + end_theta = 2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (3) + start_theta = 2*np.pi/3 + end_theta = np.pi + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (4) + start_theta = -np.pi + end_theta = -2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (5) + start_theta = -2*np.pi/3 + end_theta = -np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (6) + start_theta = -np.pi/3 + end_theta = 0 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + return ([vel_x, vel_y]) + def normal_to_hexagon_unit_vec(theta): - vel_x = np.zeros(theta.shape) - vel_y = np.zeros(theta.shape) + vel_x = 0.*theta + vel_y = 0.*theta # # 2*pi/3 pi/3 @@ -195,52 +250,48 @@ def normal_to_hexagon_unit_vec(theta): end_theta = np.pi/3 mid_theta = 0.5*(end_theta + start_theta) indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x[indices] = np.cos(mid_theta) - vel_y[indices] = np.sin(mid_theta) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) # (2) start_theta = np.pi/3 end_theta = 2*np.pi/3 mid_theta = 0.5*(end_theta + start_theta) indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x[indices] = np.cos(mid_theta) - vel_y[indices] = np.sin(mid_theta) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) # (3) start_theta = 2*np.pi/3 end_theta = np.pi mid_theta = 0.5*(end_theta + start_theta) indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x[indices] = np.cos(mid_theta) - vel_y[indices] = np.sin(mid_theta) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) # (4) start_theta = -np.pi end_theta = -2*np.pi/3 mid_theta = 0.5*(end_theta + start_theta) indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x[indices] = np.cos(mid_theta) - vel_y[indices] = np.sin(mid_theta) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) # (5) start_theta = -2*np.pi/3 end_theta = -np.pi/3 mid_theta = 0.5*(end_theta + start_theta) indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x[indices] = np.cos(mid_theta) - vel_y[indices] = np.sin(mid_theta) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) # (6) start_theta = -np.pi/3 end_theta = 0 mid_theta = 0.5*(end_theta + start_theta) indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x[indices] = np.cos(mid_theta) - vel_y[indices] = np.sin(mid_theta) - - # Convert to arrayfire arrays - vel_x = af.from_ndarray(vel_x) - vel_y = af.from_ndarray(vel_y) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) return ([vel_x, vel_y]) From 2ffa4cae8f547c61325d1e5d61814944d910225e Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Sun, 29 Mar 2020 14:38:57 -0400 Subject: [PATCH 48/58] Moved unit_vec and polygon functions to lib/utils --- bolt/lib/utils/polygon.py | 22 +++ bolt/lib/utils/unit_vectors.py | 136 ++++++++++++++ .../README.txt | 6 +- .../params.py | 169 ++---------------- 4 files changed, 173 insertions(+), 160 deletions(-) create mode 100644 bolt/lib/utils/polygon.py create mode 100644 bolt/lib/utils/unit_vectors.py diff --git a/bolt/lib/utils/polygon.py b/bolt/lib/utils/polygon.py new file mode 100644 index 00000000..51db41e6 --- /dev/null +++ b/bolt/lib/utils/polygon.py @@ -0,0 +1,22 @@ +import arrayfire as af +import numpy as np + +def polygon(n, theta, rotation = 0, shift = 0): + ''' + Returns a polygon of unit edge length on a polar coordinate system. + Inputs : + + n : number of sides of the polygon + thera : the angle grid + rotation : initial rotation + shift : initial shift in center ##TODO + ''' + + numerator = np.cos(np.pi/n) + denominator = af.cos((theta - rotation) - (2*np.pi/n)*af.floor((n*(theta - rotation) + np.pi)/(2*np.pi))) + + result = numerator/denominator + + return (result) + + diff --git a/bolt/lib/utils/unit_vectors.py b/bolt/lib/utils/unit_vectors.py new file mode 100644 index 00000000..7e8d637b --- /dev/null +++ b/bolt/lib/utils/unit_vectors.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np + + +def normal_to_circle_unit_vec(theta): + + vel_x = 0.*theta + vel_y = 0.*theta + + # (1) + start_theta = 0.0 + end_theta = np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + #(1-indices) is equivalent to complementing indices + + + # (2) + start_theta = np.pi/3 + end_theta = 2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (3) + start_theta = 2*np.pi/3 + end_theta = np.pi + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (4) + start_theta = -np.pi + end_theta = -2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (5) + start_theta = -2*np.pi/3 + end_theta = -np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + # (6) + start_theta = -np.pi/3 + end_theta = 0 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*af.cos(theta) + vel_y = (1-indices)*vel_y + indices*af.sin(theta) + + return ([vel_x, vel_y]) + + +def normal_to_hexagon_unit_vec(theta): + + vel_x = 0.*theta + vel_y = 0.*theta + +# +# 2*pi/3 pi/3 +# #%%%%%%%%%%%%%%%%%%%* +# . . , * +# ( & (2) # . +# . . . ( +# / & # +# , (3) , . (1) ( +# pi / & & +# /------------------/------------------( 0 +# -pi . # # . +# / (4) / (6) # +# * % # +# * , # # +# * ( (5) / +# ,, %( +# ##################### +# -2*pi/3 -pi/3 +# + + # (1) + start_theta = 0.0 + end_theta = np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (2) + start_theta = np.pi/3 + end_theta = 2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (3) + start_theta = 2*np.pi/3 + end_theta = np.pi + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (4) + start_theta = -np.pi + end_theta = -2*np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (5) + start_theta = -2*np.pi/3 + end_theta = -np.pi/3 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (6) + start_theta = -np.pi/3 + end_theta = 0 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + return ([vel_x, vel_y]) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt index ddb0d8b5..057b5bb9 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/README.txt @@ -9,4 +9,8 @@ to be made : - Change p_dim (if switching between 1D and 2D representation in p-space) 3. initialize : No change 4. main : No change -5. boundary_conditions : No change +i5. boundary_conditions : No change + + + +PdCoO2 works only with the polar2D grid in momentum space for the moment. diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 3c3af250..b18b2c7b 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -1,6 +1,9 @@ import numpy as np import arrayfire as af +from bolt.lib.utils.polygon import polygon +from bolt.lib.utils.unit_vectors import normal_to_hexagon_unit_vec + instantaneous_collisions = False #TODO : Remove from lib hybrid_model_enabled = False #TODO : Remove from lib source_enabled = True @@ -32,17 +35,12 @@ riemann_solver_in_q = 'upwind-flux' riemann_solver_in_p = 'upwind-flux' -# Restart(Set to zero for no-restart): -restart = 0 -restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/f_eqbm.h5' -phi_restart_file = '/home/mani/work/quazar_research/bolt/example_problems/electronic_boltzmann/graphene/dumps/phi_eqbm.h5' electrostatic_solver_every_nth_step = 1000000 -solve_for_equilibrium = 0 # Time parameters: dt = 0.025/4 # ps -t_final = 10. # ps +t_final = 100. # ps # File-writing Parameters: @@ -58,6 +56,7 @@ p_dim = 1 p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids # Set p-space start and end points accordingly in domain.py +#TODO : Use only polar2D for PdCoO2 # Number of devices(GPUs/Accelerators) on each node: num_devices = 6 @@ -130,10 +129,12 @@ def band_energy(p1, p2): else : raise NotImplementedError('Unsupported coordinate system in p_space') - p = af.sqrt(p_x**2. + p_y**2.) - + # In polar2D coordinates, p1 = radius and p2 = theta + + #p = af.sqrt(p_x**2. + p_y**2.) #E_upper = p*fermi_velocity - E_upper = initial_mu * polygon(6, p2, rotation = np.pi/6) + n = 6 #number of sides of the polygon + E_upper = initial_mu * polygon(n, p2, rotation = np.pi/6) af.eval(E_upper) return(E_upper) @@ -165,156 +166,6 @@ def band_velocity(p1, p2): return(upper_band_velocity) -def normal_to_circle_unit_vec(theta): - - vel_x = 0.*theta - vel_y = 0.*theta - - # (1) - start_theta = 0.0 - end_theta = np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*af.cos(theta) - vel_y = (1-indices)*vel_y + indices*af.sin(theta) - - # (2) - start_theta = np.pi/3 - end_theta = 2*np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*af.cos(theta) - vel_y = (1-indices)*vel_y + indices*af.sin(theta) - - # (3) - start_theta = 2*np.pi/3 - end_theta = np.pi - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*af.cos(theta) - vel_y = (1-indices)*vel_y + indices*af.sin(theta) - - # (4) - start_theta = -np.pi - end_theta = -2*np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*af.cos(theta) - vel_y = (1-indices)*vel_y + indices*af.sin(theta) - - # (5) - start_theta = -2*np.pi/3 - end_theta = -np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*af.cos(theta) - vel_y = (1-indices)*vel_y + indices*af.sin(theta) - - # (6) - start_theta = -np.pi/3 - end_theta = 0 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*af.cos(theta) - vel_y = (1-indices)*vel_y + indices*af.sin(theta) - - return ([vel_x, vel_y]) - -def normal_to_hexagon_unit_vec(theta): - - vel_x = 0.*theta - vel_y = 0.*theta - -# -# 2*pi/3 pi/3 -# #%%%%%%%%%%%%%%%%%%%* -# . . , * -# ( & (2) # . -# . . . ( -# / & # -# , (3) , . (1) ( -# pi / & & -# /------------------/------------------( 0 -# -pi . # # . -# / (4) / (6) # -# * % # -# * , # # -# * ( (5) / -# ,, %( -# ##################### -# -2*pi/3 -pi/3 -# - - # (1) - start_theta = 0.0 - end_theta = np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) - vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) - - # (2) - start_theta = np.pi/3 - end_theta = 2*np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) - vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) - - # (3) - start_theta = 2*np.pi/3 - end_theta = np.pi - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) - vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) - - # (4) - start_theta = -np.pi - end_theta = -2*np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) - vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) - - # (5) - start_theta = -2*np.pi/3 - end_theta = -np.pi/3 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) - vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) - - # (6) - start_theta = -np.pi/3 - end_theta = 0 - mid_theta = 0.5*(end_theta + start_theta) - indices = ((theta >= start_theta) & (theta < end_theta)) - vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) - vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) - - return ([vel_x, vel_y]) - -def polygon(n, theta, rotation = 0, shift = 0): - ''' - Returns a polygon of unit edge length on a polar coordinate system. - Inputs : - - n : number of sides of the polygon - thera : the angle grid - rotation : initial rotation - shift : initial shift in center ##TODO - ''' - - numerator = np.cos(np.pi/n) - denominator = af.cos((theta - rotation) - (2*np.pi/n)*af.floor((n*(theta - rotation) + np.pi)/(2*np.pi))) - - result = numerator/denominator - - return (result) - - - # Restart(Set to zero for no-restart): latest_restart = True t_restart = 0 From a64896334451ee3b26bbf736ecf40f572fd02938 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 30 Mar 2020 14:29:24 -0400 Subject: [PATCH 49/58] Moved polygon and unit vec functions to src/electronic_boltzmann/utils --- .../electronic_boltzmann}/utils/polygon.py | 0 .../utils/unit_vectors.py | 84 +++++++++++++++++++ .../params.py | 6 +- 3 files changed, 87 insertions(+), 3 deletions(-) rename bolt/{lib => src/electronic_boltzmann}/utils/polygon.py (100%) rename bolt/{lib => src/electronic_boltzmann}/utils/unit_vectors.py (60%) diff --git a/bolt/lib/utils/polygon.py b/bolt/src/electronic_boltzmann/utils/polygon.py similarity index 100% rename from bolt/lib/utils/polygon.py rename to bolt/src/electronic_boltzmann/utils/polygon.py diff --git a/bolt/lib/utils/unit_vectors.py b/bolt/src/electronic_boltzmann/utils/unit_vectors.py similarity index 60% rename from bolt/lib/utils/unit_vectors.py rename to bolt/src/electronic_boltzmann/utils/unit_vectors.py index 7e8d637b..d0803deb 100644 --- a/bolt/lib/utils/unit_vectors.py +++ b/bolt/src/electronic_boltzmann/utils/unit_vectors.py @@ -134,3 +134,87 @@ def normal_to_hexagon_unit_vec(theta): vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) return ([vel_x, vel_y]) + + +def normal_to_hexagon_unit_vec_rotated(theta): + + vel_x = 0.*theta + vel_y = 0.*theta + +# pi/2 +# (@@ +# &@ @ @( +# @# @ %@ +# 5pi/6 .@, (3) @ (2) .@. pi/6 +# @ *@ @ @/ ,* +# @ @( @ /@ ,* +# pi @ (4) %@@@& (1) ,* +# -pi @ .@, @ .@, ,* +# @ %@ @ @& ,* +# @ @( (5) @ (6) /@ ,* +# /@ @ %@ -pi/6 +#-5pi/6 @/ @ @( +# &@ @ *@ +# . +# -pi/2 + + # (1) + start_theta = -np.pi/6 + end_theta = np.pi/6 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (2) + start_theta = np.pi/6 + end_theta = np.pi/2 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (3) + start_theta = np.pi/2 + end_theta = 5*np.pi/6 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + + # Sector 4 needs to be handled as a special case, because the domain + # of theta ranges from -pi to pi. There is a break within sector 4. + # (4)a + start_theta = 5*np.pi/6 + end_theta = np.pi + mid_theta = np.pi#0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (4)b + start_theta = -np.pi + end_theta = -5*np.pi/6 + mid_theta = -np.pi#0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (5) + start_theta = -5*np.pi/6 + end_theta = -np.pi/2 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + # (6) + start_theta = -np.pi/2 + end_theta = -np.pi/6 + mid_theta = 0.5*(end_theta + start_theta) + indices = ((theta >= start_theta) & (theta < end_theta)) + vel_x = (1-indices)*vel_x + indices*np.cos(mid_theta) + vel_y = (1-indices)*vel_y + indices*np.sin(mid_theta) + + return ([vel_x, vel_y]) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index b18b2c7b..49e027e7 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -1,8 +1,8 @@ import numpy as np import arrayfire as af -from bolt.lib.utils.polygon import polygon -from bolt.lib.utils.unit_vectors import normal_to_hexagon_unit_vec +from bolt.src.electronic_boltzmann.utils.polygon import polygon +from bolt.src.electronic_boltzmann.utils.unit_vectors import normal_to_hexagon_unit_vec instantaneous_collisions = False #TODO : Remove from lib hybrid_model_enabled = False #TODO : Remove from lib @@ -47,7 +47,7 @@ dump_steps = 5 dump_dist_after = 1600 # Set to zero for no file-writing -dt_dump_f = dt #ps +dt_dump_f = 1000*dt #ps # ALWAYS set dump moments and dump fields at same frequency: dt_dump_moments = dt_dump_fields = 5*dt #ps From 69d1aec1b2d00f5c4ba67df3faba7ef40970347b Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Tue, 7 Apr 2020 15:18:19 -0400 Subject: [PATCH 50/58] Changes to clean up the code, improve conceptual understanding --- bolt/lib/nonlinear/compute_moments.py | 4 +- .../collision_operator.py | 624 +----------------- .../f_local_equilibrium.py | 348 ++++++++++ .../f_local_equilibrium_zero_T.py | 310 +++++++++ bolt/src/electronic_boltzmann/moment_defs.py | 13 - bolt/src/electronic_boltzmann/moments.py | 13 + bolt/src/utils/integral_over_p.py | 7 + .../check.py | 29 +- .../initialize.py | 33 +- .../main.py | 6 +- .../params.py | 140 +++- 11 files changed, 869 insertions(+), 658 deletions(-) create mode 100644 bolt/src/electronic_boltzmann/f_local_equilibrium.py create mode 100644 bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py delete mode 100644 bolt/src/electronic_boltzmann/moment_defs.py create mode 100644 bolt/src/electronic_boltzmann/moments.py create mode 100644 bolt/src/utils/integral_over_p.py diff --git a/bolt/lib/nonlinear/compute_moments.py b/bolt/lib/nonlinear/compute_moments.py index fcea88cc..e66dbcf2 100644 --- a/bolt/lib/nonlinear/compute_moments.py +++ b/bolt/lib/nonlinear/compute_moments.py @@ -39,11 +39,11 @@ def compute_moments(self, moment_name, f=None): if(f is None): f = self.f - measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 + #measure = (4./(2.*np.pi*self.physical_system.params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 moment = af.broadcast(getattr(self.physical_system.moments, moment_name - ), f, p1, p2, p3, measure + ), f, p1, p2, p3, self.physical_system.params.integral_measure ) af.eval(moment) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 0c55942c..6b3ebe9e 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -3,588 +3,16 @@ from petsc4py import PETSc import numpy as np import arrayfire as af -from .matrix_inverse import inverse_4x4_matrix -from .matrix_inverse import inverse_3x3_matrix -import domain - -@af.broadcast -def f0_defect_constant_T(f, p_x, p_y, p_z, params): - """ - Return the local equilibrium distribution corresponding to the tau_D - relaxation time when lattice temperature, T, is set to constant. - Parameters: - ----------- - f : Distribution function array - shape:(N_v, N_s, N_q1, N_q2) - - p_x : The array that holds data for the v1 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_y : The array that holds data for the v2 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_z : The array that holds data for the v3 dimension in v-space - shape:(N_v, N_s, 1, 1) - - params: The parameters file/object that is originally declared by the user. - This can be used to inject other functions/attributes into the function - - """ - - mu = params.mu - T = params.T - - for n in range(params.collision_nonlinear_iters): - - E_upper = params.E_band - k = params.boltzmann_constant - - tmp = ((E_upper - mu)/(k*T)) - denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) - - # TODO: Multiply with the integral measure dp_x * dp_y - a00 = af.sum(T / denominator, 0) - - fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) - af.eval(fermi_dirac) - - zeroth_moment = f - fermi_dirac - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - - N_g = domain.N_ghost - error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) - - print(" rank = ", params.rank, - "||residual_defect|| = ", error_mass_conservation - ) - - res = eqn_mass_conservation - dres_dmu = -a00 - - delta_mu = -res/dres_dmu - - mu = mu + delta_mu - - af.eval(mu) - - # Solved for mu. Now store in params - params.mu = mu - - # Print final residual - fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) - af.eval(fermi_dirac) - - zeroth_moment = f - fermi_dirac - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - - N_g = domain.N_ghost - error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) - - print(" rank = ", params.rank, - "||residual_defect|| = ", error_mass_conservation - ) - print(" rank = ", params.rank, - "mu = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), - "T = ", af.mean(params.T[0, 0, N_g:-N_g, N_g:-N_g]) - ) - PETSc.Sys.Print(" ------------------") - - return(fermi_dirac) - - -# Using af.broadcast, since p_x, p_y, p_z are of size (1, 1, Np_x*Np_y*Np_z) -# All moment quantities are of shape (Nq1, Nq2) -# By wrapping with af.broadcast, we can perform batched operations -# on arrays of different sizes. -@af.broadcast -def f0_defect(f, p_x, p_y, p_z, params): - """ - Return the local equilibrium distribution corresponding to the tau_D - relaxation time. - Parameters: - ----------- - f : Distribution function array - shape:(N_v, N_s, N_q1, N_q2) - - p_x : The array that holds data for the v1 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_y : The array that holds data for the v2 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_z : The array that holds data for the v3 dimension in v-space - shape:(N_v, N_s, 1, 1) - - params: The parameters file/object that is originally declared by the user. - This can be used to inject other functions/attributes into the function - - """ - - # Initial guess - mu = params.mu - T = params.T - - for n in range(params.collision_nonlinear_iters): - - E_upper = params.E_band - k = params.boltzmann_constant - - tmp = ((E_upper - mu)/(k*T)) - denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) - - # TODO: Multiply with the integral measure dp_x * dp_y - a00 = af.sum(T / denominator, 0) - a01 = af.sum((E_upper - mu) / denominator, 0) - a10 = af.sum(E_upper*T / denominator, 0) - a11 = af.sum(E_upper*(E_upper - mu) / denominator, 0) - - # Solve Ax = b - # where A == Jacobian, - # x == delta guess (correction to guess), - # b = -residual - - fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) - af.eval(fermi_dirac) - - zeroth_moment = f - fermi_dirac - second_moment = E_upper*(f - fermi_dirac) - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - eqn_energy_conservation = af.sum(second_moment, 0) - - N_g = domain.N_ghost - error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) - error_energy_conservation = af.max(af.abs(eqn_energy_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) - - residual = [eqn_mass_conservation, eqn_energy_conservation] - error_norm = np.max([af.max(af.abs(residual[0])), - af.max(af.abs(residual[1]))] - ) - print(" ||residual_defect|| = ", error_norm) - -# if (error_norm < 1e-9): -# params.mu = mu -# params.T = T -# return(fermi_dirac) - - b0 = eqn_mass_conservation - b1 = eqn_energy_conservation - - det = a01*a10 - a00*a11 - delta_mu = -(a11*b0 - a01*b1)/det - delta_T = (a10*b0 - a00*b1)/det - - mu = mu + delta_mu - T = T + delta_T - - af.eval(mu, T) - - # Solved for (mu, T). Now store in params - params.mu = mu - params.T = T - - # Print final residual - fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) - af.eval(fermi_dirac) - - zeroth_moment = f - fermi_dirac - second_moment = E_upper*(f - fermi_dirac) - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - eqn_energy_conservation = af.sum(second_moment, 0) - - residual = [eqn_mass_conservation, eqn_energy_conservation] - error_norm = np.max([af.max(af.abs(residual[0])), - af.max(af.abs(residual[1]))] - ) - print(" ||residual_defect|| = ", error_norm) - print(" mu = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), - "T = ", af.mean(params.T[0, 0, N_g:-N_g, N_g:-N_g]) - ) - print(" ------------------") - - return(fermi_dirac) - -@af.broadcast -def f0_ee(f, p_x, p_y, p_z, params): - """ - Return the local equilibrium distribution corresponding to the tau_ee - relaxation time. - Parameters: - ----------- - f : Distribution function array - shape:(N_v, N_s, N_q1, N_q2) - - p_x : The array that holds data for the v1 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_y : The array that holds data for the v2 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_z : The array that holds data for the v3 dimension in v-space - shape:(N_v, N_s, 1, 1) - - params: The parameters file/object that is originally declared by the user. - This can be used to inject other functions/attributes into the function - - """ - - # Initial guess - mu_ee = params.mu_ee - T_ee = params.T_ee - vel_drift_x = params.vel_drift_x - vel_drift_y = params.vel_drift_y - - for n in range(params.collision_nonlinear_iters): - - E_upper = params.E_band - k = params.boltzmann_constant - - tmp1 = (E_upper - mu_ee - p_x*vel_drift_x - p_y*vel_drift_y) - tmp = (tmp1/(k*T_ee)) - denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) - - a_0 = T_ee / denominator - a_1 = tmp1 / denominator - a_2 = T_ee * p_x / denominator - a_3 = T_ee * p_y / denominator - - af.eval(a_0, a_1, a_2, a_3) - - # TODO: Multiply with the integral measure dp_x * dp_y - a_00 = af.sum(a_0, 0) - a_01 = af.sum(a_1, 0) - a_02 = af.sum(a_2, 0) - a_03 = af.sum(a_3, 0) - - a_10 = af.sum(E_upper * a_0, 0) - a_11 = af.sum(E_upper * a_1, 0) - a_12 = af.sum(E_upper * a_2, 0) - a_13 = af.sum(E_upper * a_3, 0) - - a_20 = af.sum(p_x * a_0, 0) - a_21 = af.sum(p_x * a_1, 0) - a_22 = af.sum(p_x * a_2, 0) - a_23 = af.sum(p_x * a_3, 0) - - a_30 = af.sum(p_y * a_0, 0) - a_31 = af.sum(p_y * a_1, 0) - a_32 = af.sum(p_y * a_2, 0) - a_33 = af.sum(p_y * a_3, 0) - - A = [ [a_00, a_01, a_02, a_03], \ - [a_10, a_11, a_12, a_13], \ - [a_20, a_21, a_22, a_23], \ - [a_30, a_31, a_32, a_33] \ - ] - - fermi_dirac = 1./(af.exp( ( E_upper - mu_ee - - vel_drift_x*p_x - vel_drift_y*p_y - )/(k*T_ee) - ) + 1. - ) - af.eval(fermi_dirac) - - zeroth_moment = (f - fermi_dirac) - second_moment = E_upper*(f - fermi_dirac) - first_moment_x = p_x*(f - fermi_dirac) - first_moment_y = p_y*(f - fermi_dirac) - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - eqn_energy_conservation = af.sum(second_moment, 0) - eqn_mom_x_conservation = af.sum(first_moment_x, 0) - eqn_mom_y_conservation = af.sum(first_moment_y, 0) - - residual = [eqn_mass_conservation, \ - eqn_energy_conservation, \ - eqn_mom_x_conservation, \ - eqn_mom_y_conservation] - - error_norm = np.max([af.max(af.abs(residual[0])), - af.max(af.abs(residual[1])), - af.max(af.abs(residual[2])), - af.max(af.abs(residual[3])) - ] - ) - print(" rank = ", params.rank, - "||residual_ee|| = ", error_norm - ) - -# if (error_norm < 1e-13): -# params.mu_ee = mu_ee -# params.T_ee = T_ee -# params.vel_drift_x = vel_drift_x -# params.vel_drift_y = vel_drift_y -# return(fermi_dirac) - - b_0 = eqn_mass_conservation - b_1 = eqn_energy_conservation - b_2 = eqn_mom_x_conservation - b_3 = eqn_mom_y_conservation - b = [b_0, b_1, b_2, b_3] - - # Solve Ax = b - # where A == Jacobian, - # x == delta guess (correction to guess), - # b = -residual - - A_inv = inverse_4x4_matrix(A) - - x_0 = A_inv[0][0]*b[0] + A_inv[0][1]*b[1] + A_inv[0][2]*b[2] + A_inv[0][3]*b[3] - x_1 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + A_inv[1][3]*b[3] - x_2 = A_inv[2][0]*b[0] + A_inv[2][1]*b[1] + A_inv[2][2]*b[2] + A_inv[2][3]*b[3] - x_3 = A_inv[3][0]*b[0] + A_inv[3][1]*b[1] + A_inv[3][2]*b[2] + A_inv[3][3]*b[3] - - delta_mu = x_0 - delta_T = x_1 - delta_vx = x_2 - delta_vy = x_3 - - mu_ee = mu_ee + delta_mu - T_ee = T_ee + delta_T - vel_drift_x = vel_drift_x + delta_vx - vel_drift_y = vel_drift_y + delta_vy - - af.eval(mu_ee, T_ee, vel_drift_x, vel_drift_y) - - # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params - params.mu_ee = mu_ee - params.T_ee = T_ee - params.vel_drift_x = vel_drift_x - params.vel_drift_y = vel_drift_y - - fermi_dirac = 1./(af.exp( ( E_upper - mu_ee - - vel_drift_x*p_x - vel_drift_y*p_y - )/(k*T_ee) - ) + 1. - ) - af.eval(fermi_dirac) - - zeroth_moment = f - fermi_dirac - second_moment = E_upper*(f - fermi_dirac) - first_moment_x = p_x*(f - fermi_dirac) - first_moment_y = p_y*(f - fermi_dirac) - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - eqn_energy_conservation = af.sum(second_moment, 0) - eqn_mom_x_conservation = af.sum(first_moment_x, 0) - eqn_mom_y_conservation = af.sum(first_moment_y, 0) - - residual = [eqn_mass_conservation, \ - eqn_energy_conservation, \ - eqn_mom_x_conservation, \ - eqn_mom_y_conservation - ] - - error_norm = np.max([af.max(af.abs(residual[0])), - af.max(af.abs(residual[1])), - af.max(af.abs(residual[2])), - af.max(af.abs(residual[3])) - ] - ) - print(" rank = ", params.rank, - "||residual_ee|| = ", error_norm - ) - N_g = domain.N_ghost - print(" rank = ", params.rank, - "mu_ee = ", af.mean(params.mu_ee[0, 0, N_g:-N_g, N_g:-N_g]), - "T_ee = ", af.mean(params.T_ee[0, 0, N_g:-N_g, N_g:-N_g]), - " = ", af.mean(params.vel_drift_x[0, 0, N_g:-N_g, N_g:-N_g]), - " = ", af.mean(params.vel_drift_y[0, 0, N_g:-N_g, N_g:-N_g]) - ) - PETSc.Sys.Print(" ------------------") - - return(fermi_dirac) - -@af.broadcast -def f0_ee_constant_T(f, p_x, p_y, p_z, params): - """ - Return the local equilibrium distribution corresponding to the tau_ee - relaxation time when lattice temperature, T, is set to constant. - Parameters: - ----------- - f : Distribution function array - shape:(N_v, N_s, N_q1, N_q2) - - p_x : The array that holds data for the v1 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_y : The array that holds data for the v2 dimension in v-space - shape:(N_v, N_s, 1, 1) - - p_z : The array that holds data for the v3 dimension in v-space - shape:(N_v, N_s, 1, 1) - - params: The parameters file/object that is originally declared by the user. - This can be used to inject other functions/attributes into the function - - """ - - # Initial guess - mu_ee = params.mu_ee - T_ee = params.T_ee - vel_drift_x = params.vel_drift_x - vel_drift_y = params.vel_drift_y - - for n in range(params.collision_nonlinear_iters): - - E_upper = params.E_band - k = params.boltzmann_constant - - tmp1 = (E_upper - mu_ee - p_x*vel_drift_x - p_y*vel_drift_y) - tmp = (tmp1/(k*T_ee)) - denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) - - a_0 = T_ee / denominator - a_1 = tmp1 / denominator - a_2 = T_ee * p_x / denominator - a_3 = T_ee * p_y / denominator - - af.eval(a_0, a_1, a_2, a_3) - - - # TODO: Multiply with the integral measure dp_x * dp_y - a_00 = af.sum(a_0, 0) - #a_01 = af.sum(a_1, 0) - a_02 = af.sum(a_2, 0) - a_03 = af.sum(a_3, 0) - - #a_10 = af.sum(E_upper * a_0, 0) - #a_11 = af.sum(E_upper * a_1, 0) - #a_12 = af.sum(E_upper * a_2, 0) - #a_13 = af.sum(E_upper * a_3, 0) - - a_20 = af.sum(p_x * a_0, 0) - #a_21 = af.sum(p_x * a_1, 0) - a_22 = af.sum(p_x * a_2, 0) - a_23 = af.sum(p_x * a_3, 0) - a_30 = af.sum(p_y * a_0, 0) - #a_31 = af.sum(p_y * a_1, 0) - a_32 = af.sum(p_y * a_2, 0) - a_33 = af.sum(p_y * a_3, 0) +from .f_local_equilibrium import f0_ee, f0_defect +from .f_local_equilibrium_zero_T import f0_ee_constant_T, f0_defect_constant_T - A = [ [a_00, a_02, a_03], \ - [a_20, a_22, a_23], \ - [a_30, a_32, a_33] \ - ] - - - fermi_dirac = 1./(af.exp( ( E_upper - mu_ee - - vel_drift_x*p_x - vel_drift_y*p_y - )/(k*T_ee) - ) + 1. - ) - af.eval(fermi_dirac) - - zeroth_moment = (f - fermi_dirac) - #second_moment = E_upper*(f - fermi_dirac) - first_moment_x = p_x*(f - fermi_dirac) - first_moment_y = p_y*(f - fermi_dirac) - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - #eqn_energy_conservation = af.sum(second_moment, 0) - eqn_mom_x_conservation = af.sum(first_moment_x, 0) - eqn_mom_y_conservation = af.sum(first_moment_y, 0) - - residual = [eqn_mass_conservation, \ - eqn_mom_x_conservation, \ - eqn_mom_y_conservation] - - error_norm = np.max([af.max(af.abs(residual[0])), - af.max(af.abs(residual[1])), - af.max(af.abs(residual[2])) - ] - ) - print(" rank = ", params.rank, - "||residual_ee|| = ", error_norm - ) - -# if (error_norm < 1e-13): -# params.mu_ee = mu_ee -# params.T_ee = T_ee -# params.vel_drift_x = vel_drift_x -# params.vel_drift_y = vel_drift_y -# return(fermi_dirac) - - b_0 = eqn_mass_conservation - #b_1 = eqn_energy_conservation - b_2 = eqn_mom_x_conservation - b_3 = eqn_mom_y_conservation - b = [b_0, b_2, b_3] - - # Solve Ax = b - # where A == Jacobian, - # x == delta guess (correction to guess), - # b = -residual - - A_inv = inverse_3x3_matrix(A) - - x_0 = A_inv[0][0]*b[0] + A_inv[0][1]*b[1] + A_inv[0][2]*b[2] - #x_1 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + A_inv[1][3]*b[3] - x_2 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] - x_3 = A_inv[2][0]*b[0] + A_inv[2][1]*b[1] + A_inv[2][2]*b[2] - - delta_mu = x_0 - #delta_T = x_1 - delta_vx = x_2 - delta_vy = x_3 - - mu_ee = mu_ee + delta_mu - #T_ee = T_ee + delta_T - vel_drift_x = vel_drift_x + delta_vx - vel_drift_y = vel_drift_y + delta_vy - - af.eval(mu_ee, vel_drift_x, vel_drift_y) - - # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params - params.mu_ee = mu_ee - #params.T_ee = T_ee - params.vel_drift_x = vel_drift_x - params.vel_drift_y = vel_drift_y - - fermi_dirac = 1./(af.exp( ( E_upper - mu_ee - - vel_drift_x*p_x - vel_drift_y*p_y - )/(k*T_ee) - ) + 1. - ) - af.eval(fermi_dirac) - - zeroth_moment = f - fermi_dirac - #second_moment = E_upper*(f - fermi_dirac) - first_moment_x = p_x*(f - fermi_dirac) - first_moment_y = p_y*(f - fermi_dirac) - - eqn_mass_conservation = af.sum(zeroth_moment, 0) - #eqn_energy_conservation = af.sum(second_moment, 0) - eqn_mom_x_conservation = af.sum(first_moment_x, 0) - eqn_mom_y_conservation = af.sum(first_moment_y, 0) - - residual = [eqn_mass_conservation, \ - eqn_mom_x_conservation, \ - eqn_mom_y_conservation - ] +from .matrix_inverse import inverse_4x4_matrix +from .matrix_inverse import inverse_3x3_matrix +from bolt.src.utils.integral_over_p import integral_over_p - error_norm = np.max([af.max(af.abs(residual[0])), - af.max(af.abs(residual[1])), - af.max(af.abs(residual[2])) - ] - ) - print(" rank = ", params.rank, - "||residual_ee|| = ", error_norm - ) - N_g = domain.N_ghost - print(" rank = ", params.rank, - "mu_ee = ", af.mean(params.mu_ee[0, 0, N_g:-N_g, N_g:-N_g]), - "T_ee = ", af.mean(params.T_ee[0, 0, N_g:-N_g, N_g:-N_g]), - " = ", af.mean(params.vel_drift_x[0, 0, N_g:-N_g, N_g:-N_g]), - " = ", af.mean(params.vel_drift_y[0, 0, N_g:-N_g, N_g:-N_g]) - ) - PETSc.Sys.Print(" ------------------") +import domain - return(fermi_dirac) def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): """ @@ -620,24 +48,16 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): function is made to return f0, thus setting f = f0 wherever tau = 0 """ - if (params.p_space_grid == 'cartesian'): - p_x = p1 - p_y = p2 - p_z = p3 - elif (params.p_space_grid == 'polar2D'): - p_x = p1 * af.cos(p2) - p_y = p1 * af.sin(p2) - p_z = p3 - else : - raise NotImplementedError('Unsupported coordinate system in p_space') - - if(af.any_true(params.tau_defect(q1, q2, p_x, p_y, p_z) == 0)): - if (flag == False): - return(0.*f) - - f = f0_defect_constant_T(f, p_x, p_y, p_z, params) + p_x, p_y = params.p_x, params.p_y + p_z = p3 - return(f) + #if(af.any_true(params.tau_defect(q1, q2, p_x, p_y, p_z) == 0)): + # if (flag == False): + # return(0.*f) + # + # f = f0_defect_constant_T(f, p_x, p_y, p_z, params) + # + # return(f) if (params.disable_collision_op): # Activate the following line to disable the collision operator @@ -666,13 +86,15 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): # TODO : Multiply by dp1*dp2 and the phase space degeneracy factor # (4./(2.*np.pi*params.h_bar)**2.) - multiply = lambda a, b:a*b + params.j_x = compute_moments('j_x') + params.j_y = compute_moments('j_y') + params.j_x = moments.j_x(f, p_x, p_y, p_z, params.integral_measure) + params.j_y = moments.j_y(f, p_x, p_y, p_z, params.integral_measure) - print ('f : ',f.shape) - print ('p_x : ', p_x.shape) - - params.j_x = af.sum(af.broadcast(multiply, f, p_x), 0) - params.j_y = af.sum(af.broadcast(multiply, f, p_y), 0) + #multiply = lambda a, b:a*b + + #params.j_x = af.sum(af.broadcast(multiply, f, p_x), 0) + #params.j_y = af.sum(af.broadcast(multiply, f, p_y), 0) af.eval(C_f) diff --git a/bolt/src/electronic_boltzmann/f_local_equilibrium.py b/bolt/src/electronic_boltzmann/f_local_equilibrium.py new file mode 100644 index 00000000..e9bbd21c --- /dev/null +++ b/bolt/src/electronic_boltzmann/f_local_equilibrium.py @@ -0,0 +1,348 @@ +"""Contains the function which returns the Source/Sink term.""" + +from petsc4py import PETSc +import numpy as np +import arrayfire as af + +from .matrix_inverse import inverse_4x4_matrix +from .matrix_inverse import inverse_3x3_matrix +from bolt.src.utils.integral_over_p import integral_over_p + +import domain + + +# Using af.broadcast, since p_x, p_y, p_z are of size (1, 1, Np_x*Np_y*Np_z) +# All moment quantities are of shape (Nq1, Nq2) +# By wrapping with af.broadcast, we can perform batched operations +# on arrays of different sizes. +@af.broadcast +def f0_defect(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_D + relaxation time. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ + + # Initial guess + mu = params.mu + T = params.T + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp = ((E_upper - mu)/(k*T)) + denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + # TODO: Multiply with the integral measure dp_x * dp_y + #a00 = af.sum(T / denominator, 0) + a00 = integral_over_p(T / denominator, params.integral_measure) + #a01 = af.sum((E_upper - mu) / denominator, 0) + a01 = integral_over_p((E_upper - mu) / denominator, params.integral_measure) + a10 = integral_over_p(E_upper*T / denominator, params.integral_measure) + a11 = integral_over_p(E_upper*(E_upper - mu) / denominator, params.integral_measure) + + # Solve Ax = b + # where A == Jacobian, + # x == delta guess (correction to guess), + # b = -residual + + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + second_moment = E_upper*(f - fermi_dirac) + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + #eqn_energy_conservation = af.sum(second_moment, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) + eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) + + N_g = domain.N_ghost + error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + error_energy_conservation = af.max(af.abs(eqn_energy_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + + residual = [eqn_mass_conservation, eqn_energy_conservation] + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1]))] + ) + print(" ||residual_defect|| = ", error_norm) + +# if (error_norm < 1e-9): +# params.mu = mu +# params.T = T +# return(fermi_dirac) + + b0 = eqn_mass_conservation + b1 = eqn_energy_conservation + + det = a01*a10 - a00*a11 + delta_mu = -(a11*b0 - a01*b1)/det + delta_T = (a10*b0 - a00*b1)/det + + mu = mu + delta_mu + T = T + delta_T + + af.eval(mu, T) + + # Solved for (mu, T). Now store in params + params.mu = mu + params.T = T + + # Print final residual + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + second_moment = E_upper*(f - fermi_dirac) + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + #eqn_energy_conservation = af.sum(second_moment, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) + eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) + + residual = [eqn_mass_conservation, eqn_energy_conservation] + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1]))] + ) + print(" ||residual_defect|| = ", error_norm) + print(" mu = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), + "T = ", af.mean(params.T[0, 0, N_g:-N_g, N_g:-N_g]) + ) + print(" ------------------") + + return(fermi_dirac) + +@af.broadcast +def f0_ee(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_ee + relaxation time. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ + + # Initial guess + mu_ee = params.mu_ee + T_ee = params.T_ee + vel_drift_x = params.vel_drift_x + vel_drift_y = params.vel_drift_y + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp1 = (E_upper - mu_ee - p_x*vel_drift_x - p_y*vel_drift_y) + tmp = (tmp1/(k*T_ee)) + denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + a_0 = T_ee / denominator + a_1 = tmp1 / denominator + a_2 = T_ee * p_x / denominator + a_3 = T_ee * p_y / denominator + + af.eval(a_0, a_1, a_2, a_3) + + # TODO: Multiply with the integral measure dp_x * dp_y + #a_00 = af.sum(a_0, 0) + #a_01 = af.sum(a_1, 0) + #a_02 = af.sum(a_2, 0) + #a_03 = af.sum(a_3, 0) + a_00 = integral_over_p(a_0, params.integral_measure) + a_01 = integral_over_p(a_1, params.integral_measure) + a_02 = integral_over_p(a_2, params.integral_measure) + a_03 = integral_over_p(a_3, params.integral_measure) + + #a_10 = af.sum(E_upper * a_0, 0) + #a_11 = af.sum(E_upper * a_1, 0) + #a_12 = af.sum(E_upper * a_2, 0) + #a_13 = af.sum(E_upper * a_3, 0) + + a_10 = integral_over_p(E_upper * a_0, params.integral_measure) + a_11 = integral_over_p(E_upper * a_1, params.integral_measure) + a_12 = integral_over_p(E_upper * a_2, params.integral_measure) + a_13 = integral_over_p(E_upper * a_3, params.integral_measure) + + #a_20 = af.sum(p_x * a_0, 0) + #a_21 = af.sum(p_x * a_1, 0) + #a_22 = af.sum(p_x * a_2, 0) + #a_23 = af.sum(p_x * a_3, 0) + a_20 = integral_over_p(p_x * a_0, params.integral_measure) + a_21 = integral_over_p(p_x * a_1, params.integral_measure) + a_22 = integral_over_p(p_x * a_2, params.integral_measure) + a_23 = integral_over_p(p_x * a_3, params.integral_measure) + + #a_30 = af.sum(p_y * a_0, 0) + #a_31 = af.sum(p_y * a_1, 0) + #a_32 = af.sum(p_y * a_2, 0) + #a_33 = af.sum(p_y * a_3, 0) + a_30 = integral_over_p(p_y * a_0, params.integral_measure) + a_31 = integral_over_p(p_y * a_1, params.integral_measure) + a_32 = integral_over_p(p_y * a_2, params.integral_measure) + a_33 = integral_over_p(p_y * a_3, params.integral_measure) + + A = [ [a_00, a_01, a_02, a_03], \ + [a_10, a_11, a_12, a_13], \ + [a_20, a_21, a_22, a_23], \ + [a_30, a_31, a_32, a_33] \ + ] + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = (f - fermi_dirac) + second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + #eqn_energy_conservation = af.sum(second_moment, 0) + #eqn_mom_x_conservation = af.sum(first_moment_x, 0) + #eqn_mom_y_conservation = af.sum(first_moment_y, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) + eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) + eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) + eqn_mom_y_conservation = integral_over_p(first_moment_y, params.integral_measure) + + residual = [eqn_mass_conservation, \ + eqn_energy_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])), + af.max(af.abs(residual[3])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + +# if (error_norm < 1e-13): +# params.mu_ee = mu_ee +# params.T_ee = T_ee +# params.vel_drift_x = vel_drift_x +# params.vel_drift_y = vel_drift_y +# return(fermi_dirac) + + b_0 = eqn_mass_conservation + b_1 = eqn_energy_conservation + b_2 = eqn_mom_x_conservation + b_3 = eqn_mom_y_conservation + b = [b_0, b_1, b_2, b_3] + + # Solve Ax = b + # where A == Jacobian, + # x == delta guess (correction to guess), + # b = -residual + + A_inv = inverse_4x4_matrix(A) + + x_0 = A_inv[0][0]*b[0] + A_inv[0][1]*b[1] + A_inv[0][2]*b[2] + A_inv[0][3]*b[3] + x_1 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + A_inv[1][3]*b[3] + x_2 = A_inv[2][0]*b[0] + A_inv[2][1]*b[1] + A_inv[2][2]*b[2] + A_inv[2][3]*b[3] + x_3 = A_inv[3][0]*b[0] + A_inv[3][1]*b[1] + A_inv[3][2]*b[2] + A_inv[3][3]*b[3] + + delta_mu = x_0 + delta_T = x_1 + delta_vx = x_2 + delta_vy = x_3 + + mu_ee = mu_ee + delta_mu + T_ee = T_ee + delta_T + vel_drift_x = vel_drift_x + delta_vx + vel_drift_y = vel_drift_y + delta_vy + + af.eval(mu_ee, T_ee, vel_drift_x, vel_drift_y) + + # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params + params.mu_ee = mu_ee + params.T_ee = T_ee + params.vel_drift_x = vel_drift_x + params.vel_drift_y = vel_drift_y + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + #eqn_energy_conservation = af.sum(second_moment, 0) + #eqn_mom_x_conservation = af.sum(first_moment_x, 0) + #eqn_mom_y_conservation = af.sum(first_moment_y, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) + eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) + eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) + eqn_mom_y_conservation = integral_over_p(first_moment_y, params.integral_measure) + + residual = [eqn_mass_conservation, \ + eqn_energy_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation + ] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])), + af.max(af.abs(residual[3])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + N_g = domain.N_ghost + print(" rank = ", params.rank, + "mu_ee = ", af.mean(params.mu_ee[0, 0, N_g:-N_g, N_g:-N_g]), + "T_ee = ", af.mean(params.T_ee[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_x[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_y[0, 0, N_g:-N_g, N_g:-N_g]) + ) + PETSc.Sys.Print(" ------------------") + + return(fermi_dirac) + diff --git a/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py b/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py new file mode 100644 index 00000000..b4af23dc --- /dev/null +++ b/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py @@ -0,0 +1,310 @@ +"""Contains the function which returns the Source/Sink term.""" + +from petsc4py import PETSc +import numpy as np +import arrayfire as af + +from .matrix_inverse import inverse_4x4_matrix +from .matrix_inverse import inverse_3x3_matrix + +from bolt.src.utils.integral_over_p import integral_over_p + +import domain + +@af.broadcast +def f0_defect_constant_T(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_D + relaxation time when lattice temperature, T, is set to constant. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ + + mu = params.mu + T = params.T + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp = ((E_upper - mu)/(k*T)) + denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + # TODO: Multiply with the integral measure dp_x * dp_y + #a00 = af.sum(T / denominator, 0) + a00 = integral_over_p(T/denominator, params.integral_measure) + + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, + params.integral_measure + ) + + N_g = domain.N_ghost + error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + + print(" rank = ", params.rank, + "||residual_defect|| = ", error_mass_conservation + ) + + res = eqn_mass_conservation + dres_dmu = -a00 + + delta_mu = -res/dres_dmu + + mu = mu + delta_mu + + af.eval(mu) + + # Solved for mu. Now store in params + params.mu = mu + + # Print final residual + fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, + params.integral_measure + ) + + N_g = domain.N_ghost + error_mass_conservation = af.max(af.abs(eqn_mass_conservation)[0, 0, N_g:-N_g, N_g:-N_g]) + + print(" rank = ", params.rank, + "||residual_defect|| = ", error_mass_conservation + ) + print(" rank = ", params.rank, + "mu = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), + "T = ", af.mean(params.T[0, 0, N_g:-N_g, N_g:-N_g]) + ) + PETSc.Sys.Print(" ------------------") + + return(fermi_dirac) + + +@af.broadcast +def f0_ee_constant_T(f, p_x, p_y, p_z, params): + """ + Return the local equilibrium distribution corresponding to the tau_ee + relaxation time when lattice temperature, T, is set to constant. + Parameters: + ----------- + f : Distribution function array + shape:(N_v, N_s, N_q1, N_q2) + + p_x : The array that holds data for the v1 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_y : The array that holds data for the v2 dimension in v-space + shape:(N_v, N_s, 1, 1) + + p_z : The array that holds data for the v3 dimension in v-space + shape:(N_v, N_s, 1, 1) + + params: The parameters file/object that is originally declared by the user. + This can be used to inject other functions/attributes into the function + + """ + + # Initial guess + mu_ee = params.mu_ee + T_ee = params.T_ee + vel_drift_x = params.vel_drift_x + vel_drift_y = params.vel_drift_y + + for n in range(params.collision_nonlinear_iters): + + E_upper = params.E_band + k = params.boltzmann_constant + + tmp1 = (E_upper - mu_ee - p_x*vel_drift_x - p_y*vel_drift_y) + tmp = (tmp1/(k*T_ee)) + denominator = (k*T_ee**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) + + a_0 = T_ee / denominator + a_1 = tmp1 / denominator + a_2 = T_ee * p_x / denominator + a_3 = T_ee * p_y / denominator + + af.eval(a_0, a_1, a_2, a_3) + + + # TODO: Multiply with the integral measure dp_x * dp_y + #a_00 = af.sum(a_0, 0) + a_00 = integral_over_p(a_0, params.integral_measure) + ##a_01 = af.sum(a_1, 0) + #a_02 = af.sum(a_2, 0) + a_02 = integral_over_p(a_2, params.integral_measure) + #a_03 = af.sum(a_3, 0) + a_03 = integral_over_p(a_3, params.integral_measure) + + #a_10 = af.sum(E_upper * a_0, 0) + #a_11 = af.sum(E_upper * a_1, 0) + #a_12 = af.sum(E_upper * a_2, 0) + #a_13 = af.sum(E_upper * a_3, 0) + + #a_20 = af.sum(p_x * a_0, 0) + a_02 = integral_over_p(p_x * a_0, params.integral_measure) + ##a_21 = af.sum(p_x * a_1, 0) + #a_22 = af.sum(p_x * a_2, 0) + a_22 = integral_over_p(p_x * a_2, params.integral_measure) + #a_23 = af.sum(p_x * a_3, 0) + a_23 = integral_over_p(p_x * a_3, params.integral_measure) + + #a_30 = af.sum(p_y * a_0, 0) + a_30 = integral_over_p(p_y * a_0, params.integral_measure) + ##a_31 = af.sum(p_y * a_1, 0) + #a_32 = af.sum(p_y * a_2, 0) + a_32 = integral_measure(p_y * a_2, params.integral_measure) + #a_33 = af.sum(p_y * a_3, 0) + a_33 = integral_measure(p_y * a_3, params.integral_measure) + + A = [ [a_00, a_02, a_03], \ + [a_20, a_22, a_23], \ + [a_30, a_32, a_33] \ + ] + + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = (f - fermi_dirac) + #second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) + #eqn_energy_conservation = af.sum(second_moment, 0) + #eqn_mom_x_conservation = af.sum(first_moment_x, 0) + eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) + #eqn_mom_y_conservation = af.sum(first_moment_y, 0) + eqn_mom_y_conservation = integral_over_p(first_moment_y, params.integral_measure) + + residual = [eqn_mass_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + +# if (error_norm < 1e-13): +# params.mu_ee = mu_ee +# params.T_ee = T_ee +# params.vel_drift_x = vel_drift_x +# params.vel_drift_y = vel_drift_y +# return(fermi_dirac) + + b_0 = eqn_mass_conservation + #b_1 = eqn_energy_conservation + b_2 = eqn_mom_x_conservation + b_3 = eqn_mom_y_conservation + b = [b_0, b_2, b_3] + + # Solve Ax = b + # where A == Jacobian, + # x == delta guess (correction to guess), + # b = -residual + + A_inv = inverse_3x3_matrix(A) + + x_0 = A_inv[0][0]*b[0] + A_inv[0][1]*b[1] + A_inv[0][2]*b[2] + #x_1 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + A_inv[1][3]*b[3] + x_2 = A_inv[1][0]*b[0] + A_inv[1][1]*b[1] + A_inv[1][2]*b[2] + x_3 = A_inv[2][0]*b[0] + A_inv[2][1]*b[1] + A_inv[2][2]*b[2] + + delta_mu = x_0 + #delta_T = x_1 + delta_vx = x_2 + delta_vy = x_3 + + mu_ee = mu_ee + delta_mu + #T_ee = T_ee + delta_T + vel_drift_x = vel_drift_x + delta_vx + vel_drift_y = vel_drift_y + delta_vy + + af.eval(mu_ee, vel_drift_x, vel_drift_y) + + # Solved for (mu_ee, T_ee, vel_drift_x, vel_drift_y). Now store in params + params.mu_ee = mu_ee + #params.T_ee = T_ee + params.vel_drift_x = vel_drift_x + params.vel_drift_y = vel_drift_y + + fermi_dirac = 1./(af.exp( ( E_upper - mu_ee + - vel_drift_x*p_x - vel_drift_y*p_y + )/(k*T_ee) + ) + 1. + ) + af.eval(fermi_dirac) + + zeroth_moment = f - fermi_dirac + #second_moment = E_upper*(f - fermi_dirac) + first_moment_x = p_x*(f - fermi_dirac) + first_moment_y = p_y*(f - fermi_dirac) + + #eqn_mass_conservation = af.sum(zeroth_moment, 0) + eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) + #eqn_energy_conservation = af.sum(second_moment, 0) + #eqn_mom_x_conservation = af.sum(first_moment_x, 0) + eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) + #eqn_mom_y_conservation = af.sum(first_moment_y, 0) + eqn_mom_y_conservation = integral_over_p(first_moment_y, params.integral_measure) + + residual = [eqn_mass_conservation, \ + eqn_mom_x_conservation, \ + eqn_mom_y_conservation + ] + + error_norm = np.max([af.max(af.abs(residual[0])), + af.max(af.abs(residual[1])), + af.max(af.abs(residual[2])) + ] + ) + print(" rank = ", params.rank, + "||residual_ee|| = ", error_norm + ) + N_g = domain.N_ghost + print(" rank = ", params.rank, + "mu_ee = ", af.mean(params.mu_ee[0, 0, N_g:-N_g, N_g:-N_g]), + "T_ee = ", af.mean(params.T_ee[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_x[0, 0, N_g:-N_g, N_g:-N_g]), + " = ", af.mean(params.vel_drift_y[0, 0, N_g:-N_g, N_g:-N_g]) + ) + PETSc.Sys.Print(" ------------------") + + return(fermi_dirac) + diff --git a/bolt/src/electronic_boltzmann/moment_defs.py b/bolt/src/electronic_boltzmann/moment_defs.py deleted file mode 100644 index d72ff03e..00000000 --- a/bolt/src/electronic_boltzmann/moment_defs.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from bolt.src.utils.integral_over_v import integral_over_v - -def density(f, v1, v2, v3, integral_measure): - return(integral_over_v(f, integral_measure)) - -def j_x(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v1, integral_measure)) - -def j_y(f, v1, v2, v3, integral_measure): - return(integral_over_v(f * v2, integral_measure)) diff --git a/bolt/src/electronic_boltzmann/moments.py b/bolt/src/electronic_boltzmann/moments.py new file mode 100644 index 00000000..6d0eecf5 --- /dev/null +++ b/bolt/src/electronic_boltzmann/moments.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from bolt.src.utils.integral_over_p import integral_over_p + +def density(f, p_x, p_y, p_z, integral_measure): + return(integral_over_p(f, integral_measure)) + +def j_x(f, p_x, p_y, p_z, integral_measure): + return(integral_over_p(f * p_x, integral_measure)) + +def j_y(f, p_x, p_y, p_z, integral_measure): + return(integral_over_p(f * p_y, integral_measure)) diff --git a/bolt/src/utils/integral_over_p.py b/bolt/src/utils/integral_over_p.py new file mode 100644 index 00000000..324a18f8 --- /dev/null +++ b/bolt/src/utils/integral_over_p.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import arrayfire as af + +def integral_over_p(array, integral_measure): + return(af.sum(array*integral_measure, 0)) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py index 50bdf0af..71fe46ef 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/check.py @@ -3,17 +3,40 @@ import arrayfire as af import pylab as pl +import domain + +from bolt.src.electronic_boltzmann.utils.polygon import polygon p2_start = -np.pi p2_end = np.pi -N_p2 = 1024 +N_p2 = domain.N_p2 theta = \ p2_start + (0.5 + np.arange(N_p2))*(p2_end - p2_start)/N_p2 theta = af.from_ndarray(theta) -hexa = params.polygon(6, theta, rotation = np.pi/6) +hexa = polygon(6, theta, rotation = np.pi/6) hexa = hexa.to_ndarray() -pl.polar(theta, hexa) +#pl.polar(theta, hexa) + +#pl.plot(theta, hexa * np.cos(theta)) +#pl.plot(theta, hexa * np.sin(theta)) + +pl.gca().set_aspect(1) +pl.plot(hexa*np.cos(theta), hexa*np.sin(theta)) + +#p_hat_0_old = np.loadtxt("P_hat_0_old.txt") +#p_hat_1_old = np.loadtxt("P_hat_1_old.txt") + +#p_hat_0 = np.loadtxt("P_hat_0.txt") +#p_hat_1 = np.loadtxt("P_hat_1.txt") + +#pl.plot(theta, p_hat_0_old) +#pl.plot(theta, p_hat_1_old) + +#pl.plot(theta, p_hat_0, '--') +#pl.plot(theta, p_hat_1, '--') + + pl.savefig("images/test.png") diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py index fb8e8c88..52c19cb6 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py @@ -9,6 +9,8 @@ def initialize_f(q1, q2, p1, p2, p3, params): + params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) + PETSc.Sys.Print("Initializing f") k = params.boltzmann_constant @@ -16,7 +18,6 @@ def initialize_f(q1, q2, p1, p2, p3, params): params.T = 0.*q1 + params.initial_temperature params.vel_drift_x = 0.*q1 params.vel_drift_y = 0.*q1 - params.phi = 0.*q1 params.mu_ee = params.mu.copy() params.T_ee = params.T.copy() @@ -28,20 +29,26 @@ def initialize_f(q1, q2, p1, p2, p3, params): params.E_band = params.band_energy(p1, p2) params.vel_band = params.band_velocity(p1, p2) - E_upper = params.E_band + params.charge[0]*params.phi + # Evaluating velocity space resolution for each species: + self.dp1 = [] + self.dp2 = [] + self.dp3 = [] + + for i in range(N_species): + self.dp1.append((self.p1_end[i] - self.p1_start[i]) / self.N_p1) + self.dp2.append((self.p2_end[i] - self.p2_start[i]) / self.N_p2) + self.dp3.append((self.p3_end[i] - self.p3_start[i]) / self.N_p3) + + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 - if (params.p_space_grid == 'cartesian'): - p_x = p1 - p_y = p2 - elif (params.p_space_grid == 'polar2D'): - p_x = p1 * af.cos(p2) - p_y = p1 * af.sin(p2) - else: - raise NotImplementedError('Unsupported coordinate system in p_space') - f = (1./(af.exp( (E_upper - params.vel_drift_x*p_x - - params.vel_drift_y*p_y - - params.mu + f = (1./(af.exp( (params.E_band - params.vel_drift_x*params.p_x + - params.vel_drift_y*params.p_y + - params.mu )/(k*params.T) ) + 1. )) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py index b9069f22..348c13e1 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py @@ -24,8 +24,8 @@ as advection_terms import bolt.src.electronic_boltzmann.collision_operator \ as collision_operator -import bolt.src.electronic_boltzmann.moment_defs \ - as moment_defs +import bolt.src.electronic_boltzmann.moments \ + as moments # Create required folders if they do not exist already @@ -46,7 +46,7 @@ initialize, advection_terms, collision_operator.RTA, - moment_defs + moments ) # Declaring a nonlinear system object which will evolve the defined physical system: diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 49e027e7..49079292 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -40,7 +40,7 @@ # Time parameters: dt = 0.025/4 # ps -t_final = 100. # ps +t_final = 2.*dt # ps # File-writing Parameters: @@ -58,6 +58,12 @@ # Set p-space start and end points accordingly in domain.py #TODO : Use only polar2D for PdCoO2 + +zero_temperature = (p_dim==1) +dispersion = 'quadratic' # 'linear' or 'quadratic' +fermi_surface_shape = 'hexagon' # Supports 'circle' or 'hexagon' + + # Number of devices(GPUs/Accelerators) on each node: num_devices = 6 @@ -118,54 +124,142 @@ def tau_ee(q1, q2, p1, p2, p3): def tau(q1, q2, p1, p2, p3): return(tau_defect(q1, q2, p1, p2, p3)) + +def fermi_momentum_magnitude(theta): + #TODO : If cartesian coordinates are being used, conver to polar to calculate p_f + n = 6 #number of sides of the polygon + p_f = initial_mu/fermi_velocity * polygon(n, theta, rotation = np.pi/6) + return(p_f) + +def get_p_x_p_y_at_fermi_surface(theta): + #TODO : If cartesian coordinates are being used, conver to polar to calculate p_f + p_f = fermi_surface_magnitude(theta) + return([p_f*af.cos(theta), p_f*af.sin(theta)]) + def band_energy(p1, p2): + # Note :This function is only meant to be called once to initialize E_band if (p_space_grid == 'cartesian'): p_x = p1 p_y = p2 elif (p_space_grid == 'polar2D'): - p_x = p1 * af.cos(p2) - p_y = p1 * af.sin(p2) + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1 + theta = p2 + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) else : raise NotImplementedError('Unsupported coordinate system in p_space') - # In polar2D coordinates, p1 = radius and p2 = theta + p = af.sqrt(p_x**2. + p_y**2.) + if (dispersion == 'linear'): - #p = af.sqrt(p_x**2. + p_y**2.) - #E_upper = p*fermi_velocity - n = 6 #number of sides of the polygon - E_upper = initial_mu * polygon(n, p2, rotation = np.pi/6) + E_upper = p*fermi_velocity + + elif (dispersion == 'quadratic'): + + m = effective_mass(p1, p2) + E_upper = p**2/(2.*m) + + if (zero_temperature): + + E_upper = initial_mu * p**0. af.eval(E_upper) return(E_upper) + +def effective_mass(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + + theta = af.atan(p_y/p_x) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + if (fermi_surface_shape == 'hexagon'): + + n = 6 # No. of side of polygon + mass = mass_particle * polygon(n, theta, rotation = np.pi/6) + + elif (fermi_surface_shape == 'circle'): + + # For now, just return the free electron mass + mass = mass_particle + + return(mass) + def band_velocity(p1, p2): - # TODO :This function is only meant to be called once to initialize the vel vectors + # Note :This function is only meant to be called once to initialize the vel vectors if (p_space_grid == 'cartesian'): p_x = p1 p_y = p2 + + theta = af.atan(p_y/p_x) + elif (p_space_grid == 'polar2D'): - # Here, p1 = radius and p2 = theta - p_x = p1 * af.cos(p2) - p_y = p1 * af.sin(p2) + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 else : - raise NotImplementedError('Unsupported coordinate system in p_space') + raise NotImplementedError('Unsupported coordinate system in p_space') -# p = af.sqrt(p_x**2. + p_y**2.) -# p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] -# - v_f = fermi_velocity -# -# upper_band_velocity = [ v_f * p_hat[0], v_f * p_hat[1]] -# -# af.eval(upper_band_velocity[0], upper_band_velocity[1]) - - v_f_hat = normal_to_hexagon_unit_vec(p2) + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + if (fermi_surface_shape == 'circular'): + + v_f_hat = p_hat + + elif (fermi_surface_shape == 'hexagon'): + + v_f_hat = normal_to_hexagon_unit_vec(theta) + + # Quadratic dispersion + m = effective_mass(p1, p2) + v_f = p/m + + if (dispersion == 'linear' or zero_temperature): + + v_f = fermi_velocity + upper_band_velocity = [v_f * v_f_hat[0], v_f * v_f_hat[1]] return(upper_band_velocity) +def get_p_x_and_p_y(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + + if (zero_temperature): + # get p_x and p_y at the Fermi surface + + if (fermi_surface_shape == 'circle'): + r = initial_mu/fermi_velocity # Fermi momentum + + elif (fermi_surface_shape == 'hexagon'): + n = 6 #No. of sides of polygon + r = (initial_mu/fermi_velocity) * polygon(n, theta, rotation = np.pi/6) + + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + return([p_x, p_y]) + # Restart(Set to zero for no-restart): latest_restart = True t_restart = 0 From 6940bd4caed20d8a5470428423762a8d7ed842cf Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Tue, 7 Apr 2020 16:41:24 -0400 Subject: [PATCH 51/58] Some bug fixes [WIP] --- .../f_local_equilibrium_zero_T.py | 6 ++--- .../domain.py | 4 +-- .../initialize.py | 25 ++++++++++++------- .../params.py | 20 +++++++++------ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py b/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py index b4af23dc..1bd5d976 100644 --- a/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py +++ b/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py @@ -167,7 +167,7 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): #a_13 = af.sum(E_upper * a_3, 0) #a_20 = af.sum(p_x * a_0, 0) - a_02 = integral_over_p(p_x * a_0, params.integral_measure) + a_20 = integral_over_p(p_x * a_0, params.integral_measure) ##a_21 = af.sum(p_x * a_1, 0) #a_22 = af.sum(p_x * a_2, 0) a_22 = integral_over_p(p_x * a_2, params.integral_measure) @@ -178,9 +178,9 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): a_30 = integral_over_p(p_y * a_0, params.integral_measure) ##a_31 = af.sum(p_y * a_1, 0) #a_32 = af.sum(p_y * a_2, 0) - a_32 = integral_measure(p_y * a_2, params.integral_measure) + a_32 = integral_over_p(p_y * a_2, params.integral_measure) #a_33 = af.sum(p_y * a_3, 0) - a_33 = integral_measure(p_y * a_3, params.integral_measure) + a_33 = integral_over_p(p_y * a_3, params.integral_measure) A = [ [a_00, a_02, a_03], \ [a_20, a_22, a_23], \ diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py index f22b4a55..96ac75e4 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/domain.py @@ -35,8 +35,8 @@ # 16.*params.boltzmann_constant*params.initial_temperature] # Uncomment the following for the 1D polar representation of momentum space -p1_start = [0.5*params.initial_mu] -p1_end = [1.5*params.initial_mu] +p1_start = [0.5*params.initial_mu/params.fermi_velocity] +p1_end = [1.5*params.initial_mu/params.fermi_velocity] # If N_p2 > 1, mirror boundary conditions require p2 to be diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py index 52c19cb6..c5733daa 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py @@ -7,10 +7,10 @@ import numpy as np from petsc4py import PETSc +import domain + def initialize_f(q1, q2, p1, p2, p3, params): - params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) - PETSc.Sys.Print("Initializing f") k = params.boltzmann_constant @@ -26,24 +26,31 @@ def initialize_f(q1, q2, p1, p2, p3, params): params.j_x = 0.*q1 params.j_y = 0.*q1 + params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) params.E_band = params.band_energy(p1, p2) params.vel_band = params.band_velocity(p1, p2) # Evaluating velocity space resolution for each species: - self.dp1 = [] - self.dp2 = [] - self.dp3 = [] + dp1 = []; dp2 = []; dp3 = [] + N_p1 = domain.N_p1; N_p2 = domain.N_p2; N_p3 = domain.N_p3 + p1_start = domain.p1_start; p1_end = domain.p1_end + p2_start = domain.p2_start; p2_end = domain.p2_end + p3_start = domain.p3_start; p3_end = domain.p3_end + N_species = len(params.mass) for i in range(N_species): - self.dp1.append((self.p1_end[i] - self.p1_start[i]) / self.N_p1) - self.dp2.append((self.p2_end[i] - self.p2_start[i]) / self.N_p2) - self.dp3.append((self.p3_end[i] - self.p3_start[i]) / self.N_p3) + dp1.append((p1_end[i] - p1_start[i]) / N_p1) + dp2.append((p2_end[i] - p2_start[i]) / N_p2) + dp3.append((p3_end[i] - p3_start[i]) / N_p3) + theta = af.atan(params.p_y / params.p_x) p_f = params.fermi_momentum_magnitude(theta) params.integral_measure = \ - (4./(2.*np.pi*params.h_bar)**2) * self.dp3 * self.dp2 * self.dp1 + (4./(2.*np.pi*params.h_bar)**2) * dp3[0] * dp2[0] * dp1[0] + + print ("initialize, integral measure :", params.integral_measure) f = (1./(af.exp( (params.E_band - params.vel_drift_x*params.p_x diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 49079292..e5773538 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -40,7 +40,7 @@ # Time parameters: dt = 0.025/4 # ps -t_final = 2.*dt # ps +t_final = 100. # ps # File-writing Parameters: @@ -105,6 +105,9 @@ j_x = None j_y = None phi = None # Electric potential in the plane of graphene sheet +p_x = None +p_y = None +integral_measure = None # Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) E_band = None @@ -131,10 +134,11 @@ def fermi_momentum_magnitude(theta): p_f = initial_mu/fermi_velocity * polygon(n, theta, rotation = np.pi/6) return(p_f) -def get_p_x_p_y_at_fermi_surface(theta): - #TODO : If cartesian coordinates are being used, conver to polar to calculate p_f - p_f = fermi_surface_magnitude(theta) - return([p_f*af.cos(theta), p_f*af.sin(theta)]) +#def get_p_x_p_y_at_fermi_surface(theta): +# #TODO : If cartesian coordinates are being used, conver to polar to calculate p_f +# p_f = fermi_surface_magnitude(theta) +# return([p_f*af.cos(theta), p_f*af.sin(theta)]) + def band_energy(p1, p2): # Note :This function is only meant to be called once to initialize E_band @@ -199,10 +203,10 @@ def band_velocity(p1, p2): # Note :This function is only meant to be called once to initialize the vel vectors if (p_space_grid == 'cartesian'): - p_x = p1 - p_y = p2 + p_x_local = p1 + p_y_local = p2 - theta = af.atan(p_y/p_x) + theta = af.atan(p_y_local/p_x_local) elif (p_space_grid == 'polar2D'): # In polar2D coordinates, p1 = radius and p2 = theta From db8803633ab7f78b2c105994139ec0de490ff2f9 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Tue, 7 Apr 2020 18:45:21 -0400 Subject: [PATCH 52/58] Bug fix, integral_over_p removed from attributes --- bolt/lib/nonlinear/file_io/dump.py | 5 +++-- bolt/lib/nonlinear/nonlinear_solver.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index 4efc19b7..c787bff3 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -99,10 +99,11 @@ def dump_moments(self, file_name): attributes = [a for a in dir(self.physical_system.moments) if not a.startswith('_')] # Removing utility functions: - if('integral_over_v' in attributes): - attributes.remove('integral_over_v') + if('integral_over_p' in attributes): + attributes.remove('integral_over_p') for i in range(len(attributes)): + #print("i = ", i, attributes[i]) if(i == 0): array_to_dump = self.compute_moments(attributes[i]) else: diff --git a/bolt/lib/nonlinear/nonlinear_solver.py b/bolt/lib/nonlinear/nonlinear_solver.py index 05647105..274fa962 100644 --- a/bolt/lib/nonlinear/nonlinear_solver.py +++ b/bolt/lib/nonlinear/nonlinear_solver.py @@ -289,7 +289,7 @@ def __init__(self, physical_system, performance_test_flag = False): self._da_dump_moments = PETSc.DMDA().create([self.N_q1, self.N_q2], dof = self.N_species - * len(attributes), + * (len(attributes)-1), # do not countintegral_over_p in moments.py proc_sizes = (nproc_in_q1, nproc_in_q2 ), From 6760f8ecc14622ac9aab7b26b7e289873bce8249 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 8 Apr 2020 15:19:58 -0400 Subject: [PATCH 53/58] Clean up collision op, bugfix in integral measure in initialize.py --- .../collision_operator.py | 18 +-------- .../initialize.py | 30 +++++++++++--- .../main.py | 9 +++-- .../movie.py | 40 +------------------ .../params.py | 6 +-- 5 files changed, 34 insertions(+), 69 deletions(-) diff --git a/bolt/src/electronic_boltzmann/collision_operator.py b/bolt/src/electronic_boltzmann/collision_operator.py index 6b3ebe9e..42c94f19 100644 --- a/bolt/src/electronic_boltzmann/collision_operator.py +++ b/bolt/src/electronic_boltzmann/collision_operator.py @@ -4,6 +4,8 @@ import numpy as np import arrayfire as af +#from bolt.lib.nonlinear.compute_moments import compute_moments + from .f_local_equilibrium import f0_ee, f0_defect from .f_local_equilibrium_zero_T import f0_ee_constant_T, f0_defect_constant_T @@ -81,22 +83,6 @@ def RTA(f, t, q1, q2, p1, p2, p3, moments, params, flag = False): # TODO: WORKAROUND - # Inject j_x and j_y into params - - # TODO : Multiply by dp1*dp2 and the phase space degeneracy factor - # (4./(2.*np.pi*params.h_bar)**2.) - - params.j_x = compute_moments('j_x') - params.j_y = compute_moments('j_y') - params.j_x = moments.j_x(f, p_x, p_y, p_z, params.integral_measure) - params.j_y = moments.j_y(f, p_x, p_y, p_z, params.integral_measure) - - #multiply = lambda a, b:a*b - - #params.j_x = af.sum(af.broadcast(multiply, f, p_x), 0) - #params.j_y = af.sum(af.broadcast(multiply, f, p_y), 0) - - af.eval(C_f) return(C_f) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py index c5733daa..c2ee7948 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/initialize.py @@ -23,8 +23,6 @@ def initialize_f(q1, q2, p1, p2, p3, params): params.T_ee = params.T.copy() params.vel_drift_x = 0.*q1 + 0e-3 params.vel_drift_y = 0.*q1 + 0e-3 - params.j_x = 0.*q1 - params.j_y = 0.*q1 params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) params.E_band = params.band_energy(p1, p2) @@ -46,11 +44,31 @@ def initialize_f(q1, q2, p1, p2, p3, params): theta = af.atan(params.p_y / params.p_x) p_f = params.fermi_momentum_magnitude(theta) + + if (params.p_space_grid == 'cartesian'): + dp_x = dp1[0]; dp_y = dp2[0]; dp_z = dp3[0] + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * dp_z * dp_y * dp_x + + elif (params.p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + # Integral : \int delta(r - r_F) F(r, theta) r dr dtheta + r = p1; theta = p2 + dp_r = dp1[0]; dp_theta = dp2[0] + + if (params.zero_temperature): + # Assumption : F(r, theta) = delta(r-r_F)*F(theta) + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * p_f * dp_theta + + else: + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * r * dp_r * dp_theta + + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') - params.integral_measure = \ - (4./(2.*np.pi*params.h_bar)**2) * dp3[0] * dp2[0] * dp1[0] - - print ("initialize, integral measure :", params.integral_measure) f = (1./(af.exp( (params.E_band - params.vel_drift_x*params.p_x diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py index 348c13e1..9cd0d0ab 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py @@ -69,6 +69,7 @@ print(time_elapsed) if(latest_f is not None and time_elapsed is not None): nls.load_distribution_function(latest_f) + dump_time_array = np.loadtxt("dump_time_array.txt").tolist() using_latest_restart = True @@ -81,8 +82,8 @@ nls.dump_aux_arrays([params.mu, params.mu_ee, params.T_ee, - params.vel_drift_x, params.vel_drift_y, - params.j_x, params.j_y], + params.vel_drift_x, params.vel_drift_y + ], 'lagrange_multipliers', 'dump_lagrange_multipliers/t=' + formatted_time ) @@ -135,8 +136,8 @@ nls.dump_aux_arrays([params.mu, params.mu_ee, params.T_ee, - params.vel_drift_x, params.vel_drift_y, - params.j_x, params.j_y], + params.vel_drift_x, params.vel_drift_y + ], 'lagrange_multipliers', 'dump_lagrange_multipliers/t=' + formatted_time ) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py index dd4ca043..29cb0531 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/movie.py @@ -68,38 +68,7 @@ p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ domain.p2_start[0])/N_p2 -print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) -source_start = 0.0#params.contact_start -source_end = 0.25#params.contact_end - -drain_start = 0.0#params.contact_start -drain_end = 0.25#params.contact_end - -source_indices = (q2 > source_start) & (q2 < source_end) -drain_indices = (q2 > drain_start) & (q2 < drain_end ) - -# Left needs to be near source, right sensor near drain -sensor_1_left_start = 8.5 # um -sensor_1_left_end = 9.5 # um - -sensor_1_right_start = 8.5 # um -sensor_1_right_end = 9.5 # um - -sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) -sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) - -sensor_2_left_start = 6.5 # um -sensor_2_left_end = 7.5 # um - -sensor_2_right_start = 6.5 # um -sensor_2_right_end = 7.5 # um - -sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) -sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) - -#filepath = \ -#'/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/graphene/L_5.0_10.0_tau_ee_0.2_tau_eph_1.0/dumps' filepath = os.getcwd() moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) lagrange_multiplier_files = \ @@ -108,8 +77,6 @@ print ("moment files : ", moment_files.size) print ("lagrange multiplier files : ", lagrange_multiplier_files.size) -dt = 0.025/4#params.dt -#dump_interval = params.dump_steps time_array = np.loadtxt("dump_time_array.txt") @@ -129,10 +96,7 @@ lagrange_multipliers = \ io.readBinaryFile(lagrange_multiplier_files[file_number]) - lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 7) - #h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') - #lagrange_multipliers = h5f['lagrange_multipliers'][:] - #h5f.close() + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) mu = lagrange_multipliers[:, :, 0] mu_ee = lagrange_multipliers[:, :, 1] @@ -140,8 +104,6 @@ vel_drift_x = lagrange_multipliers[:, :, 3] vel_drift_y = lagrange_multipliers[:, :, 4] - print (vel_drift_x.shape) - print (density.shape) pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index e5773538..397eecd9 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -40,7 +40,7 @@ # Time parameters: dt = 0.025/4 # ps -t_final = 100. # ps +t_final = 20. # ps # File-writing Parameters: @@ -102,12 +102,10 @@ T_ee = None # Electron temperature used in the e-e operator vel_drift_x = None vel_drift_y = None -j_x = None -j_y = None phi = None # Electric potential in the plane of graphene sheet p_x = None p_y = None -integral_measure = None +#integral_measure = None # Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) E_band = None From 93ffe31cd7b85d83f1d54bf0e730d68ff0d940c5 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Wed, 8 Apr 2020 16:08:05 -0400 Subject: [PATCH 54/58] cleaned up params --- .../f_local_equilibrium.py | 31 ------------------- .../f_local_equilibrium_zero_T.py | 18 ----------- .../main.py | 2 +- .../params.py | 29 ++++++++--------- 4 files changed, 14 insertions(+), 66 deletions(-) diff --git a/bolt/src/electronic_boltzmann/f_local_equilibrium.py b/bolt/src/electronic_boltzmann/f_local_equilibrium.py index e9bbd21c..c28bcc15 100644 --- a/bolt/src/electronic_boltzmann/f_local_equilibrium.py +++ b/bolt/src/electronic_boltzmann/f_local_equilibrium.py @@ -52,9 +52,7 @@ def f0_defect(f, p_x, p_y, p_z, params): denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) # TODO: Multiply with the integral measure dp_x * dp_y - #a00 = af.sum(T / denominator, 0) a00 = integral_over_p(T / denominator, params.integral_measure) - #a01 = af.sum((E_upper - mu) / denominator, 0) a01 = integral_over_p((E_upper - mu) / denominator, params.integral_measure) a10 = integral_over_p(E_upper*T / denominator, params.integral_measure) a11 = integral_over_p(E_upper*(E_upper - mu) / denominator, params.integral_measure) @@ -70,8 +68,6 @@ def f0_defect(f, p_x, p_y, p_z, params): zeroth_moment = f - fermi_dirac second_moment = E_upper*(f - fermi_dirac) - #eqn_mass_conservation = af.sum(zeroth_moment, 0) - #eqn_energy_conservation = af.sum(second_moment, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) @@ -113,8 +109,6 @@ def f0_defect(f, p_x, p_y, p_z, params): zeroth_moment = f - fermi_dirac second_moment = E_upper*(f - fermi_dirac) - #eqn_mass_conservation = af.sum(zeroth_moment, 0) - #eqn_energy_conservation = af.sum(second_moment, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) @@ -177,38 +171,21 @@ def f0_ee(f, p_x, p_y, p_z, params): af.eval(a_0, a_1, a_2, a_3) # TODO: Multiply with the integral measure dp_x * dp_y - #a_00 = af.sum(a_0, 0) - #a_01 = af.sum(a_1, 0) - #a_02 = af.sum(a_2, 0) - #a_03 = af.sum(a_3, 0) a_00 = integral_over_p(a_0, params.integral_measure) a_01 = integral_over_p(a_1, params.integral_measure) a_02 = integral_over_p(a_2, params.integral_measure) a_03 = integral_over_p(a_3, params.integral_measure) - #a_10 = af.sum(E_upper * a_0, 0) - #a_11 = af.sum(E_upper * a_1, 0) - #a_12 = af.sum(E_upper * a_2, 0) - #a_13 = af.sum(E_upper * a_3, 0) - a_10 = integral_over_p(E_upper * a_0, params.integral_measure) a_11 = integral_over_p(E_upper * a_1, params.integral_measure) a_12 = integral_over_p(E_upper * a_2, params.integral_measure) a_13 = integral_over_p(E_upper * a_3, params.integral_measure) - #a_20 = af.sum(p_x * a_0, 0) - #a_21 = af.sum(p_x * a_1, 0) - #a_22 = af.sum(p_x * a_2, 0) - #a_23 = af.sum(p_x * a_3, 0) a_20 = integral_over_p(p_x * a_0, params.integral_measure) a_21 = integral_over_p(p_x * a_1, params.integral_measure) a_22 = integral_over_p(p_x * a_2, params.integral_measure) a_23 = integral_over_p(p_x * a_3, params.integral_measure) - #a_30 = af.sum(p_y * a_0, 0) - #a_31 = af.sum(p_y * a_1, 0) - #a_32 = af.sum(p_y * a_2, 0) - #a_33 = af.sum(p_y * a_3, 0) a_30 = integral_over_p(p_y * a_0, params.integral_measure) a_31 = integral_over_p(p_y * a_1, params.integral_measure) a_32 = integral_over_p(p_y * a_2, params.integral_measure) @@ -232,10 +209,6 @@ def f0_ee(f, p_x, p_y, p_z, params): first_moment_x = p_x*(f - fermi_dirac) first_moment_y = p_y*(f - fermi_dirac) - #eqn_mass_conservation = af.sum(zeroth_moment, 0) - #eqn_energy_conservation = af.sum(second_moment, 0) - #eqn_mom_x_conservation = af.sum(first_moment_x, 0) - #eqn_mom_y_conservation = af.sum(first_moment_y, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) @@ -311,10 +284,6 @@ def f0_ee(f, p_x, p_y, p_z, params): first_moment_x = p_x*(f - fermi_dirac) first_moment_y = p_y*(f - fermi_dirac) - #eqn_mass_conservation = af.sum(zeroth_moment, 0) - #eqn_energy_conservation = af.sum(second_moment, 0) - #eqn_mom_x_conservation = af.sum(first_moment_x, 0) - #eqn_mom_y_conservation = af.sum(first_moment_y, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) eqn_energy_conservation = integral_over_p(second_moment, params.integral_measure) eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) diff --git a/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py b/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py index 1bd5d976..32eccbf1 100644 --- a/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py +++ b/bolt/src/electronic_boltzmann/f_local_equilibrium_zero_T.py @@ -47,7 +47,6 @@ def f0_defect_constant_T(f, p_x, p_y, p_z, params): denominator = (k*T**2.*(af.exp(tmp) + 2. + af.exp(-tmp)) ) # TODO: Multiply with the integral measure dp_x * dp_y - #a00 = af.sum(T / denominator, 0) a00 = integral_over_p(T/denominator, params.integral_measure) fermi_dirac = 1./(af.exp( (E_upper - mu)/(k*T) ) + 1.) @@ -55,7 +54,6 @@ def f0_defect_constant_T(f, p_x, p_y, p_z, params): zeroth_moment = f - fermi_dirac - #eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure ) @@ -85,7 +83,6 @@ def f0_defect_constant_T(f, p_x, p_y, p_z, params): zeroth_moment = f - fermi_dirac - #eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure ) @@ -153,12 +150,9 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): # TODO: Multiply with the integral measure dp_x * dp_y - #a_00 = af.sum(a_0, 0) a_00 = integral_over_p(a_0, params.integral_measure) ##a_01 = af.sum(a_1, 0) - #a_02 = af.sum(a_2, 0) a_02 = integral_over_p(a_2, params.integral_measure) - #a_03 = af.sum(a_3, 0) a_03 = integral_over_p(a_3, params.integral_measure) #a_10 = af.sum(E_upper * a_0, 0) @@ -166,20 +160,14 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): #a_12 = af.sum(E_upper * a_2, 0) #a_13 = af.sum(E_upper * a_3, 0) - #a_20 = af.sum(p_x * a_0, 0) a_20 = integral_over_p(p_x * a_0, params.integral_measure) ##a_21 = af.sum(p_x * a_1, 0) - #a_22 = af.sum(p_x * a_2, 0) a_22 = integral_over_p(p_x * a_2, params.integral_measure) - #a_23 = af.sum(p_x * a_3, 0) a_23 = integral_over_p(p_x * a_3, params.integral_measure) - #a_30 = af.sum(p_y * a_0, 0) a_30 = integral_over_p(p_y * a_0, params.integral_measure) ##a_31 = af.sum(p_y * a_1, 0) - #a_32 = af.sum(p_y * a_2, 0) a_32 = integral_over_p(p_y * a_2, params.integral_measure) - #a_33 = af.sum(p_y * a_3, 0) a_33 = integral_over_p(p_y * a_3, params.integral_measure) A = [ [a_00, a_02, a_03], \ @@ -200,12 +188,9 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): first_moment_x = p_x*(f - fermi_dirac) first_moment_y = p_y*(f - fermi_dirac) - #eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) #eqn_energy_conservation = af.sum(second_moment, 0) - #eqn_mom_x_conservation = af.sum(first_moment_x, 0) eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) - #eqn_mom_y_conservation = af.sum(first_moment_y, 0) eqn_mom_y_conservation = integral_over_p(first_moment_y, params.integral_measure) residual = [eqn_mass_conservation, \ @@ -276,12 +261,9 @@ def f0_ee_constant_T(f, p_x, p_y, p_z, params): first_moment_x = p_x*(f - fermi_dirac) first_moment_y = p_y*(f - fermi_dirac) - #eqn_mass_conservation = af.sum(zeroth_moment, 0) eqn_mass_conservation = integral_over_p(zeroth_moment, params.integral_measure) #eqn_energy_conservation = af.sum(second_moment, 0) - #eqn_mom_x_conservation = af.sum(first_moment_x, 0) eqn_mom_x_conservation = integral_over_p(first_moment_x, params.integral_measure) - #eqn_mom_y_conservation = af.sum(first_moment_y, 0) eqn_mom_y_conservation = integral_over_p(first_moment_y, params.integral_measure) residual = [eqn_mass_conservation, \ diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py index 9cd0d0ab..09596215 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/main.py @@ -169,4 +169,4 @@ ) PETSc.Sys.Print("--------------------\n") -nls.dump_distribution_function('dump_f/f_laststep') +#nls.dump_distribution_function('dump_f/t_laststep') diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index 397eecd9..cdbd2eea 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -127,16 +127,18 @@ def tau(q1, q2, p1, p2, p3): def fermi_momentum_magnitude(theta): - #TODO : If cartesian coordinates are being used, conver to polar to calculate p_f - n = 6 #number of sides of the polygon - p_f = initial_mu/fermi_velocity * polygon(n, theta, rotation = np.pi/6) + if (fermi_surface_shape == 'circle'): + p_f = initial_mu/fermi_velocity # Fermi momentum + + elif (fermi_surface_shape == 'hexagon'): + n = 6 # No. of sides of polygon + p_f = (initial_mu/fermi_velocity) * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + #TODO : If cartesian coordinates are being used, convert to polar to calculate p_f + else : + raise NotImplementedError('Unsupported shape of fermi surface') return(p_f) -#def get_p_x_p_y_at_fermi_surface(theta): -# #TODO : If cartesian coordinates are being used, conver to polar to calculate p_f -# p_f = fermi_surface_magnitude(theta) -# return([p_f*af.cos(theta), p_f*af.sin(theta)]) - def band_energy(p1, p2): # Note :This function is only meant to be called once to initialize E_band @@ -189,6 +191,7 @@ def effective_mass(p1, p2): n = 6 # No. of side of polygon mass = mass_particle * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges elif (fermi_surface_shape == 'circle'): @@ -245,15 +248,9 @@ def get_p_x_and_p_y(p1, p2): r = p1; theta = p2 if (zero_temperature): - # get p_x and p_y at the Fermi surface - - if (fermi_surface_shape == 'circle'): - r = initial_mu/fermi_velocity # Fermi momentum + # Get p_x and p_y at the Fermi surface + r = fermi_momentum_magnitude(theta) - elif (fermi_surface_shape == 'hexagon'): - n = 6 #No. of sides of polygon - r = (initial_mu/fermi_velocity) * polygon(n, theta, rotation = np.pi/6) - p_x = r * af.cos(theta) p_y = r * af.sin(theta) From 4f0443682016f4d8f91ba3874a4a6e28c862a854 Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 9 Apr 2020 16:48:04 -0400 Subject: [PATCH 55/58] moment defs now take p1, p2, p3, instead of p_x, p_y, p_z --- bolt/lib/nonlinear/file_io/dump.py | 4 +++- bolt/lib/nonlinear/nonlinear_solver.py | 2 +- bolt/src/electronic_boltzmann/moments.py | 12 +++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index c787bff3..a1981bd2 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -98,9 +98,11 @@ def dump_moments(self, file_name): attributes = [a for a in dir(self.physical_system.moments) if not a.startswith('_')] - # Removing utility functions: + # Removing utility functions and imported modules: if('integral_over_p' in attributes): attributes.remove('integral_over_p') + if('params' in attributes): + attributes.remove('params') for i in range(len(attributes)): #print("i = ", i, attributes[i]) diff --git a/bolt/lib/nonlinear/nonlinear_solver.py b/bolt/lib/nonlinear/nonlinear_solver.py index 274fa962..38b8dafe 100644 --- a/bolt/lib/nonlinear/nonlinear_solver.py +++ b/bolt/lib/nonlinear/nonlinear_solver.py @@ -289,7 +289,7 @@ def __init__(self, physical_system, performance_test_flag = False): self._da_dump_moments = PETSc.DMDA().create([self.N_q1, self.N_q2], dof = self.N_species - * (len(attributes)-1), # do not countintegral_over_p in moments.py + * (len(attributes)-2), # don't countintegral_over_p, and params in moments.py proc_sizes = (nproc_in_q1, nproc_in_q2 ), diff --git a/bolt/src/electronic_boltzmann/moments.py b/bolt/src/electronic_boltzmann/moments.py index 6d0eecf5..352393e7 100644 --- a/bolt/src/electronic_boltzmann/moments.py +++ b/bolt/src/electronic_boltzmann/moments.py @@ -3,11 +3,13 @@ from bolt.src.utils.integral_over_p import integral_over_p -def density(f, p_x, p_y, p_z, integral_measure): +import params + +def density(f, p1, p2, p3, integral_measure): return(integral_over_p(f, integral_measure)) -def j_x(f, p_x, p_y, p_z, integral_measure): - return(integral_over_p(f * p_x, integral_measure)) +def j_x(f, p1, p2, p3, integral_measure): + return(integral_over_p(f * params.p_x, integral_measure)) -def j_y(f, p_x, p_y, p_z, integral_measure): - return(integral_over_p(f * p_y, integral_measure)) +def j_y(f, p1, p2, p3, integral_measure): + return(integral_over_p(f * params.p_y, integral_measure)) From 3808d5bd0def9b5c31ab70f5d071ce84cbaacfdc Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Mon, 13 Apr 2020 16:51:47 -0400 Subject: [PATCH 56/58] Added test for compute moments. Not passing and to be cleaned. --- .../test_compute_moments/PetscBinaryIO.py | 479 ++++++++++++++++++ .../boundary_conditions.py | 107 ++++ .../test_compute_moments/check.py | 42 ++ .../test_compute_moments/domain.py | 67 +++ .../test_compute_moments/edge_density.py | 122 +++++ .../test_compute_moments/edge_potential.py | 161 ++++++ .../test_compute_moments/enstrophy.py | 142 ++++++ .../test_compute_moments/initialize.py | 98 ++++ .../test_compute_moments/main.py | 57 +++ .../momentum_space_movie.py | 134 +++++ .../momentum_space_movie_debug.py | 182 +++++++ .../momentum_space_movie_zero_T.py | 183 +++++++ .../test_compute_moments/movie.py | 169 ++++++ .../test_compute_moments/params.py | 279 ++++++++++ .../test_compute_moments/petsc_conf.py | 73 +++ .../test_compute_moments/phase_vs_y.py | 180 +++++++ .../test_compute_moments/post.py | 422 +++++++++++++++ .../test_compute_moments/signals.py | 166 ++++++ .../test_compute_moments/test.py | 137 +++++ .../test_compute_moments/vorticity.py | 136 +++++ .../PetscBinaryIO.py | 479 ++++++++++++++++++ .../boundary_conditions.py | 107 ++++ .../test_compute_moments_cartesian/check.py | 42 ++ .../test_compute_moments_cartesian/domain.py | 65 +++ .../edge_density.py | 122 +++++ .../edge_potential.py | 161 ++++++ .../enstrophy.py | 142 ++++++ .../initialize.py | 98 ++++ .../test_compute_moments_cartesian/main.py | 57 +++ .../momentum_space_movie.py | 138 +++++ .../momentum_space_movie_debug.py | 182 +++++++ .../momentum_space_movie_zero_T.py | 183 +++++++ .../test_compute_moments_cartesian/movie.py | 169 ++++++ .../test_compute_moments_cartesian/params.py | 279 ++++++++++ .../petsc_conf.py | 73 +++ .../phase_vs_y.py | 180 +++++++ .../test_compute_moments_cartesian/post.py | 422 +++++++++++++++ .../test_compute_moments_cartesian/signals.py | 166 ++++++ .../test_compute_moments_cartesian/test.py | 138 +++++ .../vorticity.py | 136 +++++ 40 files changed, 6675 insertions(+) create mode 100755 example_problems/electronic_boltzmann/test_compute_moments/PetscBinaryIO.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/check.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/domain.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/edge_density.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/initialize.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/main.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_debug.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_zero_T.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/movie.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/params.py create mode 100755 example_problems/electronic_boltzmann/test_compute_moments/petsc_conf.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/post.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/signals.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/test.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments/vorticity.py create mode 100755 example_problems/electronic_boltzmann/test_compute_moments_cartesian/PetscBinaryIO.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/check.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/domain.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_density.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/initialize.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/main.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_debug.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_zero_T.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/movie.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/params.py create mode 100755 example_problems/electronic_boltzmann/test_compute_moments_cartesian/petsc_conf.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/post.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/signals.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/test.py create mode 100644 example_problems/electronic_boltzmann/test_compute_moments_cartesian/vorticity.py diff --git a/example_problems/electronic_boltzmann/test_compute_moments/PetscBinaryIO.py b/example_problems/electronic_boltzmann/test_compute_moments/PetscBinaryIO.py new file mode 100755 index 00000000..fd0e48e9 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/PetscBinaryIO.py @@ -0,0 +1,479 @@ +"""PetscBinaryIO +=============== + +Provides + 1. PETSc-named objects Vec, Mat, and IS that inherit numpy.ndarray + 2. A class to read and write these objects from PETSc binary files. + +The standard usage of this module should look like: + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> objects = io.readBinaryFile('file.dat') + +or + + >>> import PetscBinaryIO + >>> import numpy + >>> vec = numpy.array([1., 2., 3.]).view(PetscBinaryIO.Vec) + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> io.writeBinaryFile('file.dat', [vec,]) + +to read in objects one at a time use such as + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> fh = open('file.dat') + >>> objecttype = io.readObjectType(fh) + >>> if objecttype == 'Vec': + >>> v = io.readVec(fh) + + Note that one must read in the object type first and then call readVec(), readMat() etc. + + +See also PetscBinaryIO.__doc__ and methods therein. +""" + +import numpy as np +import functools + +try: + basestring # Python-2 has basestring as a common parent of unicode and str +except NameError: + basestring = str # Python-3 is unicode through and through + +def update_wrapper_with_doc(wrapper, wrapped): + """Similar to functools.update_wrapper, but also gets the wrapper's __doc__ string""" + wdoc = wrapper.__doc__ + + functools.update_wrapper(wrapper, wrapped) + if wdoc is not None: + if wrapper.__doc__ is None: + wrapper.__doc__ = wdoc + else: + wrapper.__doc__ = wrapper.__doc__ + wdoc + return wrapper + +def wraps_with_doc(wrapped): + """Similar to functools.wraps, but also gets the wrapper's __doc__ string""" + return functools.partial(update_wrapper_with_doc, wrapped=wrapped) + +def decorate_with_conf(f): + """Decorates methods to take kwargs for precisions.""" + @wraps_with_doc(f) + def decorated_f(self, *args, **kwargs): + """ + Additional kwargs: + precision: 'single', 'double', 'longlong' for scalars + indices: '32bit', '64bit' integer size + complexscalars: True/False + + Note these are set in order of preference: + 1. kwargs if given here + 2. PetscBinaryIO class __init__ arguments + 3. PETSC_DIR/PETSC_ARCH defaults + """ + + changed = False + old_precision = self.precision + old_indices = self.indices + old_complexscalars = self.complexscalars + + try: + self.precision = kwargs.pop('precision') + except KeyError: + pass + else: + changed = True + + try: + self.indices = kwargs.pop('indices') + except KeyError: + pass + else: + changed = True + + try: + self.complexscalars = kwargs.pop('complexscalars') + except KeyError: + pass + else: + changed = True + + if changed: + self._update_dtypes() + + result = f(self, *args, **kwargs) + + if changed: + self.precision = old_precision + self.indices = old_indices + self.complexscalars = old_complexscalars + self._update_dtypes() + + return result + return decorated_f + + +class DoneWithFile(Exception): pass + + +class Vec(np.ndarray): + """Vec represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + vec = numpy.array([1,2,3]).view(Vec) + """ + _classid = 1211214 + + +class MatDense(np.matrix): + """Mat represented as 2D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + mat = numpy.array([[1,0],[0,1]]).view(Mat) + """ + _classid = 1211216 + + +class MatSparse(tuple): + """Mat represented as CSR tuple ((M, N), (rowindices, col, val)) + + This should be instantiated from a tuple: + + mat = MatSparse( ((M,N), (rowindices,col,val)) ) + """ + _classid = 1211216 + def __repr__(self): + return 'MatSparse: %s'%super(MatSparse, self).__repr__() + + +class IS(np.ndarray): + """IS represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy "view" method: + + an_is = numpy.array([3,4,5]).view(IS) + """ + _classid = 1211218 + + +class PetscBinaryIO(object): + """Reader/Writer class for PETSc binary files. + + Note that by default, precisions for both scalars and indices, as well as + complex scalars, are picked up from the PETSC_DIR/PETSC_ARCH configuration + as set by environmental variables. + + Alternatively, defaults can be overridden at class instantiation, or for + a given method call. + """ + + _classid = {1211216:'Mat', + 1211214:'Vec', + 1211218:'IS', + 1211219:'Bag'} + + def __init__(self, precision=None, indices=None, complexscalars=None): + if (precision is None) or (indices is None) or (complexscalars is None): + import petsc_conf + defaultprecision, defaultindices, defaultcomplexscalars = petsc_conf.get_conf() + if precision is None: + if defaultprecision is None: + precision = 'double' + else: + precision = defaultprecision + + if indices is None: + if defaultindices is None: + indices = '32bit' + else: + indices = defaultindices + + if complexscalars is None: + if defaultcomplexscalars is None: + complexscalars = False + else: + complexscalars = defaultcomplexscalars + + self.precision = precision + self.indices = indices + self.complexscalars = complexscalars + self._update_dtypes() + + def _update_dtypes(self): + if self.indices == '64bit': + self._inttype = np.dtype('>i8') + else: + self._inttype = np.dtype('>i4') + + if self.precision == 'longlong': + nbyte = 16 + elif self.precision == 'single': + nbyte = 4 + else: + nbyte = 8 + + if self.complexscalars: + name = 'c' + nbyte = nbyte * 2 # complex scalar takes twice as many bytes + else: + name = 'f' + + self._scalartype = '>{0}{1}'.format(name, nbyte) + + @decorate_with_conf + def readVec(self, fh): + """Reads a PETSc Vec from a binary file handle, must be called after readObjectType().""" + + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + try: + vals = np.fromfile(fh, dtype=self._scalartype, count=nz) + except MemoryError: + raise IOError('Inconsistent or invalid Vec data in file') + if (len(vals) is 0): + raise IOError('Inconsistent or invalid Vec data in file') + return vals.view(Vec) + + @decorate_with_conf + def writeVec(self, fh, vec): + """Writes a PETSc Vec to a binary file handle.""" + + metadata = np.array([Vec._classid, len(vec)], dtype=self._inttype) + metadata.tofile(fh) + vec.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatSparse(self, fh): + """Reads a PETSc Mat, returning a sparse representation of the data. Must be called after readObjectType() + + (M,N), (I,J,V) = readMatSparse(fid) + + Input: + fid : file handle to open binary file. + Output: + M,N : matrix size + I,J : arrays of row and column for each nonzero + V: nonzero value + """ + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + return MatSparse(((M, N), (I, J, V))) + + @decorate_with_conf + def writeMatSparse(self, fh, mat): + """Writes a Mat into a PETSc binary file handle""" + + ((M,N), (I,J,V)) = mat + metadata = np.array([MatSparse._classid,M,N,I[-1]], dtype=self._inttype) + rownz = I[1:] - I[:-1] + + assert len(J.shape) == len(V.shape) == len(I.shape) == 1 + assert len(J) == len(V) == I[-1] == rownz.sum() + assert (rownz > -1).all() + + metadata.tofile(fh) + rownz.astype(self._inttype).tofile(fh) + J.astype(self._inttype).tofile(fh) + V.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatDense(self, fh): + """Reads a PETSc Mat, returning a dense represention of the data, must be called after readObjectType()""" + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + mat = np.zeros((M,N), dtype=self._scalartype) + for row in range(M): + rstart, rend = I[row:row+2] + mat[row, J[rstart:rend]] = V[rstart:rend] + return mat.view(MatDense) + + @decorate_with_conf + def readMatSciPy(self, fh): + from scipy.sparse import csr_matrix + (M, N), (I, J, V) = self.readMatSparse(fh) + return csr_matrix((V, J, I), shape=(M, N)) + + @decorate_with_conf + def writeMatSciPy(self, fh, mat): + from scipy.sparse import csr_matrix + if hasattr(mat, 'tocsr'): + mat = mat.tocsr() + assert isinstance(mat, csr_matrix) + V = mat.data + M,N = mat.shape + J = mat.indices + I = mat.indptr + return self.writeMatSparse(fh, (mat.shape, (mat.indptr,mat.indices,mat.data))) + + @decorate_with_conf + def readMat(self, fh, mattype='sparse'): + """Reads a PETSc Mat from binary file handle, must be called after readObjectType() + + optional mattype: 'sparse" or 'dense' + + See also: readMatSparse, readMatDense + """ + + if mattype == 'sparse': + return self.readMatSparse(fh) + elif mattype == 'dense': + return self.readMatDense(fh) + elif mattype == 'scipy.sparse': + return self.readMatSciPy(fh) + else: + raise RuntimeError('Invalid matrix type requested: choose sparse/dense/scipy.sparse') + + @decorate_with_conf + def readIS(self, fh): + """Reads a PETSc Index Set from binary file handle, must be called after readObjectType()""" + + try: + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + v = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(v) == nz + except (MemoryError,IndexError): + raise IOError('Inconsistent or invalid IS data in file') + return v.view(IS) + + @decorate_with_conf + def writeIS(self, fh, anis): + """Writes a PETSc IS to binary file handle.""" + + metadata = np.array([IS._classid, len(anis)], dtype=self._inttype) + metadata.tofile(fh) + anis.astype(self._inttype).tofile(fh) + return + + @decorate_with_conf + def readObjectType(self, fid): + """Returns the next object type as a string in the file""" + try: + header = np.fromfile(fid, dtype=self._inttype, count=1)[0] + except (MemoryError, IndexError): + raise DoneWithFile + try: + objecttype = self._classid[header] + except KeyError: + raise IOError('Invalid PetscObject CLASSID or object not implemented for python') + return objecttype + + @decorate_with_conf + def readBinaryFile(self, fid, mattype='sparse'): + """Reads a PETSc binary file, returning a tuple of the contained objects. + + objects = self.readBinaryFile(fid, **kwargs) + + Input: + fid : either file name or handle to an open binary file. + + Output: + objects : tuple of objects representing the data in numpy arrays. + + Optional: + mattype : + 'sparse': Return matrices as raw CSR: (M, N), (row, col, val). + 'dense': Return matrices as MxN numpy arrays. + 'scipy.sparse': Return matrices as scipy.sparse objects. + """ + + close = False + + if isinstance(fid, basestring): + fid = open(fid, 'rb') + close = True + + objects = [] + try: + while True: + objecttype = self.readObjectType(fid) + + if objecttype == 'Vec': + objects.append(self.readVec(fid)) + elif objecttype == 'IS': + objects.append(self.readIS(fid)) + elif objecttype == 'Mat': + objects.append(self.readMat(fid,mattype)) + elif objecttype == 'Bag': + raise NotImplementedError('Bag Reader not yet implemented') + except DoneWithFile: + pass + finally: + if close: + fid.close() + + return tuple(objects) + + @decorate_with_conf + def writeBinaryFile(self, fid, objects): + """Writes a PETSc binary file containing the objects given. + + readBinaryFile(fid, objects) + + Input: + fid : either file handle to an open binary file, or filename. + objects : list of objects representing the data in numpy arrays, + which must be of type Vec, IS, MatSparse, or MatSciPy. + """ + close = False + if isinstance(fid, basestring): + fid = open(fid, 'wb') + close = True + + for petscobj in objects: + if (isinstance(petscobj, Vec)): + self.writeVec(fid, petscobj) + elif (isinstance(petscobj, IS)): + self.writeIS(fid, petscobj) + elif (isinstance(petscobj, MatSparse)): + self.writeMatSparse(fid, petscobj) + elif (isinstance(petscobj, MatDense)): + if close: + fid.close() + raise NotImplementedError('Writing a dense matrix is not yet supported') + else: + try: + self.writeMatSciPy(fid, petscobj) + except AssertionError: + if close: + fid.close() + raise TypeError('Object %s is not a valid PETSc object'%(petscobj.__repr__())) + if close: + fid.close() + return diff --git a/example_problems/electronic_boltzmann/test_compute_moments/boundary_conditions.py b/example_problems/electronic_boltzmann/test_compute_moments/boundary_conditions.py new file mode 100644 index 00000000..762f5e79 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/boundary_conditions.py @@ -0,0 +1,107 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror+dirichlet' +in_q1_right = 'mirror+dirichlet' +in_q2_bottom = 'mirror' +in_q2_top = 'mirror' + +@af.broadcast +def f_left(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_in = params.vel_drift_x_in + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_right(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_out = params.vel_drift_x_out + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/test_compute_moments/check.py b/example_problems/electronic_boltzmann/test_compute_moments/check.py new file mode 100644 index 00000000..71fe46ef --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/check.py @@ -0,0 +1,42 @@ +import numpy as np +import params +import arrayfire as af +import pylab as pl + +import domain + +from bolt.src.electronic_boltzmann.utils.polygon import polygon + +p2_start = -np.pi +p2_end = np.pi +N_p2 = domain.N_p2 +theta = \ + p2_start + (0.5 + np.arange(N_p2))*(p2_end - p2_start)/N_p2 + +theta = af.from_ndarray(theta) + +hexa = polygon(6, theta, rotation = np.pi/6) +hexa = hexa.to_ndarray() + +#pl.polar(theta, hexa) + +#pl.plot(theta, hexa * np.cos(theta)) +#pl.plot(theta, hexa * np.sin(theta)) + +pl.gca().set_aspect(1) +pl.plot(hexa*np.cos(theta), hexa*np.sin(theta)) + +#p_hat_0_old = np.loadtxt("P_hat_0_old.txt") +#p_hat_1_old = np.loadtxt("P_hat_1_old.txt") + +#p_hat_0 = np.loadtxt("P_hat_0.txt") +#p_hat_1 = np.loadtxt("P_hat_1.txt") + +#pl.plot(theta, p_hat_0_old) +#pl.plot(theta, p_hat_1_old) + +#pl.plot(theta, p_hat_0, '--') +#pl.plot(theta, p_hat_1, '--') + + +pl.savefig("images/test.png") diff --git a/example_problems/electronic_boltzmann/test_compute_moments/domain.py b/example_problems/electronic_boltzmann/test_compute_moments/domain.py new file mode 100644 index 00000000..96ac75e4 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/domain.py @@ -0,0 +1,67 @@ +import numpy as np +import params + +q1_start = 0. +q1_end = 1.0 +N_q1 = 20 + +q2_start = 0. +q2_end = 1.25 +N_q2 = 25 + +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation +N_p1 = 1 # Set equal to 1 for 1D polar + +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space +#p1_start = [-0.04] +#p1_end = [0.04] + + +# In the 2D polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] + +# Uncomment the following for the 1D polar representation of momentum space +p1_start = [0.5*params.initial_mu/params.fermi_velocity] +p1_end = [1.5*params.initial_mu/params.fermi_velocity] + + +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero +N_p2 = 2048 + +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +#p2_start = [-0.04] +#p2_end = [0.04] + +# In the 2D polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +#p2_start = [-np.pi] +#p2_end = [np.pi] +p2_start = [-3.14159265359] +p2_end = [3.14159265359] + +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/test_compute_moments/edge_density.py b/example_problems/electronic_boltzmann/test_compute_moments/edge_density.py new file mode 100644 index 00000000..3697590e --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/edge_density.py @@ -0,0 +1,122 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/edge_potential.py b/example_problems/electronic_boltzmann/test_compute_moments/edge_potential.py new file mode 100644 index 00000000..b50b3bf5 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/edge_potential.py @@ -0,0 +1,161 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#print("Reading sensor signal...") +print("Loading data...") +density = [] +edge_density = [] +for file_number, dump_file in enumerate(moment_files): + + print("File number = ", file_number, ' of ', moment_files.size) + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density.append(moments[:, :, 0]) + edge_density.append(density[file_number][0, sensor_1_left_indices]) + +density = np.array(density) +edge_density = np.array(edge_density) + +mean_density = np.mean(density) +max_density = np.max(density) +min_density = np.min(density) + +np.savetxt("edge_density.txt", edge_density) + +print("Dumping data...") +for file_number in yt.parallel_objects(range(density.shape[0])): + + print("File number = ", file_number, ' of ', moment_files.size) + + pl.semilogy(q2[sensor_1_left_indices], + density[file_number][0, sensor_1_left_indices], + ) + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.title(r'Time = ' + "%.2f"%(file_number*dt*dump_interval) + " ps") + + pl.xlim([sensor_1_left_start, sensor_1_left_end]) + #pl.ylim([min_density-mean_density, max_density-mean_density]) + #pl.ylim([0., np.log(max_density)]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$ ps, $\\tau_\mathrm{mr} = 3.0$ ps') + #pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.savefig('images/density_' + '%06d'%file_number + '.png') + pl.clf() + + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/enstrophy.py b/example_problems/electronic_boltzmann/test_compute_moments/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/initialize.py b/example_problems/electronic_boltzmann/test_compute_moments/initialize.py new file mode 100644 index 00000000..c0d986bf --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/initialize.py @@ -0,0 +1,98 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +import domain + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 0.*params.vel_drift_x_in + 0.*q1 + params.vel_drift_y = 0.*q1 + + print (params.vel_drift_x) + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + + params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + # Evaluating velocity space resolution for each species: + dp1 = []; dp2 = []; dp3 = [] + N_p1 = domain.N_p1; N_p2 = domain.N_p2; N_p3 = domain.N_p3 + p1_start = domain.p1_start; p1_end = domain.p1_end + p2_start = domain.p2_start; p2_end = domain.p2_end + p3_start = domain.p3_start; p3_end = domain.p3_end + + N_species = len(params.mass) + for i in range(N_species): + dp1.append((p1_end[i] - p1_start[i]) / N_p1) + dp2.append((p2_end[i] - p2_start[i]) / N_p2) + dp3.append((p3_end[i] - p3_start[i]) / N_p3) + + + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + + if (params.p_space_grid == 'cartesian'): + dp_x = dp1[0]; dp_y = dp2[0]; dp_z = dp3[0] + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * dp_z * dp_y * dp_x + + elif (params.p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + # Integral : \int delta(r - r_F) F(r, theta) r dr dtheta + r = p1; theta = p2 + dp_r = dp1[0]; dp_theta = dp2[0] + + if (params.zero_temperature): + # Assumption : F(r, theta) = delta(r-r_F)*F(theta) + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * p_f * dp_theta + + else: + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * r * dp_r * dp_theta + + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + + + f = (1./(af.exp( (params.E_band - params.vel_drift_x*params.p_x + - params.vel_drift_y*params.p_y + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/test_compute_moments/main.py b/example_problems/electronic_boltzmann/test_compute_moments/main.py new file mode 100644 index 00000000..fa5ff601 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/main.py @@ -0,0 +1,57 @@ +import os +import arrayfire as af +import numpy as np +import math +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +from mpi4py import MPI +MPI.WTIME_IS_GLOBAL=True + +from bolt.lib.physical_system import physical_system +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.utils.restart_latest import latest_output, format_time + +import domain +import boundary_conditions +import initialize +import params + +import bolt.src.electronic_boltzmann.advection_terms \ + as advection_terms +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator +import bolt.src.electronic_boltzmann.moments \ + as moments + +from bolt.lib.nonlinear.compute_moments import compute_moments +from bolt.lib.utils.calculate_q import calculate_q + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moments + ) + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +N_g = domain.N_ghost +params.rank = nls._comm.rank + + +nls.dump_moments('dump_moments/moments') +nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y + ], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/lagrange_multipliers' + ) +nls.dump_distribution_function('dump_f/f') + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie.py b/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie.py new file mode 100644 index 00000000..1de644d7 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie.py @@ -0,0 +1,134 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q1_position, q2_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_debug.py b/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_debug.py new file mode 100644 index 00000000..0b2c719d --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_debug.py @@ -0,0 +1,182 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(1): + for index_2 in range(N_q2): + + q1_position = index_1 + q2_position = index_2 + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = 1.#np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func - \ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..0dae45a6 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/momentum_space_movie_zero_T.py @@ -0,0 +1,183 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func_background = np.mean(dist_func) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/movie.py b/example_problems/electronic_boltzmann/test_compute_moments/movie.py new file mode 100644 index 00000000..e335f680 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/movie.py @@ -0,0 +1,169 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[::-1]): + + file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + #print (j_x.shape, vel_drift_x.shape, density.shape) + + pl.subplot(221) + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.colorbar() + + pl.subplot(222) + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + j_x, j_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.colorbar() + + pl.subplot(223) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_x - density*vel_drift_x).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + pl.subplot(224) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_y - density*vel_drift_y).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + #pl.tight_layout() + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/params.py b/example_problems/electronic_boltzmann/test_compute_moments/params.py new file mode 100644 index 00000000..fd53d7cb --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/params.py @@ -0,0 +1,279 @@ +import numpy as np +import arrayfire as af + +from bolt.src.electronic_boltzmann.utils.polygon import polygon +from bolt.src.electronic_boltzmann.utils.unit_vectors import normal_to_hexagon_unit_vec + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +electrostatic_solver_every_nth_step = 1000000 + + +# Time parameters: +dt = 0.025/4 # ps +t_final = 25. # ps + + +# File-writing Parameters: +dump_steps = 5 +dump_dist_after = 1600 +# Set to zero for no file-writing +dt_dump_f = 1000*dt #ps +# ALWAYS set dump moments and dump fields at same frequency: +dt_dump_moments = dt_dump_fields = 5*dt #ps + + +# Dimensionality considered in velocity space: +p_dim = 1 +p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py +#TODO : Use only polar2D for PdCoO2 + + +zero_temperature = (p_dim==1) +dispersion = 'linear' # 'linear' or 'quadratic' +fermi_surface_shape = 'circle' # Supports 'circle' or 'hexagon' + + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 6 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 0.0 # um +contact_end = 0.25 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 12e-5 +initial_mu = 0.015 +vel_drift_x_in = 1e-4*fermi_velocity +vel_drift_x_out = 1e-4*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +phi = None # Electric potential in the plane of graphene sheet +p_x = None +p_y = None +#integral_measure = None + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + + +def fermi_momentum_magnitude(theta): + if (fermi_surface_shape == 'circle'): + p_f = initial_mu/fermi_velocity # Fermi momentum + + elif (fermi_surface_shape == 'hexagon'): + n = 6 # No. of sides of polygon + p_f = (initial_mu/fermi_velocity) * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + #TODO : If cartesian coordinates are being used, convert to polar to calculate p_f + else : + raise NotImplementedError('Unsupported shape of fermi surface') + return(p_f) + + +def band_energy(p1, p2): + # Note :This function is only meant to be called once to initialize E_band + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1 + theta = p2 + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + if (dispersion == 'linear'): + + E_upper = p*fermi_velocity + + elif (dispersion == 'quadratic'): + + m = effective_mass(p1, p2) + E_upper = p**2/(2.*m) + + if (zero_temperature): + + E_upper = initial_mu * p**0. + + af.eval(E_upper) + return(E_upper) + + +def effective_mass(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + + theta = af.atan(p_y/p_x) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + if (fermi_surface_shape == 'hexagon'): + + n = 6 # No. of side of polygon + mass = mass_particle * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + + elif (fermi_surface_shape == 'circle'): + + # For now, just return the free electron mass + mass = mass_particle + + return(mass) + +def band_velocity(p1, p2): + # Note :This function is only meant to be called once to initialize the vel vectors + + if (p_space_grid == 'cartesian'): + p_x_local = p1 + p_y_local = p2 + + theta = af.atan(p_y_local/p_x_local) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + if (fermi_surface_shape == 'circle'): + + v_f_hat = p_hat + + elif (fermi_surface_shape == 'hexagon'): + + v_f_hat = normal_to_hexagon_unit_vec(theta) + + # Quadratic dispersion + m = effective_mass(p1, p2) + v_f = p/m + + if (dispersion == 'linear' or zero_temperature): + + v_f = fermi_velocity + + upper_band_velocity = [v_f * v_f_hat[0], v_f * v_f_hat[1]] + + return(upper_band_velocity) + +def get_p_x_and_p_y(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + + if (zero_temperature): + # Get p_x and p_y at the Fermi surface + r = fermi_momentum_magnitude(theta) + + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + return([p_x, p_y]) + +# Restart(Set to zero for no-restart): +latest_restart = True +t_restart = 0 + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/test_compute_moments/petsc_conf.py b/example_problems/electronic_boltzmann/test_compute_moments/petsc_conf.py new file mode 100755 index 00000000..22781ed2 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/petsc_conf.py @@ -0,0 +1,73 @@ +import warnings + +def get_conf(): + """Parses various PETSc configuration/include files to get data types. + + precision, indices, complexscalars = get_conf() + + Output: + precision: 'single', 'double', 'longlong' indicates precision of PetscScalar + indices: '32', '64' indicates bit-size of PetscInt + complex: True/False indicates whether PetscScalar is complex or not. + """ + + import sys, os + precision = None + indices = None + complexscalars = None + + if 'PETSC_DIR' in os.environ: + petscdir = os.environ['PETSC_DIR'] + else: + warnings.warn('PETSC_DIR env not set - unable to locate PETSc installation, using defaults') + return None, None, None + + if os.path.isfile(os.path.join(petscdir,'lib','petsc','conf','petscrules')): + # found prefix install + petscvariables = os.path.join(petscdir,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,'include','petscconf.h') + else: + if 'PETSC_ARCH' in os.environ: + petscarch = os.environ['PETSC_ARCH'] + if os.path.isfile(os.path.join(petscdir,petscarch,'lib','petsc','conf','petscrules')): + # found legacy install + petscvariables = os.path.join(petscdir,petscarch,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,petscarch,'include','petscconf.h') + else: + warnings.warn('Unable to locate PETSc installation in specified PETSC_DIR/PETSC_ARCH, using defaults') + return None, None, None + else: + warnings.warn('PETSC_ARCH env not set or incorrect PETSC_DIR is given - unable to locate PETSc installation, using defaults') + return None, None, None + + try: + fid = open(petscvariables, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('PETSC_PRECISION'): + precision = line.strip().split('=')[1].strip('\n').strip() + + fid.close() + + try: + fid = open(petscconfinclude, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('#define PETSC_USE_64BIT_INDICES 1'): + indices = '64bit' + elif line.startswith('#define PETSC_USE_COMPLEX 1'): + complexscalars = True + + if indices is None: + indices = '32bit' + if complexscalars is None: + complexscalars = False + fid.close() + + return precision, indices, complexscalars diff --git a/example_problems/electronic_boltzmann/test_compute_moments/phase_vs_y.py b/example_problems/electronic_boltzmann/test_compute_moments/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/post.py b/example_problems/electronic_boltzmann/test_compute_moments/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/signals.py b/example_problems/electronic_boltzmann/test_compute_moments/signals.py new file mode 100644 index 00000000..979640c3 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/signals.py @@ -0,0 +1,166 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +#filepath = '/home/mchandra/gitansh/zero_T/example_problems/electronic_boltzmann/graphene/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC' +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + +# Calculate the phase difference between input_signal_array and sensor_normalized +# Code copied from : +# https:/stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves + +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] + +#Force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) + +#pl.plot(time_array, input_signal_array) +pl.plot(time_array, sensor_normalized) +#pl.axhline(0, color='black', linestyle='--') + +#pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=1) +#pl.text(135, 1.14, '$\phi : %.2f \; rad$' %phase_diff) +pl.xlabel(r'Time (ps)') +#pl.xlim([0, 200]) +#pl.ylim([-1.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 0.5$ ps') +pl.savefig('images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/test.py b/example_problems/electronic_boltzmann/test_compute_moments/test.py new file mode 100644 index 00000000..bfe5688a --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/test.py @@ -0,0 +1,137 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[:]): + + #file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + print (vel_drift_x) + print (j_x, density) + + + pl.subplot(121) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_x - density*vel_drift_x).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + pl.subplot(122) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_y - density*vel_drift_y).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + pl.tight_layout() + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments/vorticity.py b/example_problems/electronic_boltzmann/test_compute_moments/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/PetscBinaryIO.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/PetscBinaryIO.py new file mode 100755 index 00000000..fd0e48e9 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/PetscBinaryIO.py @@ -0,0 +1,479 @@ +"""PetscBinaryIO +=============== + +Provides + 1. PETSc-named objects Vec, Mat, and IS that inherit numpy.ndarray + 2. A class to read and write these objects from PETSc binary files. + +The standard usage of this module should look like: + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> objects = io.readBinaryFile('file.dat') + +or + + >>> import PetscBinaryIO + >>> import numpy + >>> vec = numpy.array([1., 2., 3.]).view(PetscBinaryIO.Vec) + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> io.writeBinaryFile('file.dat', [vec,]) + +to read in objects one at a time use such as + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> fh = open('file.dat') + >>> objecttype = io.readObjectType(fh) + >>> if objecttype == 'Vec': + >>> v = io.readVec(fh) + + Note that one must read in the object type first and then call readVec(), readMat() etc. + + +See also PetscBinaryIO.__doc__ and methods therein. +""" + +import numpy as np +import functools + +try: + basestring # Python-2 has basestring as a common parent of unicode and str +except NameError: + basestring = str # Python-3 is unicode through and through + +def update_wrapper_with_doc(wrapper, wrapped): + """Similar to functools.update_wrapper, but also gets the wrapper's __doc__ string""" + wdoc = wrapper.__doc__ + + functools.update_wrapper(wrapper, wrapped) + if wdoc is not None: + if wrapper.__doc__ is None: + wrapper.__doc__ = wdoc + else: + wrapper.__doc__ = wrapper.__doc__ + wdoc + return wrapper + +def wraps_with_doc(wrapped): + """Similar to functools.wraps, but also gets the wrapper's __doc__ string""" + return functools.partial(update_wrapper_with_doc, wrapped=wrapped) + +def decorate_with_conf(f): + """Decorates methods to take kwargs for precisions.""" + @wraps_with_doc(f) + def decorated_f(self, *args, **kwargs): + """ + Additional kwargs: + precision: 'single', 'double', 'longlong' for scalars + indices: '32bit', '64bit' integer size + complexscalars: True/False + + Note these are set in order of preference: + 1. kwargs if given here + 2. PetscBinaryIO class __init__ arguments + 3. PETSC_DIR/PETSC_ARCH defaults + """ + + changed = False + old_precision = self.precision + old_indices = self.indices + old_complexscalars = self.complexscalars + + try: + self.precision = kwargs.pop('precision') + except KeyError: + pass + else: + changed = True + + try: + self.indices = kwargs.pop('indices') + except KeyError: + pass + else: + changed = True + + try: + self.complexscalars = kwargs.pop('complexscalars') + except KeyError: + pass + else: + changed = True + + if changed: + self._update_dtypes() + + result = f(self, *args, **kwargs) + + if changed: + self.precision = old_precision + self.indices = old_indices + self.complexscalars = old_complexscalars + self._update_dtypes() + + return result + return decorated_f + + +class DoneWithFile(Exception): pass + + +class Vec(np.ndarray): + """Vec represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + vec = numpy.array([1,2,3]).view(Vec) + """ + _classid = 1211214 + + +class MatDense(np.matrix): + """Mat represented as 2D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + mat = numpy.array([[1,0],[0,1]]).view(Mat) + """ + _classid = 1211216 + + +class MatSparse(tuple): + """Mat represented as CSR tuple ((M, N), (rowindices, col, val)) + + This should be instantiated from a tuple: + + mat = MatSparse( ((M,N), (rowindices,col,val)) ) + """ + _classid = 1211216 + def __repr__(self): + return 'MatSparse: %s'%super(MatSparse, self).__repr__() + + +class IS(np.ndarray): + """IS represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy "view" method: + + an_is = numpy.array([3,4,5]).view(IS) + """ + _classid = 1211218 + + +class PetscBinaryIO(object): + """Reader/Writer class for PETSc binary files. + + Note that by default, precisions for both scalars and indices, as well as + complex scalars, are picked up from the PETSC_DIR/PETSC_ARCH configuration + as set by environmental variables. + + Alternatively, defaults can be overridden at class instantiation, or for + a given method call. + """ + + _classid = {1211216:'Mat', + 1211214:'Vec', + 1211218:'IS', + 1211219:'Bag'} + + def __init__(self, precision=None, indices=None, complexscalars=None): + if (precision is None) or (indices is None) or (complexscalars is None): + import petsc_conf + defaultprecision, defaultindices, defaultcomplexscalars = petsc_conf.get_conf() + if precision is None: + if defaultprecision is None: + precision = 'double' + else: + precision = defaultprecision + + if indices is None: + if defaultindices is None: + indices = '32bit' + else: + indices = defaultindices + + if complexscalars is None: + if defaultcomplexscalars is None: + complexscalars = False + else: + complexscalars = defaultcomplexscalars + + self.precision = precision + self.indices = indices + self.complexscalars = complexscalars + self._update_dtypes() + + def _update_dtypes(self): + if self.indices == '64bit': + self._inttype = np.dtype('>i8') + else: + self._inttype = np.dtype('>i4') + + if self.precision == 'longlong': + nbyte = 16 + elif self.precision == 'single': + nbyte = 4 + else: + nbyte = 8 + + if self.complexscalars: + name = 'c' + nbyte = nbyte * 2 # complex scalar takes twice as many bytes + else: + name = 'f' + + self._scalartype = '>{0}{1}'.format(name, nbyte) + + @decorate_with_conf + def readVec(self, fh): + """Reads a PETSc Vec from a binary file handle, must be called after readObjectType().""" + + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + try: + vals = np.fromfile(fh, dtype=self._scalartype, count=nz) + except MemoryError: + raise IOError('Inconsistent or invalid Vec data in file') + if (len(vals) is 0): + raise IOError('Inconsistent or invalid Vec data in file') + return vals.view(Vec) + + @decorate_with_conf + def writeVec(self, fh, vec): + """Writes a PETSc Vec to a binary file handle.""" + + metadata = np.array([Vec._classid, len(vec)], dtype=self._inttype) + metadata.tofile(fh) + vec.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatSparse(self, fh): + """Reads a PETSc Mat, returning a sparse representation of the data. Must be called after readObjectType() + + (M,N), (I,J,V) = readMatSparse(fid) + + Input: + fid : file handle to open binary file. + Output: + M,N : matrix size + I,J : arrays of row and column for each nonzero + V: nonzero value + """ + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + return MatSparse(((M, N), (I, J, V))) + + @decorate_with_conf + def writeMatSparse(self, fh, mat): + """Writes a Mat into a PETSc binary file handle""" + + ((M,N), (I,J,V)) = mat + metadata = np.array([MatSparse._classid,M,N,I[-1]], dtype=self._inttype) + rownz = I[1:] - I[:-1] + + assert len(J.shape) == len(V.shape) == len(I.shape) == 1 + assert len(J) == len(V) == I[-1] == rownz.sum() + assert (rownz > -1).all() + + metadata.tofile(fh) + rownz.astype(self._inttype).tofile(fh) + J.astype(self._inttype).tofile(fh) + V.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatDense(self, fh): + """Reads a PETSc Mat, returning a dense represention of the data, must be called after readObjectType()""" + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + mat = np.zeros((M,N), dtype=self._scalartype) + for row in range(M): + rstart, rend = I[row:row+2] + mat[row, J[rstart:rend]] = V[rstart:rend] + return mat.view(MatDense) + + @decorate_with_conf + def readMatSciPy(self, fh): + from scipy.sparse import csr_matrix + (M, N), (I, J, V) = self.readMatSparse(fh) + return csr_matrix((V, J, I), shape=(M, N)) + + @decorate_with_conf + def writeMatSciPy(self, fh, mat): + from scipy.sparse import csr_matrix + if hasattr(mat, 'tocsr'): + mat = mat.tocsr() + assert isinstance(mat, csr_matrix) + V = mat.data + M,N = mat.shape + J = mat.indices + I = mat.indptr + return self.writeMatSparse(fh, (mat.shape, (mat.indptr,mat.indices,mat.data))) + + @decorate_with_conf + def readMat(self, fh, mattype='sparse'): + """Reads a PETSc Mat from binary file handle, must be called after readObjectType() + + optional mattype: 'sparse" or 'dense' + + See also: readMatSparse, readMatDense + """ + + if mattype == 'sparse': + return self.readMatSparse(fh) + elif mattype == 'dense': + return self.readMatDense(fh) + elif mattype == 'scipy.sparse': + return self.readMatSciPy(fh) + else: + raise RuntimeError('Invalid matrix type requested: choose sparse/dense/scipy.sparse') + + @decorate_with_conf + def readIS(self, fh): + """Reads a PETSc Index Set from binary file handle, must be called after readObjectType()""" + + try: + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + v = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(v) == nz + except (MemoryError,IndexError): + raise IOError('Inconsistent or invalid IS data in file') + return v.view(IS) + + @decorate_with_conf + def writeIS(self, fh, anis): + """Writes a PETSc IS to binary file handle.""" + + metadata = np.array([IS._classid, len(anis)], dtype=self._inttype) + metadata.tofile(fh) + anis.astype(self._inttype).tofile(fh) + return + + @decorate_with_conf + def readObjectType(self, fid): + """Returns the next object type as a string in the file""" + try: + header = np.fromfile(fid, dtype=self._inttype, count=1)[0] + except (MemoryError, IndexError): + raise DoneWithFile + try: + objecttype = self._classid[header] + except KeyError: + raise IOError('Invalid PetscObject CLASSID or object not implemented for python') + return objecttype + + @decorate_with_conf + def readBinaryFile(self, fid, mattype='sparse'): + """Reads a PETSc binary file, returning a tuple of the contained objects. + + objects = self.readBinaryFile(fid, **kwargs) + + Input: + fid : either file name or handle to an open binary file. + + Output: + objects : tuple of objects representing the data in numpy arrays. + + Optional: + mattype : + 'sparse': Return matrices as raw CSR: (M, N), (row, col, val). + 'dense': Return matrices as MxN numpy arrays. + 'scipy.sparse': Return matrices as scipy.sparse objects. + """ + + close = False + + if isinstance(fid, basestring): + fid = open(fid, 'rb') + close = True + + objects = [] + try: + while True: + objecttype = self.readObjectType(fid) + + if objecttype == 'Vec': + objects.append(self.readVec(fid)) + elif objecttype == 'IS': + objects.append(self.readIS(fid)) + elif objecttype == 'Mat': + objects.append(self.readMat(fid,mattype)) + elif objecttype == 'Bag': + raise NotImplementedError('Bag Reader not yet implemented') + except DoneWithFile: + pass + finally: + if close: + fid.close() + + return tuple(objects) + + @decorate_with_conf + def writeBinaryFile(self, fid, objects): + """Writes a PETSc binary file containing the objects given. + + readBinaryFile(fid, objects) + + Input: + fid : either file handle to an open binary file, or filename. + objects : list of objects representing the data in numpy arrays, + which must be of type Vec, IS, MatSparse, or MatSciPy. + """ + close = False + if isinstance(fid, basestring): + fid = open(fid, 'wb') + close = True + + for petscobj in objects: + if (isinstance(petscobj, Vec)): + self.writeVec(fid, petscobj) + elif (isinstance(petscobj, IS)): + self.writeIS(fid, petscobj) + elif (isinstance(petscobj, MatSparse)): + self.writeMatSparse(fid, petscobj) + elif (isinstance(petscobj, MatDense)): + if close: + fid.close() + raise NotImplementedError('Writing a dense matrix is not yet supported') + else: + try: + self.writeMatSciPy(fid, petscobj) + except AssertionError: + if close: + fid.close() + raise TypeError('Object %s is not a valid PETSc object'%(petscobj.__repr__())) + if close: + fid.close() + return diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/boundary_conditions.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/boundary_conditions.py new file mode 100644 index 00000000..762f5e79 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/boundary_conditions.py @@ -0,0 +1,107 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror+dirichlet' +in_q1_right = 'mirror+dirichlet' +in_q2_bottom = 'mirror' +in_q2_top = 'mirror' + +@af.broadcast +def f_left(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_in = params.vel_drift_x_in + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_x_in*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_right(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_x_out = params.vel_drift_x_out + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q2_contact_start = params.contact_start + q2_contact_end = params.contact_end + + cond = ((q2 >= q2_contact_start) & \ + (q2 <= q2_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/check.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/check.py new file mode 100644 index 00000000..71fe46ef --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/check.py @@ -0,0 +1,42 @@ +import numpy as np +import params +import arrayfire as af +import pylab as pl + +import domain + +from bolt.src.electronic_boltzmann.utils.polygon import polygon + +p2_start = -np.pi +p2_end = np.pi +N_p2 = domain.N_p2 +theta = \ + p2_start + (0.5 + np.arange(N_p2))*(p2_end - p2_start)/N_p2 + +theta = af.from_ndarray(theta) + +hexa = polygon(6, theta, rotation = np.pi/6) +hexa = hexa.to_ndarray() + +#pl.polar(theta, hexa) + +#pl.plot(theta, hexa * np.cos(theta)) +#pl.plot(theta, hexa * np.sin(theta)) + +pl.gca().set_aspect(1) +pl.plot(hexa*np.cos(theta), hexa*np.sin(theta)) + +#p_hat_0_old = np.loadtxt("P_hat_0_old.txt") +#p_hat_1_old = np.loadtxt("P_hat_1_old.txt") + +#p_hat_0 = np.loadtxt("P_hat_0.txt") +#p_hat_1 = np.loadtxt("P_hat_1.txt") + +#pl.plot(theta, p_hat_0_old) +#pl.plot(theta, p_hat_1_old) + +#pl.plot(theta, p_hat_0, '--') +#pl.plot(theta, p_hat_1, '--') + + +pl.savefig("images/test.png") diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/domain.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/domain.py new file mode 100644 index 00000000..e6aebf7c --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/domain.py @@ -0,0 +1,65 @@ +import numpy as np +import params + +q1_start = 0. +q1_end = 1.0 +N_q1 = 20 + +q2_start = 0. +q2_end = 1.25 +N_q2 = 25 + +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation +N_p1 = 128 # Set equal to 1 for 1D polar + +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space +p1_start = [-0.04] +p1_end = [0.04] + + +# In the 2D polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] + +# Uncomment the following for the 1D polar representation of momentum space +#p1_start = [0.5*params.initial_mu/params.fermi_velocity] +#p1_end = [1.5*params.initial_mu/params.fermi_velocity] + + +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero +N_p2 = 128 + +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +p2_start = [-0.04] +p2_end = [0.04] + +# In the 2D polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +#p2_start = [-np.pi] +#p2_end = [np.pi] + +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_density.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_density.py new file mode 100644 index 00000000..3697590e --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_density.py @@ -0,0 +1,122 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_potential.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_potential.py new file mode 100644 index 00000000..b50b3bf5 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/edge_potential.py @@ -0,0 +1,161 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#print("Reading sensor signal...") +print("Loading data...") +density = [] +edge_density = [] +for file_number, dump_file in enumerate(moment_files): + + print("File number = ", file_number, ' of ', moment_files.size) + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density.append(moments[:, :, 0]) + edge_density.append(density[file_number][0, sensor_1_left_indices]) + +density = np.array(density) +edge_density = np.array(edge_density) + +mean_density = np.mean(density) +max_density = np.max(density) +min_density = np.min(density) + +np.savetxt("edge_density.txt", edge_density) + +print("Dumping data...") +for file_number in yt.parallel_objects(range(density.shape[0])): + + print("File number = ", file_number, ' of ', moment_files.size) + + pl.semilogy(q2[sensor_1_left_indices], + density[file_number][0, sensor_1_left_indices], + ) + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.title(r'Time = ' + "%.2f"%(file_number*dt*dump_interval) + " ps") + + pl.xlim([sensor_1_left_start, sensor_1_left_end]) + #pl.ylim([min_density-mean_density, max_density-mean_density]) + #pl.ylim([0., np.log(max_density)]) + + #pl.gca().set_aspect('equal') + #pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$ ps, $\\tau_\mathrm{mr} = 3.0$ ps') + #pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.savefig('images/density_' + '%06d'%file_number + '.png') + pl.clf() + + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/enstrophy.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/initialize.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/initialize.py new file mode 100644 index 00000000..ef1bc936 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/initialize.py @@ -0,0 +1,98 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +import domain + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 1.*params.vel_drift_x_in + 0.*q1 + params.vel_drift_y = 0.*q1 + + #print (params.vel_drift_x) + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + + params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + # Evaluating velocity space resolution for each species: + dp1 = []; dp2 = []; dp3 = [] + N_p1 = domain.N_p1; N_p2 = domain.N_p2; N_p3 = domain.N_p3 + p1_start = domain.p1_start; p1_end = domain.p1_end + p2_start = domain.p2_start; p2_end = domain.p2_end + p3_start = domain.p3_start; p3_end = domain.p3_end + + N_species = len(params.mass) + for i in range(N_species): + dp1.append((p1_end[i] - p1_start[i]) / N_p1) + dp2.append((p2_end[i] - p2_start[i]) / N_p2) + dp3.append((p3_end[i] - p3_start[i]) / N_p3) + + + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + + if (params.p_space_grid == 'cartesian'): + dp_x = dp1[0]; dp_y = dp2[0]; dp_z = dp3[0] + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * dp_z * dp_y * dp_x + + elif (params.p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + # Integral : \int delta(r - r_F) F(r, theta) r dr dtheta + r = p1; theta = p2 + dp_r = dp1[0]; dp_theta = dp2[0] + + if (params.zero_temperature): + # Assumption : F(r, theta) = delta(r-r_F)*F(theta) + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * p_f * dp_theta + + else: + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * r * dp_r * dp_theta + + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + + + f = (1./(af.exp( (params.E_band - params.vel_drift_x*params.p_x + - params.vel_drift_y*params.p_y + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/main.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/main.py new file mode 100644 index 00000000..fa5ff601 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/main.py @@ -0,0 +1,57 @@ +import os +import arrayfire as af +import numpy as np +import math +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +from mpi4py import MPI +MPI.WTIME_IS_GLOBAL=True + +from bolt.lib.physical_system import physical_system +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.utils.restart_latest import latest_output, format_time + +import domain +import boundary_conditions +import initialize +import params + +import bolt.src.electronic_boltzmann.advection_terms \ + as advection_terms +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator +import bolt.src.electronic_boltzmann.moments \ + as moments + +from bolt.lib.nonlinear.compute_moments import compute_moments +from bolt.lib.utils.calculate_q import calculate_q + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moments + ) + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +N_g = domain.N_ghost +params.rank = nls._comm.rank + + +nls.dump_moments('dump_moments/moments') +nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y + ], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/lagrange_multipliers' + ) +nls.dump_distribution_function('dump_f/f') + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie.py new file mode 100644 index 00000000..d003e39a --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie.py @@ -0,0 +1,138 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +N_s = len(params.mass) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func_backgrouind = np.mean(dist_func) + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + print ((dist_func - dist_func_background).shape) + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q2_position, q1_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_debug.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_debug.py new file mode 100644 index 00000000..0b2c719d --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_debug.py @@ -0,0 +1,182 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(1): + for index_2 in range(N_q2): + + q1_position = index_1 + q2_position = index_2 + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = 1.#np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func - \ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..0dae45a6 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/momentum_space_movie_zero_T.py @@ -0,0 +1,183 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func_background = np.mean(dist_func) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/movie.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/movie.py new file mode 100644 index 00000000..e335f680 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/movie.py @@ -0,0 +1,169 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[::-1]): + + file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + #print (j_x.shape, vel_drift_x.shape, density.shape) + + pl.subplot(221) + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.colorbar() + + pl.subplot(222) + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + j_x, j_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.colorbar() + + pl.subplot(223) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_x - density*vel_drift_x).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + pl.subplot(224) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_y - density*vel_drift_y).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + #pl.tight_layout() + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/params.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/params.py new file mode 100644 index 00000000..bab1fba5 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/params.py @@ -0,0 +1,279 @@ +import numpy as np +import arrayfire as af + +from bolt.src.electronic_boltzmann.utils.polygon import polygon +from bolt.src.electronic_boltzmann.utils.unit_vectors import normal_to_hexagon_unit_vec + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +electrostatic_solver_every_nth_step = 1000000 + + +# Time parameters: +dt = 0.025/4 # ps +t_final = 25. # ps + + +# File-writing Parameters: +dump_steps = 5 +dump_dist_after = 1600 +# Set to zero for no file-writing +dt_dump_f = 1000*dt #ps +# ALWAYS set dump moments and dump fields at same frequency: +dt_dump_moments = dt_dump_fields = 5*dt #ps + + +# Dimensionality considered in velocity space: +p_dim = 2 +p_space_grid = 'cartesian' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py +#TODO : Use only polar2D for PdCoO2 + + +zero_temperature = (p_dim==1) +dispersion = 'linear' # 'linear' or 'quadratic' +fermi_surface_shape = 'circle' # Supports 'circle' or 'hexagon' + + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 6 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 0.0 # um +contact_end = 0.25 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 1e-3#12e-5 +initial_mu = 0.015 +vel_drift_x_in = 1e-4*fermi_velocity +vel_drift_x_out = 1e-4*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +phi = None # Electric potential in the plane of graphene sheet +p_x = None +p_y = None +#integral_measure = None + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + + +def fermi_momentum_magnitude(theta): + if (fermi_surface_shape == 'circle'): + p_f = initial_mu/fermi_velocity # Fermi momentum + + elif (fermi_surface_shape == 'hexagon'): + n = 6 # No. of sides of polygon + p_f = (initial_mu/fermi_velocity) * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + #TODO : If cartesian coordinates are being used, convert to polar to calculate p_f + else : + raise NotImplementedError('Unsupported shape of fermi surface') + return(p_f) + + +def band_energy(p1, p2): + # Note :This function is only meant to be called once to initialize E_band + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1 + theta = p2 + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + if (dispersion == 'linear'): + + E_upper = p*fermi_velocity + + elif (dispersion == 'quadratic'): + + m = effective_mass(p1, p2) + E_upper = p**2/(2.*m) + + if (zero_temperature): + + E_upper = initial_mu * p**0. + + af.eval(E_upper) + return(E_upper) + + +def effective_mass(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + + theta = af.atan(p_y/p_x) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + if (fermi_surface_shape == 'hexagon'): + + n = 6 # No. of side of polygon + mass = mass_particle * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + + elif (fermi_surface_shape == 'circle'): + + # For now, just return the free electron mass + mass = mass_particle + + return(mass) + +def band_velocity(p1, p2): + # Note :This function is only meant to be called once to initialize the vel vectors + + if (p_space_grid == 'cartesian'): + p_x_local = p1 + p_y_local = p2 + + theta = af.atan(p_y_local/p_x_local) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + if (fermi_surface_shape == 'circle'): + + v_f_hat = p_hat + + elif (fermi_surface_shape == 'hexagon'): + + v_f_hat = normal_to_hexagon_unit_vec(theta) + + # Quadratic dispersion + m = effective_mass(p1, p2) + v_f = p/m + + if (dispersion == 'linear' or zero_temperature): + + v_f = fermi_velocity + + upper_band_velocity = [v_f * v_f_hat[0], v_f * v_f_hat[1]] + + return(upper_band_velocity) + +def get_p_x_and_p_y(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + + if (zero_temperature): + # Get p_x and p_y at the Fermi surface + r = fermi_momentum_magnitude(theta) + + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + return([p_x, p_y]) + +# Restart(Set to zero for no-restart): +latest_restart = True +t_restart = 0 + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/petsc_conf.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/petsc_conf.py new file mode 100755 index 00000000..22781ed2 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/petsc_conf.py @@ -0,0 +1,73 @@ +import warnings + +def get_conf(): + """Parses various PETSc configuration/include files to get data types. + + precision, indices, complexscalars = get_conf() + + Output: + precision: 'single', 'double', 'longlong' indicates precision of PetscScalar + indices: '32', '64' indicates bit-size of PetscInt + complex: True/False indicates whether PetscScalar is complex or not. + """ + + import sys, os + precision = None + indices = None + complexscalars = None + + if 'PETSC_DIR' in os.environ: + petscdir = os.environ['PETSC_DIR'] + else: + warnings.warn('PETSC_DIR env not set - unable to locate PETSc installation, using defaults') + return None, None, None + + if os.path.isfile(os.path.join(petscdir,'lib','petsc','conf','petscrules')): + # found prefix install + petscvariables = os.path.join(petscdir,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,'include','petscconf.h') + else: + if 'PETSC_ARCH' in os.environ: + petscarch = os.environ['PETSC_ARCH'] + if os.path.isfile(os.path.join(petscdir,petscarch,'lib','petsc','conf','petscrules')): + # found legacy install + petscvariables = os.path.join(petscdir,petscarch,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,petscarch,'include','petscconf.h') + else: + warnings.warn('Unable to locate PETSc installation in specified PETSC_DIR/PETSC_ARCH, using defaults') + return None, None, None + else: + warnings.warn('PETSC_ARCH env not set or incorrect PETSC_DIR is given - unable to locate PETSc installation, using defaults') + return None, None, None + + try: + fid = open(petscvariables, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('PETSC_PRECISION'): + precision = line.strip().split('=')[1].strip('\n').strip() + + fid.close() + + try: + fid = open(petscconfinclude, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('#define PETSC_USE_64BIT_INDICES 1'): + indices = '64bit' + elif line.startswith('#define PETSC_USE_COMPLEX 1'): + complexscalars = True + + if indices is None: + indices = '32bit' + if complexscalars is None: + complexscalars = False + fid.close() + + return precision, indices, complexscalars diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/phase_vs_y.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/post.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/signals.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/signals.py new file mode 100644 index 00000000..979640c3 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/signals.py @@ -0,0 +1,166 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +#filepath = '/home/mchandra/gitansh/zero_T/example_problems/electronic_boltzmann/graphene/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC' +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + +# Calculate the phase difference between input_signal_array and sensor_normalized +# Code copied from : +# https:/stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves + +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] + +#Force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) + +#pl.plot(time_array, input_signal_array) +pl.plot(time_array, sensor_normalized) +#pl.axhline(0, color='black', linestyle='--') + +#pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=1) +#pl.text(135, 1.14, '$\phi : %.2f \; rad$' %phase_diff) +pl.xlabel(r'Time (ps)') +#pl.xlim([0, 200]) +#pl.ylim([-1.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 0.5$ ps') +pl.savefig('images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/test.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/test.py new file mode 100644 index 00000000..89e69811 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/test.py @@ -0,0 +1,138 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[:]): + + #file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + print (vel_drift_x) + print (j_x, density) + print (j_x/density) + + + pl.subplot(121) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_x - density*vel_drift_x).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + pl.subplot(122) + pl.contourf(q1_meshgrid, q2_meshgrid, (j_y - density*vel_drift_y).T, 100, cmap='bwr') + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.colorbar() + + pl.tight_layout() + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/test_compute_moments_cartesian/vorticity.py b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/test_compute_moments_cartesian/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() + From e304093f5c94bb0acac8e9f93144daaddfde318e Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Thu, 23 Apr 2020 18:03:39 -0400 Subject: [PATCH 57/58] Bug fix in params --- .../pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py index cdbd2eea..288d9f64 100644 --- a/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py +++ b/example_problems/electronic_boltzmann/pdcoo2/L_1.0_1.25_tau_ee_inf_tau_eph_inf_DC/params.py @@ -40,7 +40,7 @@ # Time parameters: dt = 0.025/4 # ps -t_final = 20. # ps +t_final = 25. # ps # File-writing Parameters: @@ -218,7 +218,7 @@ def band_velocity(p1, p2): p = af.sqrt(p_x**2. + p_y**2.) p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] - if (fermi_surface_shape == 'circular'): + if (fermi_surface_shape == 'circle'): v_f_hat = p_hat From 69f64245e2bc6b4beff79239fc9c43e9baba4d6b Mon Sep 17 00:00:00 2001 From: gitansh95 Date: Tue, 1 Sep 2020 13:38:39 -0400 Subject: [PATCH 58/58] Reference folder for PdCoO2 height scaling runs. --- bolt/lib/nonlinear/file_io/dump.py | 4 + bolt/lib/nonlinear/nonlinear_solver.py | 2 +- bolt/src/electronic_boltzmann/moments.py | 14 +- .../pdcoo2/ref_rotated/PetscBinaryIO.py | 479 ++++++++++++++++++ .../pdcoo2/ref_rotated/boundary_conditions.py | 107 ++++ .../pdcoo2/ref_rotated/check.py | 42 ++ .../pdcoo2/ref_rotated/cleanup.py | 29 ++ .../pdcoo2/ref_rotated/domain.py | 66 +++ .../pdcoo2/ref_rotated/edge_density.py | 122 +++++ .../pdcoo2/ref_rotated/edge_potential.py | 113 +++++ .../pdcoo2/ref_rotated/enstrophy.py | 142 ++++++ .../pdcoo2/ref_rotated/fire_job_batch.py | 47 ++ .../pdcoo2/ref_rotated/initialize.py | 99 ++++ .../pdcoo2/ref_rotated/job_script | 4 + .../pdcoo2/ref_rotated/main.py | 172 +++++++ .../ref_rotated/momentum_space_movie.py | 134 +++++ .../ref_rotated/momentum_space_movie_debug.py | 182 +++++++ .../momentum_space_movie_zero_T.py | 193 +++++++ .../pdcoo2/ref_rotated/movie.py | 147 ++++++ .../pdcoo2/ref_rotated/movie_overplot.py | 160 ++++++ .../pdcoo2/ref_rotated/params.py | 279 ++++++++++ .../pdcoo2/ref_rotated/petsc_conf.py | 73 +++ .../pdcoo2/ref_rotated/phase_vs_y.py | 180 +++++++ .../pdcoo2/ref_rotated/post.py | 422 +++++++++++++++ .../pdcoo2/ref_rotated/signals.py | 123 +++++ .../pdcoo2/ref_rotated/time_series.py | 140 +++++ .../pdcoo2/ref_rotated/vorticity.py | 136 +++++ 27 files changed, 3607 insertions(+), 4 deletions(-) create mode 100755 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/PetscBinaryIO.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/boundary_conditions.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/check.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/cleanup.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/domain.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_density.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_potential.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/enstrophy.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/fire_job_batch.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/initialize.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/job_script create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/main.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_debug.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_zero_T.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie_overplot.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/params.py create mode 100755 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/petsc_conf.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/phase_vs_y.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/post.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/signals.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/time_series.py create mode 100644 example_problems/electronic_boltzmann/pdcoo2/ref_rotated/vorticity.py diff --git a/bolt/lib/nonlinear/file_io/dump.py b/bolt/lib/nonlinear/file_io/dump.py index a1981bd2..9caa7a41 100644 --- a/bolt/lib/nonlinear/file_io/dump.py +++ b/bolt/lib/nonlinear/file_io/dump.py @@ -103,6 +103,10 @@ def dump_moments(self, file_name): attributes.remove('integral_over_p') if('params' in attributes): attributes.remove('params') + if('af' in attributes): + attributes.remove('af') + for i in range(len(attributes)): + print("i = ", i, attributes[i]) for i in range(len(attributes)): #print("i = ", i, attributes[i]) diff --git a/bolt/lib/nonlinear/nonlinear_solver.py b/bolt/lib/nonlinear/nonlinear_solver.py index 38b8dafe..123a3de3 100644 --- a/bolt/lib/nonlinear/nonlinear_solver.py +++ b/bolt/lib/nonlinear/nonlinear_solver.py @@ -289,7 +289,7 @@ def __init__(self, physical_system, performance_test_flag = False): self._da_dump_moments = PETSc.DMDA().create([self.N_q1, self.N_q2], dof = self.N_species - * (len(attributes)-2), # don't countintegral_over_p, and params in moments.py + * (len(attributes)-3), # don't count af, integral_over_p, and params in moments.py proc_sizes = (nproc_in_q1, nproc_in_q2 ), diff --git a/bolt/src/electronic_boltzmann/moments.py b/bolt/src/electronic_boltzmann/moments.py index 352393e7..42cf0a32 100644 --- a/bolt/src/electronic_boltzmann/moments.py +++ b/bolt/src/electronic_boltzmann/moments.py @@ -1,15 +1,23 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import arrayfire as af + from bolt.src.utils.integral_over_p import integral_over_p import params def density(f, p1, p2, p3, integral_measure): - return(integral_over_p(f, integral_measure)) + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + return(integral_over_p(f+p_f/2, integral_measure)) def j_x(f, p1, p2, p3, integral_measure): - return(integral_over_p(f * params.p_x, integral_measure)) + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + return(integral_over_p(f * params.fermi_velocity * params.p_x/p_f, integral_measure)) def j_y(f, p1, p2, p3, integral_measure): - return(integral_over_p(f * params.p_y, integral_measure)) + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + return(integral_over_p(f * params.fermi_velocity * params.p_y/p_f, integral_measure)) diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/PetscBinaryIO.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/PetscBinaryIO.py new file mode 100755 index 00000000..fd0e48e9 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/PetscBinaryIO.py @@ -0,0 +1,479 @@ +"""PetscBinaryIO +=============== + +Provides + 1. PETSc-named objects Vec, Mat, and IS that inherit numpy.ndarray + 2. A class to read and write these objects from PETSc binary files. + +The standard usage of this module should look like: + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> objects = io.readBinaryFile('file.dat') + +or + + >>> import PetscBinaryIO + >>> import numpy + >>> vec = numpy.array([1., 2., 3.]).view(PetscBinaryIO.Vec) + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> io.writeBinaryFile('file.dat', [vec,]) + +to read in objects one at a time use such as + + >>> import PetscBinaryIO + >>> io = PetscBinaryIO.PetscBinaryIO() + >>> fh = open('file.dat') + >>> objecttype = io.readObjectType(fh) + >>> if objecttype == 'Vec': + >>> v = io.readVec(fh) + + Note that one must read in the object type first and then call readVec(), readMat() etc. + + +See also PetscBinaryIO.__doc__ and methods therein. +""" + +import numpy as np +import functools + +try: + basestring # Python-2 has basestring as a common parent of unicode and str +except NameError: + basestring = str # Python-3 is unicode through and through + +def update_wrapper_with_doc(wrapper, wrapped): + """Similar to functools.update_wrapper, but also gets the wrapper's __doc__ string""" + wdoc = wrapper.__doc__ + + functools.update_wrapper(wrapper, wrapped) + if wdoc is not None: + if wrapper.__doc__ is None: + wrapper.__doc__ = wdoc + else: + wrapper.__doc__ = wrapper.__doc__ + wdoc + return wrapper + +def wraps_with_doc(wrapped): + """Similar to functools.wraps, but also gets the wrapper's __doc__ string""" + return functools.partial(update_wrapper_with_doc, wrapped=wrapped) + +def decorate_with_conf(f): + """Decorates methods to take kwargs for precisions.""" + @wraps_with_doc(f) + def decorated_f(self, *args, **kwargs): + """ + Additional kwargs: + precision: 'single', 'double', 'longlong' for scalars + indices: '32bit', '64bit' integer size + complexscalars: True/False + + Note these are set in order of preference: + 1. kwargs if given here + 2. PetscBinaryIO class __init__ arguments + 3. PETSC_DIR/PETSC_ARCH defaults + """ + + changed = False + old_precision = self.precision + old_indices = self.indices + old_complexscalars = self.complexscalars + + try: + self.precision = kwargs.pop('precision') + except KeyError: + pass + else: + changed = True + + try: + self.indices = kwargs.pop('indices') + except KeyError: + pass + else: + changed = True + + try: + self.complexscalars = kwargs.pop('complexscalars') + except KeyError: + pass + else: + changed = True + + if changed: + self._update_dtypes() + + result = f(self, *args, **kwargs) + + if changed: + self.precision = old_precision + self.indices = old_indices + self.complexscalars = old_complexscalars + self._update_dtypes() + + return result + return decorated_f + + +class DoneWithFile(Exception): pass + + +class Vec(np.ndarray): + """Vec represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + vec = numpy.array([1,2,3]).view(Vec) + """ + _classid = 1211214 + + +class MatDense(np.matrix): + """Mat represented as 2D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy view method: + + mat = numpy.array([[1,0],[0,1]]).view(Mat) + """ + _classid = 1211216 + + +class MatSparse(tuple): + """Mat represented as CSR tuple ((M, N), (rowindices, col, val)) + + This should be instantiated from a tuple: + + mat = MatSparse( ((M,N), (rowindices,col,val)) ) + """ + _classid = 1211216 + def __repr__(self): + return 'MatSparse: %s'%super(MatSparse, self).__repr__() + + +class IS(np.ndarray): + """IS represented as 1D numpy array + + The best way to instantiate this class for use with writeBinaryFile() + is through the numpy "view" method: + + an_is = numpy.array([3,4,5]).view(IS) + """ + _classid = 1211218 + + +class PetscBinaryIO(object): + """Reader/Writer class for PETSc binary files. + + Note that by default, precisions for both scalars and indices, as well as + complex scalars, are picked up from the PETSC_DIR/PETSC_ARCH configuration + as set by environmental variables. + + Alternatively, defaults can be overridden at class instantiation, or for + a given method call. + """ + + _classid = {1211216:'Mat', + 1211214:'Vec', + 1211218:'IS', + 1211219:'Bag'} + + def __init__(self, precision=None, indices=None, complexscalars=None): + if (precision is None) or (indices is None) or (complexscalars is None): + import petsc_conf + defaultprecision, defaultindices, defaultcomplexscalars = petsc_conf.get_conf() + if precision is None: + if defaultprecision is None: + precision = 'double' + else: + precision = defaultprecision + + if indices is None: + if defaultindices is None: + indices = '32bit' + else: + indices = defaultindices + + if complexscalars is None: + if defaultcomplexscalars is None: + complexscalars = False + else: + complexscalars = defaultcomplexscalars + + self.precision = precision + self.indices = indices + self.complexscalars = complexscalars + self._update_dtypes() + + def _update_dtypes(self): + if self.indices == '64bit': + self._inttype = np.dtype('>i8') + else: + self._inttype = np.dtype('>i4') + + if self.precision == 'longlong': + nbyte = 16 + elif self.precision == 'single': + nbyte = 4 + else: + nbyte = 8 + + if self.complexscalars: + name = 'c' + nbyte = nbyte * 2 # complex scalar takes twice as many bytes + else: + name = 'f' + + self._scalartype = '>{0}{1}'.format(name, nbyte) + + @decorate_with_conf + def readVec(self, fh): + """Reads a PETSc Vec from a binary file handle, must be called after readObjectType().""" + + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + try: + vals = np.fromfile(fh, dtype=self._scalartype, count=nz) + except MemoryError: + raise IOError('Inconsistent or invalid Vec data in file') + if (len(vals) is 0): + raise IOError('Inconsistent or invalid Vec data in file') + return vals.view(Vec) + + @decorate_with_conf + def writeVec(self, fh, vec): + """Writes a PETSc Vec to a binary file handle.""" + + metadata = np.array([Vec._classid, len(vec)], dtype=self._inttype) + metadata.tofile(fh) + vec.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatSparse(self, fh): + """Reads a PETSc Mat, returning a sparse representation of the data. Must be called after readObjectType() + + (M,N), (I,J,V) = readMatSparse(fid) + + Input: + fid : file handle to open binary file. + Output: + M,N : matrix size + I,J : arrays of row and column for each nonzero + V: nonzero value + """ + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + return MatSparse(((M, N), (I, J, V))) + + @decorate_with_conf + def writeMatSparse(self, fh, mat): + """Writes a Mat into a PETSc binary file handle""" + + ((M,N), (I,J,V)) = mat + metadata = np.array([MatSparse._classid,M,N,I[-1]], dtype=self._inttype) + rownz = I[1:] - I[:-1] + + assert len(J.shape) == len(V.shape) == len(I.shape) == 1 + assert len(J) == len(V) == I[-1] == rownz.sum() + assert (rownz > -1).all() + + metadata.tofile(fh) + rownz.astype(self._inttype).tofile(fh) + J.astype(self._inttype).tofile(fh) + V.astype(self._scalartype).tofile(fh) + return + + @decorate_with_conf + def readMatDense(self, fh): + """Reads a PETSc Mat, returning a dense represention of the data, must be called after readObjectType()""" + + try: + M,N,nz = np.fromfile(fh, dtype=self._inttype, count=3) + I = np.empty(M+1, dtype=self._inttype) + I[0] = 0 + rownz = np.fromfile(fh, dtype=self._inttype, count=M) + np.cumsum(rownz, out=I[1:]) + assert I[-1] == nz + + J = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(J) == nz + V = np.fromfile(fh, dtype=self._scalartype, count=nz) + assert len(V) == nz + + except (AssertionError, MemoryError, IndexError): + raise IOError('Inconsistent or invalid Mat data in file') + + mat = np.zeros((M,N), dtype=self._scalartype) + for row in range(M): + rstart, rend = I[row:row+2] + mat[row, J[rstart:rend]] = V[rstart:rend] + return mat.view(MatDense) + + @decorate_with_conf + def readMatSciPy(self, fh): + from scipy.sparse import csr_matrix + (M, N), (I, J, V) = self.readMatSparse(fh) + return csr_matrix((V, J, I), shape=(M, N)) + + @decorate_with_conf + def writeMatSciPy(self, fh, mat): + from scipy.sparse import csr_matrix + if hasattr(mat, 'tocsr'): + mat = mat.tocsr() + assert isinstance(mat, csr_matrix) + V = mat.data + M,N = mat.shape + J = mat.indices + I = mat.indptr + return self.writeMatSparse(fh, (mat.shape, (mat.indptr,mat.indices,mat.data))) + + @decorate_with_conf + def readMat(self, fh, mattype='sparse'): + """Reads a PETSc Mat from binary file handle, must be called after readObjectType() + + optional mattype: 'sparse" or 'dense' + + See also: readMatSparse, readMatDense + """ + + if mattype == 'sparse': + return self.readMatSparse(fh) + elif mattype == 'dense': + return self.readMatDense(fh) + elif mattype == 'scipy.sparse': + return self.readMatSciPy(fh) + else: + raise RuntimeError('Invalid matrix type requested: choose sparse/dense/scipy.sparse') + + @decorate_with_conf + def readIS(self, fh): + """Reads a PETSc Index Set from binary file handle, must be called after readObjectType()""" + + try: + nz = np.fromfile(fh, dtype=self._inttype, count=1)[0] + v = np.fromfile(fh, dtype=self._inttype, count=nz) + assert len(v) == nz + except (MemoryError,IndexError): + raise IOError('Inconsistent or invalid IS data in file') + return v.view(IS) + + @decorate_with_conf + def writeIS(self, fh, anis): + """Writes a PETSc IS to binary file handle.""" + + metadata = np.array([IS._classid, len(anis)], dtype=self._inttype) + metadata.tofile(fh) + anis.astype(self._inttype).tofile(fh) + return + + @decorate_with_conf + def readObjectType(self, fid): + """Returns the next object type as a string in the file""" + try: + header = np.fromfile(fid, dtype=self._inttype, count=1)[0] + except (MemoryError, IndexError): + raise DoneWithFile + try: + objecttype = self._classid[header] + except KeyError: + raise IOError('Invalid PetscObject CLASSID or object not implemented for python') + return objecttype + + @decorate_with_conf + def readBinaryFile(self, fid, mattype='sparse'): + """Reads a PETSc binary file, returning a tuple of the contained objects. + + objects = self.readBinaryFile(fid, **kwargs) + + Input: + fid : either file name or handle to an open binary file. + + Output: + objects : tuple of objects representing the data in numpy arrays. + + Optional: + mattype : + 'sparse': Return matrices as raw CSR: (M, N), (row, col, val). + 'dense': Return matrices as MxN numpy arrays. + 'scipy.sparse': Return matrices as scipy.sparse objects. + """ + + close = False + + if isinstance(fid, basestring): + fid = open(fid, 'rb') + close = True + + objects = [] + try: + while True: + objecttype = self.readObjectType(fid) + + if objecttype == 'Vec': + objects.append(self.readVec(fid)) + elif objecttype == 'IS': + objects.append(self.readIS(fid)) + elif objecttype == 'Mat': + objects.append(self.readMat(fid,mattype)) + elif objecttype == 'Bag': + raise NotImplementedError('Bag Reader not yet implemented') + except DoneWithFile: + pass + finally: + if close: + fid.close() + + return tuple(objects) + + @decorate_with_conf + def writeBinaryFile(self, fid, objects): + """Writes a PETSc binary file containing the objects given. + + readBinaryFile(fid, objects) + + Input: + fid : either file handle to an open binary file, or filename. + objects : list of objects representing the data in numpy arrays, + which must be of type Vec, IS, MatSparse, or MatSciPy. + """ + close = False + if isinstance(fid, basestring): + fid = open(fid, 'wb') + close = True + + for petscobj in objects: + if (isinstance(petscobj, Vec)): + self.writeVec(fid, petscobj) + elif (isinstance(petscobj, IS)): + self.writeIS(fid, petscobj) + elif (isinstance(petscobj, MatSparse)): + self.writeMatSparse(fid, petscobj) + elif (isinstance(petscobj, MatDense)): + if close: + fid.close() + raise NotImplementedError('Writing a dense matrix is not yet supported') + else: + try: + self.writeMatSciPy(fid, petscobj) + except AssertionError: + if close: + fid.close() + raise TypeError('Object %s is not a valid PETSc object'%(petscobj.__repr__())) + if close: + fid.close() + return diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/boundary_conditions.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/boundary_conditions.py new file mode 100644 index 00000000..ce33f043 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/boundary_conditions.py @@ -0,0 +1,107 @@ +import numpy as np +import arrayfire as af +import domain + +in_q1_left = 'mirror' +in_q1_right = 'mirror' +in_q2_bottom = 'mirror+dirichlet' +in_q2_top = 'mirror+dirichlet' + +@af.broadcast +def f_top(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_y_in = -params.vel_drift_x_in + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + + fermi_dirac_in = (1./(af.exp( (E_upper - vel_drift_y_in*p_y - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q1_contact_start = params.contact_start + q1_contact_end = params.contact_end + + cond = ((q1 >= q1_contact_start) & \ + (q1 <= q1_contact_end) \ + ) + + f_left = cond*fermi_dirac_in + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + vel_drift_x_out = -params.vel_drift_x_in * np.sin(omega*t) + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_x_out*p_x - mu)/(k*T) ) + 1.) + ) + + # TODO: set these parameters in params.py + cond_in = ((q2 >= 3.5) & (q2 <= 4.5)) + cond_out = ((q2 >= 5.5) & (q2 <= 6.5)) + + f_left = cond_in*fermi_dirac_in + cond_out*fermi_dirac_out \ + + (1 - cond_in)*(1 - cond_out)*f + + af.eval(f_left) + return(f_left) + +@af.broadcast +def f_bottom(f, t, q1, q2, p1, p2, p3, params): + + k = params.boltzmann_constant + E_upper = params.E_band + T = params.initial_temperature + mu = params.initial_mu + + t = params.current_time + omega = 2. * np.pi * params.AC_freq + vel_drift_y_out = -params.vel_drift_x_out + + if (params.p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (params.p_space_grid == 'polar2D'): + p_x = p1 * af.cos(p2) + p_y = p1 * af.sin(p2) + else: + raise NotImplementedError('Unsupported coordinate system in p_space') + + fermi_dirac_out = (1./(af.exp( (E_upper - vel_drift_y_out*p_y - mu)/(k*T) ) + 1.) + ) + + if (params.contact_geometry=="straight"): + # Contacts on either side of the device + + q1_contact_start = params.contact_start + q1_contact_end = params.contact_end + + cond = ((q1 >= q1_contact_start) & \ + (q1 <= q1_contact_end) \ + ) + + f_right = cond*fermi_dirac_out + (1 - cond)*f + + elif (params.contact_geometry=="turn_around"): + # Contacts on the same side of the device + + f_right = f + + af.eval(f_right) + return(f_right) diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/check.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/check.py new file mode 100644 index 00000000..71fe46ef --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/check.py @@ -0,0 +1,42 @@ +import numpy as np +import params +import arrayfire as af +import pylab as pl + +import domain + +from bolt.src.electronic_boltzmann.utils.polygon import polygon + +p2_start = -np.pi +p2_end = np.pi +N_p2 = domain.N_p2 +theta = \ + p2_start + (0.5 + np.arange(N_p2))*(p2_end - p2_start)/N_p2 + +theta = af.from_ndarray(theta) + +hexa = polygon(6, theta, rotation = np.pi/6) +hexa = hexa.to_ndarray() + +#pl.polar(theta, hexa) + +#pl.plot(theta, hexa * np.cos(theta)) +#pl.plot(theta, hexa * np.sin(theta)) + +pl.gca().set_aspect(1) +pl.plot(hexa*np.cos(theta), hexa*np.sin(theta)) + +#p_hat_0_old = np.loadtxt("P_hat_0_old.txt") +#p_hat_1_old = np.loadtxt("P_hat_1_old.txt") + +#p_hat_0 = np.loadtxt("P_hat_0.txt") +#p_hat_1 = np.loadtxt("P_hat_1.txt") + +#pl.plot(theta, p_hat_0_old) +#pl.plot(theta, p_hat_1_old) + +#pl.plot(theta, p_hat_0, '--') +#pl.plot(theta, p_hat_1, '--') + + +pl.savefig("images/test.png") diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/cleanup.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/cleanup.py new file mode 100644 index 00000000..21ce5c08 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/cleanup.py @@ -0,0 +1,29 @@ +import os +import numpy as np +import glob + +# TODO : Set t_final and number of gpus in jobscript depending on device size +start_index = 3.00 +end_index = 3.5001 +step = 0.1 + + +for index in np.arange(start_index, end_index, step): + print (index) + filepath = \ + '/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/pdcoo2/L_1.0_%.2f_tau_ee_inf_tau_eph_inf_DC_rotated'%index + + # List all dump_f files + dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + dist_func_info_files = np.sort(glob.glob(filepath+'/dump_f/*.bin.info')) + + # Save first and last files + os.system("mkdir " + filepath + "/dump_f/save") + os.system("mv " + str(dist_func_files[0]) + " " + filepath+"/dump_f/save/.") + os.system("mv " + str(dist_func_files[-1]) + " " + filepath+"/dump_f/save/.") + os.system("mv " + str(dist_func_info_files[0]) + " " + filepath+"/dump_f/save/.") + os.system("mv " + str(dist_func_info_files[-1]) + " " + filepath+"/dump_f/save/.") + os.system("rm " + filepath + "/dump_f/t*") + + # Remove all files in dump_f except first and last dist funcs + #os.system("rm " + filepath+"/output.txt") diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/domain.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/domain.py new file mode 100644 index 00000000..857e1bfe --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/domain.py @@ -0,0 +1,66 @@ +import numpy as np +import params + +q2_start = 0. +q2_end = 1.0 +N_q2 = 40 + +q1_start = 0. +N_q1 = int(N_q2*q1_end/q2_end) + +# If N_p1 > 1, mirror boundary conditions require p1 to be +# symmetric about zero +# TODO : Check and fix discrepancy between this and the claim +# that p1_center = mu in polar representation +N_p1 = 1 # Set equal to 1 for 1D polar + +# In the cartesian representation of momentum space, +# p1 = p_x (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is 0 + +# Uncomment the following for the cartesian representation of momentum space +#p1_start = [-0.04] +#p1_end = [0.04] + + +# In the 2D polar representation of momentum space, +# p1 = p_r (magnitude of momentum) +# p1_start and p1_end are set such that p1_center is mu + +# Uncomment the following for the 2D polar representation of momentum space +#p1_start = [params.initial_mu - \ +# 16.*params.boltzmann_constant*params.initial_temperature] +#p1_end = [params.initial_mu + \ +# 16.*params.boltzmann_constant*params.initial_temperature] + +# Uncomment the following for the 1D polar representation of momentum space +p1_start = [0.5*params.initial_mu/params.fermi_velocity] +p1_end = [1.5*params.initial_mu/params.fermi_velocity] + + +# If N_p2 > 1, mirror boundary conditions require p2 to be +# symmetric about zero +N_p2 = 2048 + +# In the cartesian representation of momentum space, +# p2 = p_y (magnitude of momentum) +# p2_start and p2_end are set such that p2_center is 0 +#p2_start = [-0.04] +#p2_end = [0.04] + +# In the 2D polar representation of momentum space, +# p2 = p_theta (angle of momentum) +# N_p_theta MUST be even. +#p2_start = [-np.pi] +#p2_end = [np.pi] +p2_start = [-3.14159265359] +p2_end = [3.14159265359] + +# If N_p3 > 1, mirror boundary conditions require p3 to be +# symmetric about zero + +p3_start = [-0.5] +p3_end = [0.5] +N_p3 = 1 + +N_ghost = 2 diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_density.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_density.py new file mode 100644 index 00000000..3697590e --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_density.py @@ -0,0 +1,122 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() +import os + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +import PetscBinaryIO + +import domain +import boundary_conditions +import params +import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + moments = io.readBinaryFile(dump_file) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + + source = np.mean(density[source_indices, 0]) + drain = np.mean(density[drain_indices, -1]) + + sensor_1_left = np.mean(density[0, 0]) + sensor_1_right = np.mean(density[0, -1]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) + +input_normalized = \ + input_signal_array/np.max(np.abs(input_signal_array[half_time:])) +sensor_normalized = \ + sensor_1_signal_array#/np.max(np.abs(sensor_1_signal_array[half_time:])) + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_potential.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_potential.py new file mode 100644 index 00000000..c32ff136 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/edge_potential.py @@ -0,0 +1,113 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + + +import domain +import boundary_conditions +import params +import initialize + +import PetscBinaryIO +io = PetscBinaryIO.PetscBinaryIO() + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 0.25 # um +sensor_1_left_end = 5.0 # um + +sensor_1_right_start = 0.25 # um +sensor_1_right_end = 5.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +dt = params.dt +dump_interval = params.dump_steps + + +file_number = -1 +print("file number = ", file_number, "of ", moment_files.size) + +moments = io.readBinaryFile(moment_files[file_number]) +moments = moments[0].reshape(N_q2, N_q1, 3) + +density = moments[:, :, 0] +j_x = moments[:, :, 1] +j_y = moments[:, :, 2] + +density = density - np.mean(density) + +left_edge = 0 +pl.plot(q2[sensor_1_left_indices], density[sensor_1_left_indices, left_edge]) + +pl.ylabel('$\delta$n') +pl.xlabel('y ($\mu$m)') + +pl.savefig("images/iv.png") + + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/enstrophy.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/enstrophy.py new file mode 100644 index 00000000..aeab5a28 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/enstrophy.py @@ -0,0 +1,142 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +kinetic_energy_array = [] +enstrophy_array = [] +print("Reading kinetic energy and enstrophy signals...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + kinetic_energy = 0.5 * np.sum(vel_drift_x**2 + vel_drift_y**2) * dq1 * dq2 + kinetic_energy_array.append(kinetic_energy) + + enstrophy = np.sum(vorticity**2) * dq1 * dq2 + enstrophy_array.append(enstrophy) + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +kinetic_energy_normalized = \ + kinetic_energy_array/np.max(np.abs(kinetic_energy_array[half_time:])) +enstrophy_normalized = \ + enstrophy_array/np.max(np.abs(enstrophy_array[half_time:])) + + +pl.plot(time_array, kinetic_energy_normalized) +pl.plot(time_array, enstrophy_normalized) +pl.axhline(0, color='black', linestyle='--') + +pl.legend(['Kinetic Energy', 'Enstrophy'], loc=1) +pl.xlabel(r'Time (ps)') +pl.xlim([0, 200]) +pl.ylim([-0.1, 1.1]) + +pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') +pl.savefig('vorticity_images/iv' + '.png') +pl.clf() + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/fire_job_batch.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/fire_job_batch.py new file mode 100644 index 00000000..44d81a4d --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/fire_job_batch.py @@ -0,0 +1,47 @@ +import os +import numpy as np + +# TODO : Set t_final and number of gpus in jobscript depending on device size +start_index = 1.50 + 0.025 +end_index = 1.5751 +step = 0.05 + +current_filepath = \ + '/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/pdcoo2/ref_rotated' +source_filepath = \ + '/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/pdcoo2/ref_rotated' + +for index in np.arange(start_index, end_index, step): + filepath = \ + '/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/pdcoo2/L_1.0_%.3f_tau_ee_inf_tau_eph_inf_DC_rotated'%index + + # If folder does not exist, make one and add all files from source folder + + if not os.path.isdir(filepath): + os.mkdir(filepath) + os.mkdir(filepath+"/dump_f") + os.mkdir(filepath+"/dump_moments") + os.mkdir(filepath+"/dump_lagrange_multipliers") + os.mkdir(filepath+"/images") + + os.system("cp " + source_filepath + "/* " + filepath+"/.") + + # Change required files + # Code copied from here : + # https://stackoverflow.com/questions/4454298/prepend-a-line-to-an-existing-file-in-python + + f = open(filepath + "/domain.py", "r") + old = f.read() # read everything in the file + f.close() + + f = open(filepath + "/domain.py", "w") + f.write("q1_end = " + str(index) + " \n") + f.write(old) + f.close() + + # Schedule job after changing to run directory so that generated slurm file + # is stored in that directory + os.chdir(filepath) + os.system("sbatch job_script") + os.chdir(current_filepath) # Return to job firing script's directory + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/initialize.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/initialize.py new file mode 100644 index 00000000..c2ee7948 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/initialize.py @@ -0,0 +1,99 @@ +""" +Functions which are used in assigning the I.C's to +the system. +""" + +import arrayfire as af +import numpy as np +from petsc4py import PETSc + +import domain + +def initialize_f(q1, q2, p1, p2, p3, params): + + PETSc.Sys.Print("Initializing f") + k = params.boltzmann_constant + + params.mu = 0.*q1 + params.initial_mu + params.T = 0.*q1 + params.initial_temperature + params.vel_drift_x = 0.*q1 + params.vel_drift_y = 0.*q1 + + params.mu_ee = params.mu.copy() + params.T_ee = params.T.copy() + params.vel_drift_x = 0.*q1 + 0e-3 + params.vel_drift_y = 0.*q1 + 0e-3 + + params.p_x, params.p_y = params.get_p_x_and_p_y(p1, p2) + params.E_band = params.band_energy(p1, p2) + params.vel_band = params.band_velocity(p1, p2) + + # Evaluating velocity space resolution for each species: + dp1 = []; dp2 = []; dp3 = [] + N_p1 = domain.N_p1; N_p2 = domain.N_p2; N_p3 = domain.N_p3 + p1_start = domain.p1_start; p1_end = domain.p1_end + p2_start = domain.p2_start; p2_end = domain.p2_end + p3_start = domain.p3_start; p3_end = domain.p3_end + + N_species = len(params.mass) + for i in range(N_species): + dp1.append((p1_end[i] - p1_start[i]) / N_p1) + dp2.append((p2_end[i] - p2_start[i]) / N_p2) + dp3.append((p3_end[i] - p3_start[i]) / N_p3) + + + theta = af.atan(params.p_y / params.p_x) + p_f = params.fermi_momentum_magnitude(theta) + + if (params.p_space_grid == 'cartesian'): + dp_x = dp1[0]; dp_y = dp2[0]; dp_z = dp3[0] + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * dp_z * dp_y * dp_x + + elif (params.p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + # Integral : \int delta(r - r_F) F(r, theta) r dr dtheta + r = p1; theta = p2 + dp_r = dp1[0]; dp_theta = dp2[0] + + if (params.zero_temperature): + # Assumption : F(r, theta) = delta(r-r_F)*F(theta) + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * p_f * dp_theta + + else: + params.integral_measure = \ + (4./(2.*np.pi*params.h_bar)**2) * r * dp_r * dp_theta + + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + + + f = (1./(af.exp( (params.E_band - params.vel_drift_x*params.p_x + - params.vel_drift_y*params.p_y + - params.mu + )/(k*params.T) + ) + 1. + )) + + af.eval(f) + return(f) + + +def initialize_E(q1, q2, params): + + E1 = 0.*q1 + E2 = 0.*q1 + E3 = 0.*q1 + + return(E1, E2, E3) + +def initialize_B(q1, q2, params): + + B1 = 0.*q1 + B2 = 0.*q1 + B3 = 0.*q1 + + return(B1, B2, B3) diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/job_script b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/job_script new file mode 100644 index 00000000..374fd6c1 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/job_script @@ -0,0 +1,4 @@ +#!/bin/bash +#SBATCH -p gpu -n 2 --gres=gpu:2 -c1 --hint=nomultithread -t 2-00:00 +# (Note: use one MPI process per gpu, update both gres and -n together; max 6) +export PYTHONPATH=/home/mchandra/gitansh/bolt_master; time mpirun python main.py > output.txt diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/main.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/main.py new file mode 100644 index 00000000..09596215 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/main.py @@ -0,0 +1,172 @@ +import os +import arrayfire as af +import numpy as np +import math +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +from mpi4py import MPI +MPI.WTIME_IS_GLOBAL=True + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear.nonlinear_solver \ + import nonlinear_solver +#from bolt.lib.nonlinear.fields.fields.fields \ +# import fields_solver.compute_electrostatic_fields +from bolt.lib.utils.restart_latest import latest_output, format_time + +import domain +import boundary_conditions +import initialize +import params + +import bolt.src.electronic_boltzmann.advection_terms \ + as advection_terms +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator +import bolt.src.electronic_boltzmann.moments \ + as moments + + +# Create required folders if they do not exist already +#if not os.path.isdir("dump_f"): +# os.system("mkdir dump_f") +#if not os.path.isdir("dump_moments"): +# os.system("mkdir dump_moments") +#if not os.path.isdir("dump_lagrange_multipliers"): +# os.system("mkdir dump_lagrange_multipliers") +#if not os.path.isdir("images"): +# os.system("mkdir images") + + +# Defining the physical system to be solved: +system = physical_system(domain, + boundary_conditions, + params, + initialize, + advection_terms, + collision_operator.RTA, + moments + ) + +# Declaring a nonlinear system object which will evolve the defined physical system: +nls = nonlinear_solver(system) +N_g = domain.N_ghost +params.rank = nls._comm.rank + +# Time parameters: +dt = params.dt +t_final = params.t_final +params.current_time = time_elapsed = 0.0 +params.time_step = time_step = 0 +dump_counter = 0 +dump_time_array = [] + + +using_latest_restart = False +if(params.latest_restart == True): + latest_f, time_elapsed = latest_output('') + print(time_elapsed) + if(latest_f is not None and time_elapsed is not None): + nls.load_distribution_function(latest_f) + dump_time_array = np.loadtxt("dump_time_array.txt").tolist() + using_latest_restart = True + + +if using_latest_restart == False: + if(params.t_restart == 0 or params.latest_restart == True): + time_elapsed = 0 + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y + ], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + dump_time_array.append(time_elapsed) + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + else: + time_elapsed = params.t_restart + formatted_time = format_time(time_elapsed) + nls.load_distribution_function('dump_f/t=' + formatted_time) + +# Checking that the file writing intervals are greater than dt: +assert(params.dt_dump_f >= dt) +assert(params.dt_dump_moments >= dt) +assert(params.dt_dump_fields >= dt) + + +#if (params.restart): +# nls.load_distribution_function(params.restart_file) + +density = nls.compute_moments('density') +print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "i\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + +nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) +while(time_elapsed < t_final): + + # Refine to machine error + if (time_step==0): + params.collision_nonlinear_iters = 10 + else: + params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters + + dump_steps = params.dump_steps + + if(params.dt_dump_moments != 0): + # We step by delta_dt to get the values at dt_dump + delta_dt = (1 - math.modf(time_elapsed/params.dt_dump_moments)[0]) \ + * params.dt_dump_moments + + if((delta_dt-dt)<1e-5): + nls.strang_timestep(delta_dt) + time_elapsed += delta_dt + formatted_time = format_time(time_elapsed) + nls.dump_moments('dump_moments/t=' + formatted_time) + nls.dump_aux_arrays([params.mu, + params.mu_ee, + params.T_ee, + params.vel_drift_x, params.vel_drift_y + ], + 'lagrange_multipliers', + 'dump_lagrange_multipliers/t=' + formatted_time + ) + dump_time_array.append(time_elapsed) + if (params.rank==0): + np.savetxt("dump_time_array.txt", dump_time_array) + + if(math.modf(time_elapsed/params.dt_dump_f)[0] < 1e-12): + formatted_time = format_time(time_elapsed) + nls.dump_distribution_function('dump_f/t=' + formatted_time) + + PETSc.Sys.Print("Time step =", time_step, ", Time =", time_elapsed) + + nls.strang_timestep(dt) + time_elapsed = time_elapsed + dt + time_step = time_step + 1 + params.time_step = time_step + params.current_time = time_elapsed + + # Floors + nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f) + + density = nls.compute_moments('density') + print("rank = ", params.rank, "\n", + " = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n", + " max(n) = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n" + ) + PETSc.Sys.Print("--------------------\n") + +#nls.dump_distribution_function('dump_f/t_laststep') diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie.py new file mode 100644 index 00000000..1de644d7 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie.py @@ -0,0 +1,134 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() + "/dumps" +moment_files = np.sort(glob.glob(filepath+'/moment*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) +dist_func_files = np.sort(glob.glob(filepath+'/f_*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q1, N_q2, 1, 1, N_p2, N_p1) + + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + #a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + #b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + #norm_factor = np.maximum(a, b) + #f_at_desired_q = \ + # np.reshape((dist_func-dist_func_background)[q2_position, q1_position, :, :], + # [N_p2, N_p1])/norm_factor + + f_at_desired_q = np.reshape((dist_func - \ + dist_func_background)[q1_position, q2_position, :], + [N_p2, N_p1] + ) + pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_debug.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_debug.py new file mode 100644 index 00000000..0b2c719d --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_debug.py @@ -0,0 +1,182 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(1): + for index_2 in range(N_q2): + + q1_position = index_1 + q2_position = index_2 + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = 1.#np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func - \ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + x = (radius + 5.)*np.cos(theta) + y = (radius + 5.)*np.sin(theta) + + x_bg = 5*np.cos(theta) + y_bg = 5*np.sin(theta) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.5, 6.5]) + pl.ylim([-6.5, 6.5]) + + pl.gca().set_aspect('equal') + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_zero_T.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_zero_T.py new file mode 100644 index 00000000..b13ab52d --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/momentum_space_movie_zero_T.py @@ -0,0 +1,193 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import os +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +from bolt.src.electronic_boltzmann.utils.polygon import polygon + +import domain +import params + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_s = len(params.mass) # Number of species + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1_start = domain.q1_start +q1_end = domain.q1_end +q2_start = domain.q2_start +q2_end = domain.q2_end + +q1 = q1_start + (0.5 + np.arange(N_q1)) * (q1_end - q1_start)/N_q1 +q2 = q2_start + (0.5 + np.arange(N_q2)) * (q2_end - q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 +N_p3 = domain.N_p3 + +p1_start = domain.p1_start +p1_end = domain.p1_end +p2_start = domain.p2_start +p2_end = domain.p2_end + +p1 = p1_start[0] + (0.5 + np.arange(N_p1)) * (p1_end[0] - p1_start[0])/N_p1 +p2 = p2_start[0] + (0.5 + np.arange(N_p2)) * (p2_end[0] - p2_start[0])/N_p2 + +p1_meshgrid, p2_meshgrid = np.meshgrid(p1, p2) + +p_x = p1_meshgrid * np.cos(p2_meshgrid) +p_y = p1_meshgrid * np.sin(p2_meshgrid) + +#p2_meshgrid, p1_meshgrid = np.meshgrid(p2, p1) + +io = PetscBinaryIO.PetscBinaryIO() + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) +dist_func_files = np.sort(glob.glob(filepath+'/dump_f/*.bin')) + +#moment_files = np.sort(glob.glob(filepath+'/dumps/moments*.bin')) +#lagrange_multiplier_files = \ +# np.sort(glob.glob(filepath+'/dumps/lagrange_multipliers*.bin')) +#dist_func_files = np.sort(glob.glob(filepath+'/dumps/f*.bin')) + +dist_func_bg_file = dist_func_files[0] +dist_func_file = dist_func_files[-1] + +print(dist_func_bg_file) +print(dist_func_file) + +dist_func_background = io.readBinaryFile(dist_func_bg_file) +#dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_p2, N_p1) +dist_func_background = dist_func_background[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) +dist_func = io.readBinaryFile(dist_func_file) + +print (dist_func[0].shape) + +dist_func = dist_func[0].reshape(N_q2, N_q1, N_s, N_p3, N_p2, N_p1) + +time_array = np.loadtxt("dump_time_array.txt") +file_number = -1 + +N = 7 +for index_1 in range(N): + for index_2 in range(N): + + q1_position = int(N_q1*((index_1/N)+(1/(2*N)))) + q2_position = int(N_q2*((index_2/N)+(1/(2*N)))) + + a = np.max((dist_func - dist_func_background)[q2_position, q1_position, :, :]) + b = np.abs(np.min((dist_func - dist_func_background)[q2_position, q1_position, :, :])) + norm_factor = np.maximum(a, b) + f_at_desired_q = \ + np.reshape((dist_func-\ + dist_func_background)[q2_position, q1_position, :, :],\ + [N_p2, N_p1])/norm_factor + + im = pl.plot(p2, f_at_desired_q) + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.ylabel('$f$') + pl.xlabel('$p_{\\theta}$') + #pl.tight_layout() + #pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + + np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + #f_at_desired_q = np.reshape((dist_func - \ + # dist_func_background)[q1_position, q2_position, :], + # [N_p2, N_p1] + # ) + + #print ("f at desired q : ", dist_func[q1_position, q2_position, :].shape) + print ("norm : ", norm_factor) + + + radius = f.copy() + theta = p2.copy() + + n = 6 # Number of sides of polygon + r_bg = 5. + + weight = polygon(n, af.from_ndarray(theta), rotation = np.pi/6).to_ndarray() + + x = (radius + r_bg)*np.cos(theta) * weight + y = (radius + r_bg)*np.sin(theta) * weight + + x_bg = r_bg*np.cos(theta)* weight + y_bg = r_bg*np.sin(theta)* weight + + # To remove the discontinuity at -pi/pi + x = np.insert(x, -1, x[0]) + y = np.insert(y, -1, y[0]) + + print ('p2 : ', p2.shape) + #pl.plot(p2, f_at_desired_q) + pl.plot(x, y, color='r', linestyle = '-', lw=3) + pl.plot(x_bg, y_bg, color='k', alpha=0.5, lw=3) + #pl.contourf(p1_meshgrid, p2_meshgrid, f_at_desired_q, 100, cmap='bwr') + + #np.savetxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2), f_at_desired_q) + #f = np.loadtxt('data/f_vs_theta_%d_%d.txt'%(index_1, index_2)) + + + #pl.contourf(p_x, p_y, f_at_desired_q, 100, cmap='bwr') + #pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.xlabel('$p_x$') + pl.ylabel('$p_y$') + + pl.xlim([-6.3, 6.3]) + pl.ylim([-6.3, 6.3]) + + pl.gca().set_aspect('equal') + pl.savefig('images/dist_func_at_a_point_%d_%d.png'%(index_1, index_2)) + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie.py new file mode 100644 index 00000000..b227ac0e --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie.py @@ -0,0 +1,147 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[:]): + + file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + #print (j_x.shape, vel_drift_x.shape, density.shape) + +# pl.subplot(121) + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.colorbar() + +# pl.subplot(122) +# pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') +# pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") +# pl.streamplot(q1, q2, +# j_x, j_y, +# density=2, color='k', +# linewidth=0.7, arrowsize=1 +# ) +# +# pl.xlim([q1[0], q1[-1]]) +# pl.ylim([q2[0], q2[-1]]) +# +# pl.gca().set_aspect('equal') +# pl.xlabel(r'$x\;(\mu \mathrm{m})$') +# #pl.ylabel(r'$y\;(\mu \mathrm{m})$') + #pl.colorbar() + + #pl.tight_layout() + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie_overplot.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie_overplot.py new file mode 100644 index 00000000..0504d6e8 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/movie_overplot.py @@ -0,0 +1,160 @@ +#import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +#import params +#import initialize + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +print ("moment files : ", moment_files.size) +print ("lagrange multiplier files : ", lagrange_multiplier_files.size) + + +filepath = os.getcwd() + '/../L_1.0_5.25_tau_ee_inf_tau_eph_inf_DC_rotated_fermi' +moment_files_2 = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) +lagrange_multiplier_files_2 = \ + np.sort(glob.glob(filepath+'/dump_lagrange_multipliers/*.bin')) + +time_array = np.loadtxt("dump_time_array.txt") + +io = PetscBinaryIO.PetscBinaryIO() + +for file_number, dump_file in enumerate(moment_files[:]): + + #file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q2, N_q1, 5) + + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + moments = io.readBinaryFile(moment_files_2[file_number]) + moments = moments[0].reshape(N_q1, N_q2, 3) + + density_2 = moments[:, :, 0].T + j_x_2 = moments[:, :, 1].T + j_y_2 = moments[:, :, 2].T + + lagrange_multipliers = \ + io.readBinaryFile(lagrange_multiplier_files_2[file_number]) + lagrange_multipliers = lagrange_multipliers[0].reshape(N_q1, N_q2, 5) + + vel_drift_x_2 = lagrange_multipliers[:, :, 3].T + vel_drift_y_2 = lagrange_multipliers[:, :, 4].T + + + pl.subplot(211) + pl.contourf(q1_meshgrid, q2_meshgrid, density.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.subplot(212) + pl.contourf(q1_meshgrid, q2_meshgrid, density_2.T, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + pl.streamplot(q1, q2, + vel_drift_x_2, vel_drift_y_2, + density=2, color='k', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([q1[0], q1[-1]]) + pl.ylim([q2[0], q2[-1]]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + #pl.tight_layout() + pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$') + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/params.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/params.py new file mode 100644 index 00000000..e656b1ee --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/params.py @@ -0,0 +1,279 @@ +import numpy as np +import arrayfire as af + +from bolt.src.electronic_boltzmann.utils.polygon import polygon +from bolt.src.electronic_boltzmann.utils.unit_vectors import normal_to_hexagon_unit_vec + +instantaneous_collisions = False #TODO : Remove from lib +hybrid_model_enabled = False #TODO : Remove from lib +source_enabled = True +disable_collision_op = False + +fields_enabled = False +# Can be defined as 'electrostatic', 'user-defined'. +# The initial conditions need to be specified under initialize +# Ensure that the initial conditions specified satisfy +# Maxwell's constraint equations +fields_initialize = 'user-defined' + +# Can be defined as 'electrostatic' and 'fdtd' +# To turn feedback from Electric fields on, set fields_solver = 'LCA' +# and set charge_electron +fields_type = 'electrostatic' +fields_solver = 'SNES' + +# Can be defined as 'strang' and 'lie' +time_splitting = 'strang' + +# Method in q-space +solver_method_in_q = 'FVM' +solver_method_in_p = 'FVM' + +reconstruction_method_in_q = 'minmod' +reconstruction_method_in_p = 'minmod' + +riemann_solver_in_q = 'upwind-flux' +riemann_solver_in_p = 'upwind-flux' + +electrostatic_solver_every_nth_step = 1000000 + + +# Time parameters: +dt = 0.025/4 # ps +t_final = 100. # ps + + +# File-writing Parameters: +dump_steps = 5 +dump_dist_after = 1600 +# Set to zero for no file-writing +dt_dump_f = 10000*dt #ps +# ALWAYS set dump moments and dump fields at same frequency: +dt_dump_moments = dt_dump_fields = 5*dt #ps + + +# Dimensionality considered in velocity space: +p_dim = 1 +p_space_grid = 'polar2D' # Supports 'cartesian' or 'polar2D' grids +# Set p-space start and end points accordingly in domain.py +#TODO : Use only polar2D for PdCoO2 + + +zero_temperature = (p_dim==1) +dispersion = 'quadratic' # 'linear' or 'quadratic' +fermi_surface_shape = 'hexagon' # Supports 'circle' or 'hexagon' + + +# Number of devices(GPUs/Accelerators) on each node: +num_devices = 6 + +# Constants: +mass_particle = 0.910938356 # x 1e-30 kg +h_bar = 1.0545718e-4 # x aJ ps +boltzmann_constant = 1 +charge = [0.*-0.160217662] # x aC +mass = [0.] #TODO : Not used in electronic_boltzmann + # Remove from lib +speed_of_light = 300. # x [um/ps] +fermi_velocity = speed_of_light/300 +epsilon0 = 8.854187817 # x [aC^2 / (aJ um) ] + +epsilon_relative = 3.9 # SiO2 +backgate_potential = -10 # V +global_chem_potential = 0.03 +contact_start = 0.0 # um +contact_end = 0.25 # um +contact_geometry = "straight" # Contacts on either side of the device + # For contacts on the same side, use + # contact_geometry = "turn_around" + +initial_temperature = 12e-4 +initial_mu = 0.015 +vel_drift_x_in = 1e-4*fermi_velocity +vel_drift_x_out = 1e-4*fermi_velocity +AC_freq = 1./100 # ps^-1 + +B3_mean = 1. # T + +# Spatial quantities (will be initialized to shape = [q1, q2] in initalize.py) +mu = None # chemical potential used in the e-ph operator +T = None # Electron temperature used in the e-ph operator +mu_ee = None # chemical potential used in the e-e operator +T_ee = None # Electron temperature used in the e-e operator +vel_drift_x = None +vel_drift_y = None +phi = None # Electric potential in the plane of graphene sheet +p_x = None +p_y = None +#integral_measure = None + +# Momentum quantities (will be initialized to shape = [p1*p2*p3] in initialize.py) +E_band = None +vel_band = None + +collision_operator_nonlinear_iters = 2 + +# Variation of collisional-timescale parameter through phase space: +@af.broadcast +def tau_defect(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +@af.broadcast +def tau_ee(q1, q2, p1, p2, p3): + return(np.inf * q1**0 * p1**0) + +def tau(q1, q2, p1, p2, p3): + return(tau_defect(q1, q2, p1, p2, p3)) + + +def fermi_momentum_magnitude(theta): + if (fermi_surface_shape == 'circle'): + p_f = initial_mu/fermi_velocity # Fermi momentum + + elif (fermi_surface_shape == 'hexagon'): + n = 6 # No. of sides of polygon + p_f = (initial_mu/fermi_velocity) * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + #TODO : If cartesian coordinates are being used, convert to polar to calculate p_f + else : + raise NotImplementedError('Unsupported shape of fermi surface') + return(p_f) + + +def band_energy(p1, p2): + # Note :This function is only meant to be called once to initialize E_band + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1 + theta = p2 + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + if (dispersion == 'linear'): + + E_upper = p*fermi_velocity + + elif (dispersion == 'quadratic'): + + m = effective_mass(p1, p2) + E_upper = p**2/(2.*m) + + if (zero_temperature): + + E_upper = initial_mu * p**0. + + af.eval(E_upper) + return(E_upper) + + +def effective_mass(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + + theta = af.atan(p_y/p_x) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + if (fermi_surface_shape == 'hexagon'): + + n = 6 # No. of side of polygon + mass = mass_particle * polygon(n, theta, rotation = np.pi/6) + # Note : Rotation by pi/6 results in a hexagon with horizontal top & bottom edges + + elif (fermi_surface_shape == 'circle'): + + # For now, just return the free electron mass + mass = mass_particle + + return(mass) + +def band_velocity(p1, p2): + # Note :This function is only meant to be called once to initialize the vel vectors + + if (p_space_grid == 'cartesian'): + p_x_local = p1 + p_y_local = p2 + + theta = af.atan(p_y_local/p_x_local) + + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + p = af.sqrt(p_x**2. + p_y**2.) + p_hat = [p_x / (p + 1e-20), p_y / (p + 1e-20)] + + if (fermi_surface_shape == 'circle'): + + v_f_hat = p_hat + + elif (fermi_surface_shape == 'hexagon'): + + v_f_hat = normal_to_hexagon_unit_vec(theta) + + # Quadratic dispersion + m = effective_mass(p1, p2) + v_f = p/m + + if (dispersion == 'linear' or zero_temperature): + + v_f = fermi_velocity + + upper_band_velocity = [v_f * v_f_hat[0], v_f * v_f_hat[1]] + + return(upper_band_velocity) + +def get_p_x_and_p_y(p1, p2): + + if (p_space_grid == 'cartesian'): + p_x = p1 + p_y = p2 + elif (p_space_grid == 'polar2D'): + # In polar2D coordinates, p1 = radius and p2 = theta + r = p1; theta = p2 + + if (zero_temperature): + # Get p_x and p_y at the Fermi surface + r = fermi_momentum_magnitude(theta) + + p_x = r * af.cos(theta) + p_y = r * af.sin(theta) + + else : + raise NotImplementedError('Unsupported coordinate system in p_space') + + return([p_x, p_y]) + +# Restart(Set to zero for no-restart): +latest_restart = True +t_restart = 0 + +@af.broadcast +def fermi_dirac(mu, E_band): + + k = boltzmann_constant + T = initial_temperature + + f = (1./(af.exp( (E_band - mu + )/(k*T) + ) + 1. + ) + ) + + af.eval(f) + return(f) diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/petsc_conf.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/petsc_conf.py new file mode 100755 index 00000000..22781ed2 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/petsc_conf.py @@ -0,0 +1,73 @@ +import warnings + +def get_conf(): + """Parses various PETSc configuration/include files to get data types. + + precision, indices, complexscalars = get_conf() + + Output: + precision: 'single', 'double', 'longlong' indicates precision of PetscScalar + indices: '32', '64' indicates bit-size of PetscInt + complex: True/False indicates whether PetscScalar is complex or not. + """ + + import sys, os + precision = None + indices = None + complexscalars = None + + if 'PETSC_DIR' in os.environ: + petscdir = os.environ['PETSC_DIR'] + else: + warnings.warn('PETSC_DIR env not set - unable to locate PETSc installation, using defaults') + return None, None, None + + if os.path.isfile(os.path.join(petscdir,'lib','petsc','conf','petscrules')): + # found prefix install + petscvariables = os.path.join(petscdir,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,'include','petscconf.h') + else: + if 'PETSC_ARCH' in os.environ: + petscarch = os.environ['PETSC_ARCH'] + if os.path.isfile(os.path.join(petscdir,petscarch,'lib','petsc','conf','petscrules')): + # found legacy install + petscvariables = os.path.join(petscdir,petscarch,'lib','petsc','conf','petscvariables') + petscconfinclude = os.path.join(petscdir,petscarch,'include','petscconf.h') + else: + warnings.warn('Unable to locate PETSc installation in specified PETSC_DIR/PETSC_ARCH, using defaults') + return None, None, None + else: + warnings.warn('PETSC_ARCH env not set or incorrect PETSC_DIR is given - unable to locate PETSc installation, using defaults') + return None, None, None + + try: + fid = open(petscvariables, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('PETSC_PRECISION'): + precision = line.strip().split('=')[1].strip('\n').strip() + + fid.close() + + try: + fid = open(petscconfinclude, 'r') + except IOError: + warnings.warn('Nonexistent or invalid PETSc installation, using defaults') + return None, None, None + else: + for line in fid: + if line.startswith('#define PETSC_USE_64BIT_INDICES 1'): + indices = '64bit' + elif line.startswith('#define PETSC_USE_COMPLEX 1'): + complexscalars = True + + if indices is None: + indices = '32bit' + if complexscalars is None: + complexscalars = False + fid.close() + + return precision, indices, complexscalars diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/phase_vs_y.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/phase_vs_y.py new file mode 100644 index 00000000..fc6ac364 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/phase_vs_y.py @@ -0,0 +1,180 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +from scipy.optimize import curve_fit +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +def sin_curve_fit(t, A, tau): + return A*np.sin(2*np.pi*AC_freq*(t + tau )) + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +# Left needs to be near source, right sensor near drain +sensor_1_left_start = 5.5 # um +sensor_1_left_end = 10.0 # um + +sensor_1_right_start = 5.5 # um +sensor_1_right_end = 10.0 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +filepath = \ + '/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_2.5_tau_ee_inf_tau_eph_2.5/dumps' + +AC_freq = 1./100.0 +time_period = 1/AC_freq +t_final = params.t_final +transient_time = t_final/2. + +time = np.loadtxt(filepath + "/../dump_time_array.txt") +edge_density = np.loadtxt(filepath + "/../edge_density.txt") +q2 = np.loadtxt(filepath + "/../q2_edge.txt") + +N_spatial = edge_density.shape[1] + +transient_index = int((transient_time/t_final)*time.size) + +drive = np.sin(2*np.pi*AC_freq*time) +nsamples = drive.size +dt_corr = np.linspace(-time[-1] + time[0],\ + time[-1] - time[0], 2*nsamples-1) + +# Discarding transients +q = q2.size/2 +time_half = time[transient_index:] +drive_half = drive[transient_index:] + +# Plotting signals at edge +norm_0 = np.max(edge_density[transient_index:, 0]) +norm_1 = np.max(edge_density[transient_index:, -1]) + +pl.plot(time, drive, color='black', linestyle='--') +pl.ylim([-1.1, 1.1]) +pl.xlim([0,200]) +pl.xlabel('$\mathrm{Time\;(s)}$') + +for i in range(N_spatial): + norm_i = np.max(edge_density[transient_index:, i]) + pl.plot(time, edge_density[:, i]/norm_i) + +pl.savefig('images/signals.png') +pl.clf() + +phase_shift_corr_array = [] +phase_shift_fitting_array = []\ + +for i in range(N_spatial): + print ('index : ', i) + signal_1 = edge_density[:, i] + norm_1 = np.max(signal_1[transient_index:]) + signal_1_normalized = signal_1/norm_1 + + # Calculate phase_shifts using scipy.correlate + corr = correlate(drive, signal_1_normalized) + time_shift_corr = dt_corr[corr.argmax()] + phase_shift_corr = 2*np.pi*(((0.5 + time_shift_corr/time_period) % 1.0) - 0.5) + + # Calculate phase_shifts using scipy.curve_fit + popt, pcov = curve_fit(sin_curve_fit, time[transient_index:],\ + signal_1_normalized[transient_index:]) + time_shift_fitting = popt[1]%(time_period/2.0) + phase_shift_fitting = 2*np.pi*(((0.5 + time_shift_fitting/time_period) % 1.0) - 0.5) + + phase_shift_corr_array.append(phase_shift_corr) + phase_shift_fitting_array.append(phase_shift_fitting) + +phase_shift_corr_array = np.array(phase_shift_corr_array) +phase_shift_fitting_array = np.array(phase_shift_fitting_array) + +# Plot +pl.ylabel('$\mathrm{\phi}$') +pl.xlabel('$\mathrm{y\ \mu m}$') + +pl.plot(q2, phase_shift_corr_array, '-o', label='$\mathrm{corr}$') +pl.plot(q2, phase_shift_fitting_array, '-o', label='$\mathrm{fit}$') + +pl.title('$\mathrm{2.5 \\times 10,\ \\tau_{ee} = \infty,\ \\tau_{eph} = 2.5}$') +pl.legend(loc='best') + +#pl.axvspan(sensor_1_left_start, sensor_1_left_end, color = 'k', alpha = 0.1) +#pl.axvspan(sensor_2_left_start, sensor_2_left_end, color = 'k', alpha = 0.1) + +pl.savefig('images/phase_vs_y.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/post.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/post.py new file mode 100644 index 00000000..a297c6f0 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/post.py @@ -0,0 +1,422 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +#pl.rcParams['figure.figsize'] = 8, 7.5 +pl.rcParams['figure.figsize'] = 8, 8 +#pl.rcParams['figure.figsize'] = 17, 9.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +#pl.rcParams['lines.linewidth'] = 3 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 +#N_q1 = 120 +#N_q2 = 240 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +source_start = params.contact_start +source_end = params.contact_end + +drain_start = params.contact_start +drain_end = params.contact_end + +#source_start = 3.5; source_end = 4.5 +#drain_start = 5.5; drain_end = 6.5 + +source_indices = (q2 > source_start) & (q2 < source_end) +drain_indices = (q2 > drain_start) & (q2 < drain_end ) + +sensor_1_left_start = 8.5 # um +sensor_1_left_end = 9.5 # um + +sensor_1_right_start = 8.5 # um +sensor_1_right_end = 9.5 # um + +# Left needs to be near source, right sensor near drain +#sensor_1_left_start = 1.5 # um +#sensor_1_left_end = 2.5 # um + +#sensor_1_right_start = 7.5 # um +#sensor_1_right_end = 8.5 # um + +sensor_1_left_indices = (q2 > sensor_1_left_start ) & (q2 < sensor_1_left_end) +sensor_1_right_indices = (q2 > sensor_1_right_start) & (q2 < sensor_1_right_end) + +sensor_2_left_start = 6.5 # um +sensor_2_left_end = 7.5 # um + +sensor_2_right_start = 6.5 # um +sensor_2_right_end = 7.5 # um + +sensor_2_left_indices = (q2 > sensor_2_left_start ) & (q2 < sensor_2_left_end) +sensor_2_right_indices = (q2 > sensor_2_right_start) & (q2 < sensor_2_right_end) + +#dump_index = 0 +#h5f = h5py.File('dumps/moments_' + '%06d'%(dump_index) + '.h5', 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#j_x = moments[:, :, 1] +#j_y = moments[:, :, 2] +#pl.contourf(q1, q2, density, 100) +##pl.title('Time = ' + "%.2f"%(t0)) +#pl.axes().set_aspect('equal') +#pl.xlabel(r'$x$') +#pl.ylabel(r'$y$') +#pl.colorbar() +#pl.savefig('images/density' + '.png') +#pl.clf() +# +#h5f = h5py.File('dumps/lagrange_multipliers_' + '%06d'%(dump_index) + '.h5', 'r') +#lagrange_multipliers = np.swapaxes(h5f['lagrange_multipliers'][:], 0, 1) +#h5f.close() +# +#print("lagrange_multipliers.shape = ", lagrange_multipliers.shape) +#mu = lagrange_multipliers[:, :, 0] +#mu_ee = lagrange_multipliers[:, :, 1] +#T_ee = lagrange_multipliers[:, :, 2] +#vel_drift_x = lagrange_multipliers[:, :, 3] +#vel_drift_y = lagrange_multipliers[:, :, 4] +#j_x_prime = density*vel_drift_x +#print("err = ", np.mean(np.abs(j_x_prime - j_x))) + +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_50_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_50_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_50_tau_ee_0.2.txt', q2) +##pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_5_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_5_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_5_tau_ee_0.2.txt', q2) +# +#filepath = \ +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/DC/tau_D_10_tau_ee_0.2' +#dump_file= np.sort(glob.glob(filepath+'/moment*.h5'))[-1] +# +#N_q1 = 120 +#N_q2 = 240 +# +#q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +#q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 +# +#h5f = h5py.File(dump_file, 'r') +#moments = np.swapaxes(h5f['moments'][:], 0, 1) +#h5f.close() +# +#density = moments[:, :, 0] +#np.savetxt('paper_plots/density_tau_D_10_tau_ee_0.2.txt', density) +#np.savetxt('paper_plots/q2_DC_tau_D_10_tau_ee_0.2.txt', q2) + + +#pl.plot(q2[q2>source_end], density[0, q2>source_end]-np.mean(density)) +#pl.axhline(0, color='black', linestyle='--') +#pl.legend(['$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=50$ ps', +# '$\\tau_{ee}=0.2$ ps, $\\tau_{e-ph}=10$ ps'], loc='lower right') +#pl.xlabel(r'$x\;(\mu \mathrm{m})$') +#pl.ylabel(r'$R\; (\mathrm{a.u.})$') +#pl.xlim(xmin=(source_end+0.1)) +#pl.savefig('paper_plots/DC.png') + +filepath = \ +'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_1_tau_ee_0.2_movie' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/geom_1/55_GHz/tau_D_5_tau_ee_0.2' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_AC_10_Ghz_tau_D_10_tau_ee_1_geom_2/' +#'/home/mchandra/bolt/example_problems/electronic_boltzmann/graphene/dumps_tau_D_2_tau_ee_1_AC/' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +sensor_1_signal_array = [] +print("Reading sensor signal...") +for file_number, dump_file in enumerate(moment_files): + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + density = moments[:, :, 0] + + source = np.mean(density[0, source_indices]) + drain = np.mean(density[-1, drain_indices]) + + sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) + sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) + + sensor_1_signal = sensor_1_left - sensor_1_right + + sensor_1_signal_array.append(sensor_1_signal) + +time_array = np.loadtxt("dump_time_array.txt") +AC_freq = 1./100 +input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +sensor_1_signal_array = np.array(sensor_1_signal_array) +half_time = (int)(time_array.size/2) +sensor_normalized = \ + sensor_1_signal_array/np.max(np.abs(sensor_1_signal_array[half_time:])) + +pl.rcParams['figure.figsize'] = 10, 8 +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + gs = gridspec.GridSpec(3, 2) + pl.subplot(gs[:, 0]) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + pl.contourf(q1_meshgrid, q2_meshgrid, density, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + #pl.colorbar() + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + +# pl.streamplot(q1[(int)(N_q1/2):], q2, +# vel_drift_x[:, (int)(N_q1/2):], vel_drift_y[:, (int)(N_q1/2):], +# density=2, color='blue', +# linewidth=0.7, arrowsize=1 +# ) + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) +# pl.streamplot(q1, q2, +# vel_drift_x, vel_drift_y, +# density=3, color='blue', +# linewidth=0.8, arrowsize=1.1 +# ) + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + #pl.ylim([0, 5]) + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + + pl.gca().annotate("+", xy=(-0.07, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white")) + pl.gca().annotate("-", xy=(1.05, .9), xycoords=("axes fraction"), + ha="center", va="center", size=30, + bbox=dict(fc="white", pad=6.5)) + + + pl.subplot(gs[1, 1]) + + pl.plot(time_array, input_signal_array) + pl.plot(time_array, sensor_normalized) + pl.axhline(0, color='black', linestyle='--') + pl.axvline(time_array[file_number], color='black', alpha=0.75) + pl.legend(['Source $I(t)$', 'Measured $V(t)$'], loc=(0.04, 1.125)) + pl.xlabel(r'Time (ps)') + pl.xlim([100, 200]) + pl.ylim([-1.1, 1.1]) + + + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1$ ps') + #pl.tight_layout() + pl.savefig('images/dump_' + '%06d'%file_number + '.png') + #pl.savefig('paper_plots/DC.png') + pl.clf() + + +#time_array = [] +#input_signal_array = [] +#sensor_1_signal_array = [] +#sensor_2_signal_array = [] +#for file_number, dump_file in enumerate(moment_files): +# +# print("file number = ", file_number, "of ", moment_files.size) +# +# h5f = h5py.File(dump_file, 'r') +# moments = np.swapaxes(h5f['moments'][:], 0, 1) +# h5f.close() +# +# density = moments[:, :, 0] +# +# source = np.mean(density[0, source_indices]) +# drain = np.mean(density[-1, drain_indices]) +# +# sensor_1_left = np.mean(density[0, sensor_1_left_indices] ) +# sensor_1_right = np.mean(density[-1, sensor_1_right_indices]) +# #sensor_1_right = np.mean(density[0, sensor_1_right_indices]) +# +# sensor_2_left = np.mean(density[0, sensor_2_left_indices] ) +# sensor_2_right = np.mean(density[-1, sensor_2_right_indices]) +# +# #sensor_1_left = density[0, q2>source_end] +# #sensor_1_right = density[-1, q2>source_end] +# +# input_signal = source - drain +# sensor_1_signal = sensor_1_left - sensor_1_right +# sensor_2_signal = sensor_2_left - sensor_2_right +# +# time_array.append(file_number*dt*dump_interval) +# input_signal_array.append(input_signal) +# sensor_1_signal_array.append(sensor_1_signal) +# sensor_2_signal_array.append(sensor_2_signal) +# +##pl.rcParams['figure.figsize'] = 12, 8 +## +#AC_freq = 5.5/100 +#time_array = np.array(time_array) +#input_signal_array = np.sin(2.*np.pi*AC_freq*time_array) +#sensor_1_signal_array = np.array(sensor_1_signal_array) +###np.savetxt('drive.txt', input_signal_array) +##np.savetxt('paper_plots/sensor_tau_ee_0.2_tau_D_5.txt', sensor_1_signal_array) +##np.savetxt('time.txt', time_array) +## +##print("sensor.shape = ", sensor_1_signal_array.shape) +##sensor_2_signal_array = np.array(sensor_2_signal_array) +## +#half_time = (int)(time_array.size/2) +#pl.plot(time_array, input_signal_array/np.max(input_signal_array[half_time:])) +#pl.plot(time_array, +# sensor_1_signal_array/np.max(sensor_1_signal_array[half_time:]) +# ) +##pl.plot(time_array, +## sensor_2_signal_array/np.max(sensor_2_signal_array[half_time:]) +## ) +#pl.xlabel(r"Time (ps)") +#pl.ylim([-1.1, 1.1]) +#pl.legend(['Input', 'Sensor 1', 'Sensor 2']) +#pl.savefig('paper_plots/IV_55_Ghz_tau_ee_0.2_tau_D_5.png') +##half_time = 0 +#input_normalized = input_signal_array[half_time:]/np.max(input_signal_array[half_time:]) +#sensor_normalized = sensor_1_signal_array[half_time:]/np.max(sensor_1_signal_array[half_time:]) +# +## Calculate the phase diff. Copied from: +## https://stackoverflow.com/questions/6157791/find-phase-difference-between-two-inharmonic-waves +#corr = correlate(input_normalized, sensor_normalized) +#nsamples = input_normalized.size +#time_corr = time_array[half_time:] +#dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], 2*nsamples-1) +#time_shift = dt_corr[corr.argmax()] +# +## force the phase shift to be in [-pi:pi] +#period = 1./AC_freq +#phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +#print("density.shape = ", density.shape) +#print("Phase diff = ", phase_diff) + +#phase_vs_x = [] +#for i in range(sensor_1_signal_array[0, :].size): +# signal = sensor_1_signal_array[:, i] +# corr = correlate(input_signal_array, signal) +# nsamples = input_signal_array.size +# half_time = 0 +# time_corr = time_array[half_time:] +# dt_corr = np.linspace(-time_corr[-1] + time_corr[0], +# time_corr[-1] - time_corr[0], +# 2*nsamples-1 +# ) +# time_shift = dt_corr[corr.argmax()] +# +# # force the phase shift to be in [-pi:pi] +# period = 1./params.AC_freq +# phase_diff = 2*np.pi*(((0.5 + time_shift/period) % 1.0) - 0.5) +# phase_vs_x.append(phase_diff) +# +#phase_vs_x = np.array(phase_vs_x) +#print("phase_vs_x.shape = ", phase_vs_x.shape) +#np.savetxt("paper_plots/phase_vs_x_tau_ee_0.2_tau_D_1.txt", phase_vs_x) +#np.savetxt("paper_plots/q2_tau_ee_0.2_tau_D_1.txt", q2) +#print("density.shape = ", density.shape) + + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/signals.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/signals.py new file mode 100644 index 00000000..7f7ba1e7 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/signals.py @@ -0,0 +1,123 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import sys +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +from matplotlib.collections import LineCollection +from matplotlib import transforms, colors +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +import params +#import initialize +#import coords + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +io = PetscBinaryIO.PetscBinaryIO() + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) + +filepath = os.getcwd() +moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) + +print ("moment files : ", moment_files.size) + +time_step = params.dt +dump_step = params.dt_dump_moments + +#time_array = np.loadtxt(filepath+"/dump_time_array.txt") +time_array = dump_step * np.arange(0, moment_files.size, 1) + +q1_index = 0; q2_index = (q2 < .25) + +sensor_1_array = [] +for file_number, dump_file in enumerate(moment_files[:]): + + #file_number = -1 + print("file number = ", file_number, "of ", moment_files.size) + + moments = io.readBinaryFile(moment_files[file_number]) + moments = moments[0].reshape(N_q2, N_q1, 3) + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + signal = np.mean(density[q2_index, q1_index]) + + sensor_1_array.append(signal) + +sensor_1_array = np.array(sensor_1_array) + +time_indices = time_array > 300 + +pl.plot(time_array[time_indices], sensor_1_array[time_indices] - np.mean(sensor_1_array[time_indices])) +pl.ylim([1e-8, -1e-8]) + +#pl.gca().set_aspect('equal') +pl.ylabel(r'$n$') +pl.xlabel(r'Time (ps)') +pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$ ps') +pl.savefig('images/iv.png') +pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/time_series.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/time_series.py new file mode 100644 index 00000000..f004d47c --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/time_series.py @@ -0,0 +1,140 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import os +import sys +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +from matplotlib.collections import LineCollection +from matplotlib import transforms, colors +matplotlib.use('agg') +import pylab as pl +#import yt +#yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc +import PetscBinaryIO + +import domain +#import boundary_conditions +import params +#import initialize +#import coords + + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 12, 7.5 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +io = PetscBinaryIO.PetscBinaryIO() + +N_p1 = domain.N_p1 +N_p2 = domain.N_p2 + +p1 = domain.p1_start[0] + (0.5 + np.arange(N_p1)) * (domain.p1_end[0] - \ + domain.p1_start[0])/N_p1 +p2 = domain.p2_start[0] + (0.5 + np.arange(N_p2)) * (domain.p2_end[0] - \ + domain.p2_start[0])/N_p2 + +print ('Momentum space : ', p1[-1], p2[int(N_p2/2)]) + +heights = np.arange(0.25, 0.351, 0.025) +heights_1 = np.arange(0.375, 0.4751, 0.025) +heights_2 = np.arange(0.500, 0.601, 0.025) +heights_3 = np.arange(0.650, 1.801, 0.025) +heights_4 = np.arange(1.800, 2.850, 0.05) +heights_5 = np.arange(3.000, 3.5001, 0.25) +heights = np.append(heights, heights_1) +heights = np.append(heights, heights_2) +heights = np.append(heights, heights_3) +heights = np.append(heights, heights_4) +heights = np.append(heights, heights_5) + +for index in heights: + filepath = \ + '/home/mchandra/gitansh/bolt_master/example_problems/electronic_boltzmann/pdcoo2/L_1.0_%.3f_tau_ee_inf_tau_eph_inf_DC_rotated'%index + + moment_files = np.sort(glob.glob(filepath+'/dump_moments/*.bin')) + + #print ("moment files : ", moment_files.size) + + q1_end = index + + N_q2 = domain.N_q2 + N_q1 = int(N_q2*q1_end/domain.q2_end) + + q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (q1_end - domain.q1_start)/N_q1 + q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + + q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + + dump_step = params.dt_dump_moments + + #time_array = np.loadtxt(filepath+"/dump_time_array.txt") + time_array = dump_step * np.arange(0, moment_files.size, 1) + + print("Index : ", index, ", moment files : ", moment_files.size) + + q1_index = 0; q2_index = (q2 < .25) + + #sensor_1_array = [] + #for file_number, dump_file in enumerate(moment_files[:]): + + # #file_number = -1 + # print("file number = ", file_number, "of ", moment_files.size) + + # moments = io.readBinaryFile(moment_files[file_number]) + # moments = moments[0].reshape(N_q2, N_q1, 3) + + # density = moments[:, :, 0] + # j_x = moments[:, :, 1] + # j_y = moments[:, :, 2] + + # signal = np.mean(density[q2_index, q1_index]) + + # sensor_1_array.append(signal) + + #sensor_1_array = np.array(sensor_1_array) + + #time_indices = time_array > 300 + + #pl.plot(time_array[time_indices], sensor_1_array[time_indices] - np.mean(sensor_1_array[time_indices])) + #pl.ylim([1e-8, -1e-8]) + + #pl.gca().set_aspect('equal') + #pl.ylabel(r'$n$') + #pl.xlabel(r'Time (ps)') + #pl.suptitle('$\\tau_\mathrm{mc} = \infty$, $\\tau_\mathrm{mr} = \infty$ ps') + #pl.savefig('images/iv.png') + #pl.clf() + diff --git a/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/vorticity.py b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/vorticity.py new file mode 100644 index 00000000..2f494c60 --- /dev/null +++ b/example_problems/electronic_boltzmann/pdcoo2/ref_rotated/vorticity.py @@ -0,0 +1,136 @@ +import arrayfire as af +import numpy as np +from scipy.signal import correlate +import glob +import h5py +import matplotlib +import matplotlib.gridspec as gridspec +import matplotlib.patches as patches +matplotlib.use('agg') +import pylab as pl +import yt +yt.enable_parallelism() + +import petsc4py, sys; petsc4py.init(sys.argv) +from petsc4py import PETSc + +from bolt.lib.physical_system import physical_system + +from bolt.lib.nonlinear_solver.nonlinear_solver \ + import nonlinear_solver +from bolt.lib.nonlinear_solver.EM_fields_solver.electrostatic \ + import compute_electrostatic_fields + +import domain +import boundary_conditions +import params +import initialize + +import bolt.src.electronic_boltzmann.advection_terms as advection_terms + +import bolt.src.electronic_boltzmann.collision_operator \ + as collision_operator + +import bolt.src.electronic_boltzmann.moment_defs as moment_defs + +# Optimized plot parameters to make beautiful plots: +pl.rcParams['figure.figsize'] = 8, 8 +pl.rcParams['figure.dpi'] = 100 +pl.rcParams['image.cmap'] = 'jet' +pl.rcParams['lines.linewidth'] = 1.5 +pl.rcParams['font.family'] = 'serif' +pl.rcParams['font.weight'] = 'bold' +pl.rcParams['font.size'] = 25 +pl.rcParams['font.sans-serif'] = 'serif' +pl.rcParams['text.usetex'] = True +pl.rcParams['axes.linewidth'] = 1.5 +pl.rcParams['axes.titlesize'] = 'medium' +pl.rcParams['axes.labelsize'] = 'medium' + +pl.rcParams['xtick.major.size'] = 8 +pl.rcParams['xtick.minor.size'] = 4 +pl.rcParams['xtick.major.pad'] = 8 +pl.rcParams['xtick.minor.pad'] = 8 +pl.rcParams['xtick.color'] = 'k' +pl.rcParams['xtick.labelsize'] = 'medium' +pl.rcParams['xtick.direction'] = 'in' + +pl.rcParams['ytick.major.size'] = 8 +pl.rcParams['ytick.minor.size'] = 4 +pl.rcParams['ytick.major.pad'] = 8 +pl.rcParams['ytick.minor.pad'] = 8 +pl.rcParams['ytick.color'] = 'k' +pl.rcParams['ytick.labelsize'] = 'medium' +pl.rcParams['ytick.direction'] = 'in' + +N_q1 = domain.N_q1 +N_q2 = domain.N_q2 + +q1 = domain.q1_start + (0.5 + np.arange(N_q1)) * (domain.q1_end - domain.q1_start)/N_q1 +q2 = domain.q2_start + (0.5 + np.arange(N_q2)) * (domain.q2_end - domain.q2_start)/N_q2 + +q2_meshgrid, q1_meshgrid = np.meshgrid(q2, q1) + +filepath = \ +'/home/mchandra/gitansh/bolt/example_problems/electronic_boltzmann/graphene/L_1.0_tau_ee_0.2_tau_eph_0.5/dumps' +moment_files = np.sort(glob.glob(filepath+'/moment*.h5')) +lagrange_multiplier_files = \ + np.sort(glob.glob(filepath+'/lagrange_multipliers*.h5')) + +dt = params.dt +dump_interval = params.dump_steps + +time_array = np.loadtxt("dump_time_array.txt") +half_time = (int)(time_array.size/2) + +for file_number, dump_file in yt.parallel_objects(enumerate(moment_files)): + + print("file number = ", file_number, "of ", moment_files.size) + + h5f = h5py.File(dump_file, 'r') + moments = np.swapaxes(h5f['moments'][:], 0, 1) + h5f.close() + + + density = moments[:, :, 0] + j_x = moments[:, :, 1] + j_y = moments[:, :, 2] + + h5f = h5py.File(lagrange_multiplier_files[file_number], 'r') + lagrange_multipliers = h5f['lagrange_multipliers'][:] + h5f.close() + + mu = lagrange_multipliers[:, :, 0] + mu_ee = lagrange_multipliers[:, :, 1] + T_ee = lagrange_multipliers[:, :, 2] + vel_drift_x = lagrange_multipliers[:, :, 3] + vel_drift_y = lagrange_multipliers[:, :, 4] + + + dq1 = (domain.q1_end - domain.q1_start)/domain.N_q1 + dq2 = (domain.q2_end - domain.q2_start)/domain.N_q2 + + dvx_dx, dvx_dy = np.gradient(j_x/density, dq1, dq2) + dvy_dx, dvy_dy = np.gradient(j_y/density, dq1, dq2) + + vorticity = dvy_dx - dvx_dy + + pl.contourf(q1_meshgrid, q2_meshgrid, vorticity, 100, cmap='bwr') + pl.title(r'Time = ' + "%.2f"%(time_array[file_number]) + " ps") + + pl.streamplot(q1, q2, + vel_drift_x, vel_drift_y, + density=2, color='blue', + linewidth=0.7, arrowsize=1 + ) + + pl.xlim([domain.q1_start, domain.q1_end]) + pl.ylim([domain.q2_start, domain.q2_end]) + + pl.gca().set_aspect('equal') + pl.xlabel(r'$x\;(\mu \mathrm{m})$') + pl.ylabel(r'$y\;(\mu \mathrm{m})$') + pl.suptitle('$\\tau_\mathrm{mc} = 0.2$ ps, $\\tau_\mathrm{mr} = 1.0$ ps') + pl.savefig('vorticity_images/dump_' + '%06d'%file_number + '.png') + pl.clf() +