scraed commited on
Commit
34a423b
·
verified ·
1 Parent(s): 18ef9a6

Upload folder using huggingface_hub

Browse files
Files changed (7) hide show
  1. .gitattributes +2 -0
  2. .gitignore +37 -0
  3. README.md +42 -3
  4. Run.py +1612 -0
  5. dynamics.png +3 -0
  6. requirements.txt +9 -0
  7. spectra.png +3 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ dynamics.png filter=lfs diff=lfs merge=lfs -text
37
+ spectra.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Large data and model files (exceed GitHub's 100MB limit or kept out of repo)
2
+ # See README for how to obtain these.
3
+ spectraV1_225_50_50_250000_5e_06_0_005_1_0_1_0.npz
4
+ Boltzmann3_macro_values_Adapt_FullExp.pkl
5
+ DSMC3ModelsExp/DSMC3LearnModelFull6.pt
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ *$py.class
11
+ *.so
12
+ .Python
13
+ *.egg-info/
14
+ .eggs/
15
+ dist/
16
+ build/
17
+
18
+ # Virtual envs
19
+ .env
20
+ .venv
21
+ venv/
22
+ env/
23
+
24
+ # IDE / OS
25
+ .idea/
26
+ .vscode/
27
+ .DS_Store
28
+ *.swp
29
+ *~
30
+
31
+ # Jupyter
32
+ .ipynb_checkpoints/
33
+ *.ipynb_checkpoints
34
+
35
+ # Optional: uncomment to also ignore generated outputs
36
+ # spectra.png
37
+ # dynamics.png
README.md CHANGED
@@ -1,3 +1,42 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Learning the Optimal Linear Hydrodynamic Closure
2
+
3
+ Code for generating spectral and time-evolution comparisons used in the paper *Learning the Optimal Linear Hydrodynamic Closure*. The main entry point is `Run.py`.
4
+
5
+ ## Setup
6
+
7
+ Create a fresh environment and install the dependencies:
8
+
9
+ ```bash
10
+ conda create -n nc-code python=3.11
11
+ conda activate nc-code
12
+ pip install -r requirements.txt
13
+ ```
14
+
15
+ If you prefer, you can use `venv` instead of Conda.
16
+
17
+ ## Required Files
18
+
19
+ Before running `Run.py`, make sure these files are present:
20
+
21
+ - `spectraV1_225_50_50_250000_5e_06_0_005_1_0_1_0.npz`
22
+ - `Boltzmann3_macro_values_Adapt_FullExp.pkl`
23
+ - `DSMC3ModelsExp/DSMC3LearnModelFull6.pt`
24
+
25
+ ## Run
26
+
27
+ Run from the repository root:
28
+
29
+ ```bash
30
+ python Run.py
31
+ ```
32
+
33
+ The script loads the precomputed data and trained model, then writes:
34
+
35
+ - `spectra.png`
36
+ - `dynamics.png`
37
+
38
+ ## Notes
39
+
40
+ - `Run.py` uses relative paths, so run it from the repository root.
41
+ - JAX is set to CPU mode in the script.
42
+ - `jax` and `torch` may need platform-specific installation steps on some systems.
Run.py ADDED
@@ -0,0 +1,1612 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import jax
2
+ import jax.numpy as np
3
+ jax.config.update("jax_platform_name", "cpu")
4
+ jax.config.update("jax_enable_x64", True)
5
+ import scipy
6
+ import scipy.special as special
7
+ import scipy.signal as signal
8
+ import matplotlib.pyplot as plt
9
+ import copy
10
+ import numpy.f2py
11
+ import os
12
+ import copy
13
+
14
+ from IPython.display import clear_output
15
+
16
+ with np.load(r"./spectraV1_225_50_50_250000_5e_06_0_005_1_0_1_0.npz", allow_pickle = True) as load:
17
+ densitiesF = load["densitiesF"]
18
+ parameters = load["parameters"].item()
19
+ try:
20
+ velocitiesF = load["velocitiesF"]
21
+ has_velocitiesF = True
22
+ except:
23
+ has_velocitiesF = False
24
+
25
+ for key in parameters.keys():
26
+ exec( key + "=parameters['"+key+"']" )
27
+ Boltz = 1.380622e-23
28
+
29
+ print("total_Time", total_Time)
30
+ for key in parameters.keys():
31
+ exec( key + "=parameters['"+key+"']" )
32
+
33
+ import scipy.special as special
34
+ import scipy.signal as signal
35
+
36
+ time_ratio = 0.05
37
+ domain_T = total_Time*(1-time_ratio)
38
+ cutoff_time_step = int(densitiesF.shape[0]*time_ratio)
39
+ spectra = np.sqrt(2*np.pi)**3/domain_LX/domain_LY/domain_LZ*np.sqrt(2*np.pi)/domain_T*np.abs( delta_x*delta_t*np.fft.fftn(densitiesF[cutoff_time_step:], axes=(-2, -1))/np.sqrt(2*np.pi)/np.sqrt(2*np.pi) )**2
40
+ kx_freq = 2*np.pi*np.fft.fftfreq(spectra.shape[1], d=delta_x)
41
+ omega_freq = 2*np.pi*np.fft.fftfreq(spectra.shape[0], d=delta_t)
42
+
43
+ tau_BGK = viscosity_coef/(density_0/molecule_mass*Boltz*Temp_0)
44
+ time_scale = 10*tau_BGK# non-dim tau_BGK = 0.1
45
+
46
+ kx_freq = 2*np.pi*np.fft.fftfreq(spectra.shape[1], d=delta_x)
47
+ omega_freq = 2*np.pi*np.fft.fftfreq(spectra.shape[0], d=delta_t)
48
+
49
+ space_scale = time_scale*np.sqrt(Boltz*Temp_0/molecule_mass) # Non-dim
50
+
51
+ k_titla_freq = kx_freq*space_scale
52
+ omega_titla_freq = omega_freq*time_scale
53
+ '''
54
+ k_number=11
55
+ omega_plot = np.fft.fftshift(omega_freq)/(kx_freq[k_number]*speed_of_sound)
56
+ omega_spacing = np.mean( omega_plot[1:]-omega_plot[:-1] )
57
+ plot_spectra = np.fft.fftshift( spectra[:,k_number])/space_scale**3/time_scale
58
+
59
+ b, a = signal.butter(1, 20, fs = 1/omega_spacing)
60
+ filtered_spectra = signal.filtfilt(b, a, plot_spectra)
61
+
62
+
63
+ def CE_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k):
64
+ m = molecule_mass
65
+ mu1 = 0
66
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
67
+ mu2 = -4/3*Kn
68
+ mu3 = 0
69
+ kap1 = 0
70
+ kap2 = 0
71
+ kap3 = -15/4*Kn
72
+ kabs = np.abs(k)
73
+ tau1 = -kabs*(1-kabs**2*mu1)
74
+ tau2 = kabs**2*mu2
75
+ tau3 = -kabs*(1-kabs**2*mu3)
76
+ tau4 = 2/3*kabs**2*kap1
77
+ tau5 = -2/3*kabs*(1+kap2)
78
+ tau6 = 2/3*kabs**2*kap3
79
+ omega = omega_freq
80
+ Neff = num_effect
81
+ rho0 = density_0
82
+ L = delta_x
83
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
84
+ return spec
85
+ #m = molecule_mass*num_effect/(4*np.pi**2*wavelength**3)
86
+ #spec = -((complex(0,1)*m*(-4*k**2-20*k**4*Kn**2-23*complex(0,1)*k**2*Kn*omega_freq+6*omega_freq**2))/(density_0*(15*complex(0,1)*k**4*Kn-10*k**2*omega_freq-20*k**4*Kn**2*omega_freq-23*complex(0,1)*k**2*Kn*omega_freq**2+6*omega_freq**3)))
87
+ #return 2*np.real(spec)
88
+
89
+ def TH_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k, mask = -1):
90
+ m = molecule_mass
91
+ mu1 = 0
92
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
93
+ mu2 = -4/3*Kn
94
+ mu3 = 0
95
+ kap1 = 0
96
+ kap2 = 0
97
+ kap3 = -15/4*Kn
98
+ kabs = np.abs(k)
99
+ print(kabs)
100
+ tau1 = -0.910858854965221635639183580413607*kabs-0.0681031747662745635208073664825305*kabs**2
101
+ tau2 = -0.137647159761080650249789096758410*kabs**2+0.00258989586650062128792005410176610*kabs**3
102
+ tau3 = -0.980736834542179305331651160476348*kabs+0.002878781203443508188808986885745442*kabs**3
103
+ tau4 = 0.00270043719488066581208735095210*kabs**2-0.000956430940350492874510704526398*kabs**3+0.0000398354558076273539332410866928*kabs**4
104
+ #tau4 = 2/3*kabs**2*kap1
105
+ tau5 = -0.677006693600986515897927777975082*kabs-0.02720695551116714037510321445687466*kabs**2
106
+ tau6 = -0.248523533056964259160237397019776*kabs**2+0.00978711916205478871774188307120469*kabs**3
107
+
108
+
109
+ if mask == 0:
110
+ tau1 = -kabs*(1-kabs**2*mu1)
111
+ elif mask == 1:
112
+ tau2 = kabs**2*mu2
113
+ elif mask == 2:
114
+ tau3 = -kabs*(1-kabs**2*mu3)
115
+ elif mask == 3:
116
+ tau4 = 2/3*kabs**2*kap1
117
+ elif mask == 4:
118
+ tau5 = -2/3*kabs*(1+kap2)
119
+ elif mask == 5:
120
+ tau6 = 2/3*kabs**2*kap3
121
+ omega = omega_freq
122
+ Neff = num_effect
123
+ rho0 = density_0
124
+ L = delta_x
125
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
126
+ return spec
127
+
128
+ def THBGK_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k, mask = -1):
129
+ m = molecule_mass
130
+ mu1 = 0
131
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
132
+ mu2 = -4/3*Kn
133
+ mu3 = 0
134
+ kap1 = 0
135
+ kap2 = 0
136
+ kap3 = -15/4*Kn
137
+ kabs = np.abs(k)
138
+ print(kabs)
139
+ #tau1 = -0.910858854965221635639183580413607*kabs-0.0681031747662745635208073664825305*kabs**2
140
+ tau1 = -0.9858867248408030*kabs-0.04701941111476196*kabs**2
141
+ #tau2 = -0.137647159761080650249789096758410*kabs**2+0.00258989586650062128792005410176610*kabs**3
142
+ tau2 = -0.129198118429724*kabs**2+0.00400848955369925*kabs**3
143
+ #tau3 = -0.980736834542179305331651160476348*kabs+0.002878781203443508188808986885745442*kabs**3
144
+ tau3 = -1.002964233770220*kabs-0.0000911571759799050*kabs**3
145
+ #tau4 = 0.00270043719488066581208735095210*kabs**2-0.000956430940350492874510704526398*kabs**3+0.0000398354558076273539332410866928*kabs**4
146
+ tau4 = -0.0084451424529939*kabs**2-0.00060032464997635*kabs**3+0.000017125859875981*kabs**4
147
+ #tau4 = 2/3*kabs**2*kap1
148
+ #tau5 = -0.677006693600986515897927777975082*kabs-0.02720695551116714037510321445687466*kabs**2
149
+ tau5 = -0.677965329349480*kabs-0.002348308957845470*kabs**2
150
+ #tau6 = -0.248523533056964259160237397019776*kabs**2+0.00978711916205478871774188307120469*kabs**3
151
+ tau6 = -0.185259190536085*kabs**2+0.0068634125525231*kabs**3
152
+
153
+
154
+ if mask == 0:
155
+ tau1 = -kabs*(1-kabs**2*mu1)
156
+ elif mask == 1:
157
+ tau2 = kabs**2*mu2
158
+ elif mask == 2:
159
+ tau3 = -kabs*(1-kabs**2*mu3)
160
+ elif mask == 3:
161
+ tau4 = 2/3*kabs**2*kap1
162
+ elif mask == 4:
163
+ tau5 = -2/3*kabs*(1+kap2)
164
+ elif mask == 5:
165
+ tau6 = 2/3*kabs**2*kap3
166
+ omega = omega_freq
167
+ Neff = num_effect
168
+ rho0 = density_0
169
+ L = delta_x
170
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
171
+ return spec
172
+ def MW_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k):
173
+ m = molecule_mass
174
+ mu1 = 0
175
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
176
+ mu2 = -4/3*Kn
177
+ mu3 = 0
178
+ kap1 = 0
179
+ kap2 = 0
180
+ kap3 = -15/4*Kn
181
+ kabs = np.abs(k)
182
+ tau1 = -kabs*(1-kabs**2*mu1)
183
+ tau2 = kabs**2*mu2
184
+ tau3 = -kabs*(1-kabs**2*mu3)
185
+ tau4 = 2/3*kabs**2*kap1
186
+ tau5 = -2/3*kabs*(1+kap2)
187
+ tau6 = 2/3*kabs**2*kap3
188
+ omega = omega_freq
189
+ Neff = num_effect
190
+ rho0 = density_0
191
+ L = delta_x
192
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
193
+ return spec
194
+ #m = molecule_mass*num_effect/(4*np.pi**2*wavelength**3)
195
+ #spec = -((complex(0,1)*m*(-4*k**2-20*k**4*Kn**2-23*complex(0,1)*k**2*Kn*omega_freq+6*omega_freq**2))/(density_0*(15*complex(0,1)*k**4*Kn-10*k**2*omega_freq-20*k**4*Kn**2*omega_freq-23*complex(0,1)*k**2*Kn*omega_freq**2+6*omega_freq**3)))
196
+ #return 2*np.real(spec)
197
+
198
+ plt.title("k = "+ str(k_titla_freq[k_number]))
199
+ plt.plot(omega_plot , filtered_spectra, label = "DSMC")
200
+ plt.plot( np.fft.fftshift(omega_freq)/(kx_freq[k_number]*speed_of_sound) , np.fft.fftshift( CE_spectra(space_scale,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_titla_freq,num_effect,k_titla_freq[k_number])) , label = "NS Equation")
201
+ plt.legend()
202
+ plt.xlim(-2,2)
203
+ plt.show()
204
+ plt.title("k = "+ str(k_titla_freq[k_number]))
205
+ plt.plot(omega_plot , filtered_spectra, label = "DSMC")
206
+ plt.plot( np.fft.fftshift(omega_freq)/(kx_freq[k_number]*speed_of_sound) , np.fft.fftshift( TH_spectra(space_scale,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_titla_freq,num_effect,k_titla_freq[k_number])) , label = "TheorysBGK")
207
+ plt.legend()
208
+ plt.xlim(-2,2)
209
+ plt.show()
210
+ plt.title("k = "+ str(k_titla_freq[k_number]))
211
+ plt.plot(omega_plot , filtered_spectra, label = "DSMC")
212
+ plt.plot( np.fft.fftshift(omega_freq)/(kx_freq[k_number]*speed_of_sound) , np.fft.fftshift( THBGK_spectra(space_scale,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_titla_freq,num_effect,k_titla_freq[k_number])) , label = "TheoryBGK")
213
+ plt.legend()
214
+ plt.xlim(-2,2)
215
+ plt.show()
216
+
217
+ '''
218
+ k_traval = np.logspace(-2, 2.79817986094985, 2048, endpoint=True)
219
+ from jax import grad, jit, vmap
220
+ from numpy.polynomial.hermite import hermgauss
221
+ from scipy import optimize
222
+ import jaxopt
223
+ from scipy.sparse.linalg import LinearOperator
224
+ from jax.scipy.optimize import minimize
225
+ from functools import partial
226
+ # Define the function \tilde{h}^{(+)}
227
+ @jit
228
+ def h_plus(u, k, omega):
229
+ # Dummy implementation of \tilde{h}^{(+)} for demonstration purposes
230
+ #out = np.sin(np.dot(u, k)[:, np.newaxis] + omega)
231
+ out = np.sin(np.dot(u, k)[:, np.newaxis] + omega)*0
232
+ return out
233
+ @jit
234
+ def compute_n_plus(k, h_values, u_mesh, u_weights):
235
+ u_squared = np.sum(u_mesh**2, axis=-1)
236
+ pre_factor = 1
237
+
238
+ # Vectorize the computation over omega
239
+
240
+ integrand = h_values[:, :, np.newaxis]
241
+ integral = np.sum(integrand * u_weights[:, np.newaxis, np.newaxis], axis=0)
242
+ q_plus = pre_factor * integral
243
+
244
+ return q_plus
245
+ @jit
246
+ def compute_v_plus(k, h_values, u_mesh, u_weights):
247
+ u_squared = np.sum(u_mesh**2, axis=-1)
248
+ pre_factor = 1
249
+
250
+ # Vectorize the computation over omega
251
+
252
+ integrand = u_mesh[:, np.newaxis, :] * h_values[:, :, np.newaxis]
253
+ integral = np.sum(integrand * u_weights[:, np.newaxis, np.newaxis], axis=0)
254
+ q_plus = pre_factor * integral
255
+
256
+ return q_plus
257
+ @jit
258
+ def compute_T_plus(k, h_values, u_mesh, u_weights):
259
+ u_squared = np.sum(u_mesh**2, axis=-1)
260
+ pre_factor = 1
261
+
262
+ # Vectorize the computation over omega
263
+
264
+ integrand = 1/3 * (u_squared[:, np.newaxis, np.newaxis] * h_values[:, :, np.newaxis])
265
+ integral = np.sum(integrand * u_weights[:, np.newaxis, np.newaxis], axis=0)
266
+ q_plus = pre_factor * integral
267
+
268
+ return q_plus
269
+ @jit
270
+ def compute_sigma_plus(k, h_values, u_mesh, u_weights):
271
+ u_squared = np.sum(u_mesh**2, axis=-1)
272
+ pre_factor = 1
273
+
274
+ # Vectorize the computation over omega
275
+
276
+ integrand = ( ((u_mesh[:,np.newaxis,:]*u_mesh[:,:,np.newaxis]).reshape(u_mesh.shape[0],1,-1)- 1/3 * (np.sum(u_mesh**2, axis=-1)[:,np.newaxis,np.newaxis]*np.eye(3).reshape(-1))) * h_values[:, :, np.newaxis])
277
+ integral = np.sum(integrand * u_weights[:, np.newaxis, np.newaxis], axis=0)
278
+ q_plus = pre_factor * integral
279
+
280
+ return q_plus
281
+
282
+ # Function to compute \tilde{q}^{(+)} _i
283
+ @jit
284
+ def compute_q_plus(k, h_values, u_mesh, u_weights):
285
+ u_squared = np.sum(u_mesh**2, axis=-1)
286
+ pre_factor = 1
287
+
288
+ # Vectorize the computation over omega
289
+
290
+ integrand = 1/2*u_mesh[:, np.newaxis, :] * (u_squared[:, np.newaxis, np.newaxis] * h_values[:, :, np.newaxis])
291
+ integral = np.sum(integrand * u_weights[:, np.newaxis, np.newaxis], axis=0)
292
+ q_plus = pre_factor * integral
293
+
294
+ return q_plus
295
+
296
+
297
+ @jit
298
+ def taus(k):
299
+ m = molecule_mass
300
+ mu1 = 0
301
+ Kn = (np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/space_scale)[0]
302
+ mu2 = -4/3*Kn
303
+ mu3 = 0
304
+ kap1 = 0
305
+ kap2 = 0
306
+ kap3 = -15/4*Kn
307
+ kabs = np.abs(k)
308
+ tau1 = -kabs*(1-kabs**2*mu1)
309
+ tau2 = kabs**2*mu2
310
+ tau3 = -kabs*(1-kabs**2*mu3)
311
+ tau4 = 2/3*kabs**2*kap1
312
+ tau5 = -2/3*kabs*(1+kap2)
313
+ tau6 = 2/3*kabs**2*kap3
314
+ return tau1, tau2, tau3, tau4, tau5, tau6
315
+
316
+ @jit
317
+ def denominator_reg(denominator):
318
+ sign = 1-2*(denominator < 0)
319
+ return sign*np.maximum(np.abs(denominator), 1e-10)
320
+ @jit
321
+ def get_rhoRe(k,omega):
322
+ tau1, tau2, tau3, tau4, tau5, tau6 = taus(k)
323
+ # Define the numerator
324
+ numerator = k * omega**2 * (tau1 * tau2 + tau3 * tau4) - k * (tau3 * tau4 - tau1 * tau6) * (tau2 * tau6 + tau3 * tau5)
325
+
326
+ # Define the denominator
327
+ denominator = (omega**2 * (k**2 * tau1**2 - 2 * k * (tau1 * tau3 * tau5 - tau1 * tau6**2 + tau2 * tau3 * tau4 + tau3 * tau4 * tau6)
328
+ + (tau2 * tau6 + tau3 * tau5)**2) + k**2 * (tau3 * tau4 - tau1 * tau6)**2
329
+ + omega**4 * (2 * k * tau1 + tau2**2 - 2 * tau3 * tau5 + tau6**2) + omega**6)
330
+ # Define the expression
331
+ expression = numerator / denominator_reg(denominator)
332
+ return expression
333
+ @jit
334
+ def get_rhoIm(k,omega):
335
+ tau1, tau2, tau3, tau4, tau5, tau6 = taus(k)
336
+ # Define the numerator
337
+ numerator_2 = omega * (-(tau3 * tau5 + tau2 * tau6)**2 - (tau2**2 - 2 * tau3 * tau5 + tau6**2) * omega**2
338
+ - omega**4 + k * (tau2 * tau3 * tau4 + tau1 * tau3 * tau5 + tau3 * tau4 * tau6
339
+ - tau1 * tau6**2 - tau1 * omega**2))
340
+
341
+ # Define the denominator
342
+ denominator_2 = (k**2 * (tau3 * tau4 - tau1 * tau6)**2
343
+ + (k**2 * tau1**2 + (tau3 * tau5 + tau2 * tau6)**2
344
+ - 2 * k * (tau2 * tau3 * tau4 + tau1 * tau3 * tau5 + tau3 * tau4 * tau6 - tau1 * tau6**2)) * omega**2
345
+ + (2 * k * tau1 + tau2**2 - 2 * tau3 * tau5 + tau6**2) * omega**4 + omega**6)
346
+
347
+ # Define the expression
348
+ expression_2 = numerator_2 / denominator_reg(denominator_2)
349
+ return expression_2
350
+ @jit
351
+ def get_vRe(k,omega):
352
+ tau1, tau2, tau3, tau4, tau5, tau6 = taus(k)
353
+ # Define the numerator
354
+ numerator_3 = omega * (tau3 * tau4 - tau1 * tau6) * (tau2 * tau6 + tau3 * tau5) - omega**3 * (tau1 * tau2 + tau3 * tau4)
355
+
356
+ # Define the denominator
357
+ denominator_3 = (omega**2 * (k**2 * tau1**2 - 2 * k * (tau1 * tau3 * tau5 - tau1 * tau6**2 + tau2 * tau3 * tau4 + tau3 * tau4 * tau6)
358
+ + (tau2 * tau6 + tau3 * tau5)**2)
359
+ + k**2 * (tau3 * tau4 - tau1 * tau6)**2
360
+ + omega**4 * (2 * k * tau1 + tau2**2 - 2 * tau3 * tau5 + tau6**2)
361
+ + omega**6)
362
+
363
+ # Define the expression
364
+ expression_3 = numerator_3 / denominator_reg(denominator_3)
365
+ return expression_3
366
+ @jit
367
+ def get_vIm(k,omega):
368
+ tau1, tau2, tau3, tau4, tau5, tau6 = taus(k)
369
+ # Define the numerator
370
+ numerator_4 = (-k * (tau3 * tau4 - tau1 * tau6)**2 + (-k * tau1**2 + tau2 * tau3 * tau4 + tau1 * tau3 * tau5
371
+ + tau3 * tau4 * tau6 - tau1 * tau6**2) * omega**2
372
+ - tau1 * omega**4)
373
+
374
+ # Define the denominator
375
+ denominator_4 = (k**2 * (tau3 * tau4 - tau1 * tau6)**2
376
+ + (k**2 * tau1**2 + (tau3 * tau5 + tau2 * tau6)**2
377
+ - 2 * k * (tau2 * tau3 * tau4 + tau1 * tau3 * tau5 + tau3 * tau4 * tau6 - tau1 * tau6**2)) * omega**2
378
+ + (2 * k * tau1 + tau2**2 - 2 * tau3 * tau5 + tau6**2) * omega**4 + omega**6)
379
+
380
+ # Define the expression
381
+ expression_4 = numerator_4 / denominator_reg(denominator_4)
382
+ return expression_4
383
+ @jit
384
+ def get_TRe(k,omega):
385
+ tau1, tau2, tau3, tau4, tau5, tau6 = taus(k)
386
+ # Define the numerator
387
+ numerator_5 = (-omega**2 * (k * tau1 * tau4 + tau1 * tau2 * tau5 + tau1 * tau5 * tau6 + tau2**2 * tau4 - tau3 * tau4 * tau5)
388
+ + k * (tau1 * tau5 + tau2 * tau4) * (tau3 * tau4 - tau1 * tau6) - tau4 * omega**4)
389
+
390
+ # Define the denominator
391
+ denominator_5 = (omega**2 * (k**2 * tau1**2 - 2 * k * (tau1 * tau3 * tau5 - tau1 * tau6**2 + tau2 * tau3 * tau4 + tau3 * tau4 * tau6)
392
+ + (tau2 * tau6 + tau3 * tau5)**2)
393
+ + k**2 * (tau3 * tau4 - tau1 * tau6)**2
394
+ + omega**4 * (2 * k * tau1 + tau2**2 - 2 * tau3 * tau5 + tau6**2)
395
+ + omega**6)
396
+
397
+ # Define the expression
398
+ expression_5 = numerator_5 / denominator_reg(denominator_5)
399
+ return expression_5
400
+ @jit
401
+ def get_TIm(k,omega):
402
+ tau1, tau2, tau3, tau4, tau5, tau6 = taus(k)
403
+ # Define the numerator
404
+ numerator_6 = omega * (-k * (tau3 * tau4**2 + tau1**2 * tau5 + tau1 * tau4 * (tau2 - tau6))
405
+ + (tau2 * tau4 + tau1 * tau5) * (tau3 * tau5 + tau2 * tau6)
406
+ + (-tau1 * tau5 + tau4 * tau6) * omega**2)
407
+
408
+ # Define the denominator
409
+ denominator_6 = (k**2 * (tau3 * tau4 - tau1 * tau6)**2
410
+ + (k**2 * tau1**2 + (tau3 * tau5 + tau2 * tau6)**2
411
+ - 2 * k * (tau2 * tau3 * tau4 + tau1 * tau3 * tau5 + tau3 * tau4 * tau6 - tau1 * tau6**2)) * omega**2
412
+ + (2 * k * tau1 + tau2**2 - 2 * tau3 * tau5 + tau6**2) * omega**4 + omega**6)
413
+
414
+ # Define the expression
415
+ expression_6 = numerator_6 / denominator_reg(denominator_6)
416
+ return expression_6
417
+ @jit
418
+ def get_rhoRe_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
419
+ h_values_Re = Kn/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
420
+ return compute_n_plus(k, h_values_Re, u_mesh, u_weights)
421
+ @jit
422
+ def get_rhoIm_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
423
+ h_values_Im = -Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
424
+ return compute_n_plus(k, h_values_Im, u_mesh, u_weights)
425
+ @jit
426
+ def get_vRe_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
427
+ h_values_Re = Kn/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
428
+ return compute_v_plus(k, h_values_Re, u_mesh, u_weights)
429
+ @jit
430
+ def get_vIm_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
431
+ h_values_Im = -Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
432
+ return compute_v_plus(k, h_values_Im, u_mesh, u_weights)
433
+ @jit
434
+ def get_TRe_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
435
+ h_values_Re = Kn/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
436
+ return compute_T_plus(k, h_values_Re, u_mesh, u_weights) - compute_n_plus(k, h_values_Re, u_mesh, u_weights)
437
+ @jit
438
+ def get_TIm_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
439
+ h_values_Im = -Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
440
+ return compute_T_plus(k, h_values_Im, u_mesh, u_weights) - compute_n_plus(k, h_values_Im, u_mesh, u_weights)
441
+ @jit
442
+ def get_sigmaRe_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
443
+ h_values_Re = Kn/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
444
+ return compute_sigma_plus(k, h_values_Re, u_mesh, u_weights)
445
+ @jit
446
+ def get_sigmaIm_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
447
+ h_values_Im = -Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
448
+ return compute_sigma_plus(k, h_values_Im, u_mesh, u_weights)
449
+ @jit
450
+ def get_qRe_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
451
+ h_values_Re = Kn/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
452
+ return compute_q_plus(k, h_values_Re, u_mesh, u_weights) - 5/2*compute_v_plus(k, h_values_Re, u_mesh, u_weights)
453
+ @jit
454
+ def get_qIm_Asymp(k, Kn, omega_mesh, u_mesh, u_weights):
455
+ h_values_Im = -Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
456
+ return compute_q_plus(k, h_values_Im, u_mesh, u_weights) - 5/2*compute_v_plus(k, h_values_Im, u_mesh, u_weights)
457
+
458
+
459
+ @jit
460
+ def func(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh):
461
+ lamb = 1
462
+ h_values_Re, h_values_Im = x[:len(x)//2], x[len(x)//2:]
463
+ n_plus_result_Re = compute_n_plus(k, h_values_Re, u_mesh, u_weights)
464
+ n_plus_result_Im = compute_n_plus(k, h_values_Im, u_mesh, u_weights)
465
+
466
+ v_plus_result_Re = compute_v_plus(k, h_values_Re, u_mesh, u_weights)
467
+ v_plus_result_Im = compute_v_plus(k, h_values_Im, u_mesh, u_weights)
468
+
469
+ T_plus_result_Re = compute_T_plus(k, h_values_Re, u_mesh, u_weights) - n_plus_result_Re
470
+ T_plus_result_Im = compute_T_plus(k, h_values_Im, u_mesh, u_weights) - n_plus_result_Im
471
+
472
+ sigma_plus_result_Re = compute_sigma_plus(k, h_values_Re, u_mesh, u_weights)
473
+ sigma_plus_result_Im = compute_sigma_plus(k, h_values_Im, u_mesh, u_weights)
474
+
475
+ q_plus_result_Re = compute_q_plus(k, h_values_Re, u_mesh, u_weights) - 5/2*v_plus_result_Re
476
+ q_plus_result_Im = compute_q_plus(k, h_values_Im, u_mesh, u_weights) - 5/2*v_plus_result_Im
477
+ # Spectra
478
+ rho0k = 1
479
+ # Density impulse
480
+
481
+
482
+ h_values_Re_new = Kn*(h_values_Im*omega_mesh + u_mesh.dot(k)[:,np.newaxis]*h_values_Im + rho0k) + lamb*(-\
483
+ (1-Pr)*(1 - np.sum( u_mesh**2, axis = -1 )[:,np.newaxis]/5 )*np.sum( u_mesh[:, np.newaxis,:]*q_plus_result_Re, axis = -1 ) +\
484
+ n_plus_result_Re[:,0] + np.sum( u_mesh[:, np.newaxis,:]*v_plus_result_Re, axis = -1 ) +\
485
+ (np.sum( u_mesh**2, axis = -1 )[:,np.newaxis]/2 - 3/2 )*T_plus_result_Re[:,0] )
486
+ h_values_Im_new = -Kn*(h_values_Re*omega_mesh + u_mesh.dot(k)[:,np.newaxis]*h_values_Re) + lamb*( -\
487
+ (1-Pr)*(1 - np.sum( u_mesh**2, axis = -1 )[:,np.newaxis]/5 )*np.sum( u_mesh[:, np.newaxis,:]*q_plus_result_Im, axis = -1 )+\
488
+ n_plus_result_Im[:,0] + np.sum( u_mesh[:, np.newaxis,:]*v_plus_result_Im, axis = -1 ) +\
489
+ (np.sum( u_mesh**2, axis = -1 )[:,np.newaxis]/2 - 3/2 )*T_plus_result_Im[:,0] )
490
+
491
+
492
+ resRe = (h_values_Re_new - h_values_Re)#*(u_weights/np.max(u_weights))[:, np.newaxis]
493
+ resIm = (h_values_Im_new - h_values_Im)#*(u_weights/np.max(u_weights))[:, np.newaxis]
494
+
495
+ return np.concatenate( (resRe , resIm) , axis = 0)
496
+
497
+
498
+
499
+
500
+
501
+ @jit
502
+ def mv(h_flat, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re):
503
+ shape = h_values_Re.shape
504
+ h_values_Re = h_flat[:len(h_flat)//2].reshape(shape)
505
+ h_values_Im = h_flat[len(h_flat)//2:].reshape(shape)
506
+ x = np.concatenate( (h_values_Re , h_values_Im) , axis = 0)
507
+ return func(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh).reshape(-1)
508
+
509
+ @jit
510
+ def rescompute_mv(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re):
511
+ return np.mean( mv(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re)**2 )
512
+
513
+ @jit
514
+ def grad_rescompute_mv(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re):
515
+ return grad(rescompute_mv)(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re)
516
+
517
+ @partial(jit, static_argnames=["method"])
518
+ def compute_h(k, omega_mesh, u_mesh, u_weights, molecule_mass, Boltz, Temp_0, viscosity_coef, density_0, space_scale, tol=1e-8, verbose = False, method = "SBGK"):
519
+
520
+
521
+ #N = 2000
522
+ #u_mesh = np.random.randn(N, 3)
523
+ #u_weights = np.zeros(N) + 1/N
524
+ #print("u_mesh", u_mesh.shape)
525
+ #print("u_weights", u_weights.shape)
526
+ #print("omega_mesh", omega_mesh.shape)
527
+
528
+
529
+ khat = (k/np.sqrt(denominator_reg(np.sum(k**2))))
530
+ h_values_Re = h_plus(u_mesh, k, omega_mesh)
531
+ h_values_Im = h_plus(u_mesh, k, omega_mesh)
532
+
533
+
534
+ Kn = (np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/space_scale)[0]
535
+
536
+
537
+
538
+
539
+
540
+ rhoRe = get_rhoRe(np.abs(k[0]), omega_mesh)
541
+ rhoIm = get_rhoIm(np.abs(k[0]), omega_mesh)
542
+ vRe = get_vRe(np.abs(k[0]), omega_mesh)
543
+ vIm = get_vIm(np.abs(k[0]), omega_mesh)
544
+ TRe = get_TRe(np.abs(k[0]), omega_mesh)
545
+ TIm = get_TIm(np.abs(k[0]), omega_mesh)
546
+
547
+ h_values_Re_ini_NS = (u_mesh[:,0:1]*0+rhoRe + np.sum( ( u_mesh[:,np.newaxis,:]*(vRe[:,np.newaxis]*khat) ) ,axis=-1) ) + (np.sum( u_mesh[:,np.newaxis,:]**2 ,axis=-1)/2 - 3/2)*TRe
548
+ h_values_Im_ini_NS = (u_mesh[:,0:1]*0+rhoIm + np.sum( ( u_mesh[:,np.newaxis,:]*(vIm[:,np.newaxis]*khat) ) ,axis=-1) ) + (np.sum( u_mesh[:,np.newaxis,:]**2 ,axis=-1)/2 - 3/2)*TIm
549
+ h_values_Re_ini_Asmp = Kn/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
550
+ h_values_Im_ini_Asmp = -Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)/(1+Kn**2*( u_mesh.dot(k)[...,None] + omega_mesh)**2)
551
+ less20 = k[0] < 20
552
+ h_values_Re = h_values_Re_ini_NS * less20 + (1 - less20) * h_values_Re_ini_Asmp
553
+ h_values_Im = h_values_Im_ini_NS * less20 + (1 - less20) * h_values_Im_ini_Asmp
554
+
555
+ '''
556
+ h_values_Re = np.zeros_like(h_values_Re_ini)
557
+ h_values_Im = np.zeros_like(h_values_Im_ini)
558
+ for i, omega in enumerate(omega_mesh):
559
+ nearest_index = np.argmin(np.abs(omega_mesh_ini - omega))
560
+ #print(len(h_values_Re_ini))
561
+ h_values_Re = h_values_Re.at[:,i].set(h_values_Re_ini[:,nearest_index])
562
+ h_values_Im = h_values_Im.at[:,i].set(h_values_Im_ini[:,nearest_index])
563
+ '''
564
+ # sBGK model
565
+
566
+ lamb = 1.0
567
+ stepI = 0.005
568
+ nite = 10000
569
+ reshist = []
570
+
571
+ h_flat = np.concatenate( (h_values_Re.reshape(-1) , h_values_Im.reshape(-1)) , axis = 0)
572
+ #print("h_flat", h_flat.shape)
573
+
574
+
575
+ '''
576
+ A = LinearOperator((len(h_flat),len(h_flat)), matvec=lambda x: mv(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re.shape))
577
+ from scipy.sparse.linalg import bicgstab, lgmres, tfqmr
578
+ x, exit_code = tfqmr(A, np.zeros_like(h_flat), atol=1e-15, x0 = h_flat, maxiter = 1000)
579
+ print("exit_code",exit_code)
580
+ print("residual", np.linalg.norm(A@x - np.zeros_like(h_flat)))
581
+ #x = spsolve(A, np.zeros_like(h_flat), maxiter = 1000)
582
+ h_values_Re = x[:len(x)//2].reshape(h_values_Re.shape)
583
+ h_values_Im = x[len(x)//2:].reshape(h_values_Im.shape)
584
+ '''
585
+ #h_ini = np.concatenate( (h_values_Re , h_values_Im) , axis = 0)
586
+ if method == "SBGK":
587
+ rescompute = lambda x: rescompute_mv(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re)
588
+ jac_rescompute = lambda x: grad_rescompute_mv(x, k, Kn, Pr, u_mesh, u_weights, omega_mesh, h_values_Re)
589
+ solver = jaxopt.LBFGS(fun=rescompute, maxiter=1000, tol=tol)
590
+ #solver = jaxopt.ScipyMinimize(fun=rescompute, method="L-BFGS-B", maxiter=1000, tol=tol)
591
+ x = solver.run(h_flat)[0]
592
+ #x = jax.scipy.optimize.minimize(rescompute,h_flat, tol=1e-3, options = {'maxiter': 1000}, method="BFGS").x
593
+ #if k[0] > 1 and k[0] < 200:
594
+ # x = jaxopt.ScipyMinimize(rescompute, h_flat, tol=tol, options = {"disp":False, 'maxiter': 1000}, method="L-BFGS-B").x
595
+ h_values_Re = x[:len(x)//2].reshape(h_values_Re.shape)
596
+ h_values_Im = x[len(x)//2:].reshape(h_values_Im.shape)
597
+
598
+
599
+ rho_spec_S = np.sum( 2*h_values_Re * u_weights[:,np.newaxis] ,axis = 0)
600
+ return h_values_Re, h_values_Im, rho_spec_S
601
+
602
+
603
+
604
+ def hermGauss(N):
605
+ gh_nodes, gh_weights = hermgauss(N) # integrate exp(- x^2)
606
+ gh_nodes, gh_weights = 2**0.5*gh_nodes, 2**0.5*gh_weights #https://en.wikipedia.org/wiki/Gauss%E2%80%93Hermite_quadrature # integrate exp(- x^2/2)
607
+ # Create the 3D mesh for \tilde{\mathbf{u}}
608
+ u_mesh_x, u_mesh_y, u_mesh_z = np.meshgrid(gh_nodes, gh_nodes, gh_nodes, indexing='ij')
609
+ u_weights_x, u_weights_y, u_weights_z = np.meshgrid(gh_weights, gh_weights, gh_weights, indexing='ij')
610
+
611
+ # Flatten the mesh and weights for vectorized operations
612
+ u_mesh = np.stack([u_mesh_x.ravel(), u_mesh_y.ravel(), u_mesh_z.ravel()], axis=-1)
613
+ u_weights = (1 / (2 * np.pi)**(3/2)) * np.prod(np.stack([u_weights_x.ravel(), u_weights_y.ravel(), u_weights_z.ravel()], axis=-1), axis=-1)
614
+ return u_mesh, u_weights
615
+
616
+ def monteCarlo(N):
617
+ u_mesh = np.random.randn(N, 3)
618
+ u_weights = np.zeros(N) + 1/N
619
+ return u_mesh, u_weights
620
+ from scipy.stats import qmc, norm
621
+
622
+ def quasiMonteCarlo(N):
623
+ # Initialize a Sobol sequence sampler for 3 dimensions
624
+ sampler = qmc.Sobol(d=3, scramble=True)
625
+
626
+ # Generate N quasi-random samples in the unit cube [0, 1]^3
627
+ sample = sampler.random(N)
628
+
629
+ # Transform the samples to follow a standard normal distribution
630
+ # by applying the inverse cumulative distribution function (CDF)
631
+ u_mesh = norm.ppf(sample)
632
+
633
+ # Assign equal weights to each sample
634
+ u_weights = np.full(N, 1/N)
635
+
636
+ return u_mesh, u_weights
637
+
638
+ def quasiMonteCarloGaussian(N):
639
+ sampler = qmc.MultivariateNormalQMC(mean=np.zeros(3), cov=np.eye(3))
640
+ sample = sampler.random(N)
641
+ u_weights = np.full(N, 1/N)
642
+ return sample, u_weights
643
+
644
+
645
+ # Example usage
646
+ Pr = 2/3
647
+ N = 2**14
648
+
649
+ #h_values_Res = []
650
+ #h_values_Ims = []
651
+ omegas = []
652
+ k_numbers = []
653
+ macro_values = []
654
+
655
+
656
+ amplitude = molecule_mass*num_effect/density_0
657
+
658
+ u_mesh, u_weights = quasiMonteCarloGaussian(N)
659
+
660
+
661
+ impulse = 1/(2*np.pi)**2/space_scale**3*amplitude
662
+
663
+
664
+
665
+ import tqdm
666
+ for k_val in tqdm.tqdm(k_traval[1900:1901]):
667
+
668
+ #k_val = k_traval[k_number]
669
+
670
+ k = np.array([k_val, 0, 0])
671
+ Kn = (np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/space_scale)[0]
672
+ eps = 1e-1
673
+ peakwidth_NS = (15*(k_val + eps)**2*Kn)/(4*(1+5*(k_val + eps)**2*Kn**2))
674
+ peakwidth_Asympt = np.exp(-(1/(2*k_val**2*Kn**2)))*k_val*np.sqrt(2/np.pi)
675
+ peakwidth = np.maximum(peakwidth_NS, peakwidth_Asympt)
676
+ domainwidth = 10*abs( (k_val + eps) )
677
+ number_of_points = int(20*domainwidth/peakwidth)//2 + 1
678
+ #print("number_of_points", number_of_points)
679
+ omega_mesh = np.linspace(-domainwidth/2, domainwidth/2, number_of_points)
680
+
681
+ rhoRe = get_rhoRe(np.abs(k[0]), omega_mesh)
682
+
683
+ omega_plt = omega_mesh/(denominator_reg(k[0])*(5/3)**0.5)
684
+
685
+
686
+
687
+
688
+
689
+
690
+ #for N in [9,10, 11, 12]:
691
+ #for N in [9,10, 11, 12]:
692
+
693
+ #h_values_Re, h_values_Im, rho_spec_S = compute_h(k,omega_mesh, *hermGauss(N), verbose = True)
694
+ if k_val < 1 or k_val > 200:
695
+ optmethod = "Theory"
696
+ else:
697
+ optmethod = "SBGK"
698
+ h_values_Re, h_values_Im, rho_spec_S = compute_h(k,omega_mesh, u_mesh, u_weights, molecule_mass, Boltz, Temp_0, viscosity_coef, density_0, space_scale, tol = 1e-8, verbose = True, method = optmethod)
699
+
700
+
701
+ n_plus_result_Re = compute_n_plus(k, h_values_Re, u_mesh, u_weights)
702
+ n_plus_result_Im = compute_n_plus(k, h_values_Im, u_mesh, u_weights)
703
+
704
+ v_plus_result_Re = compute_v_plus(k, h_values_Re, u_mesh, u_weights)
705
+ v_plus_result_Im = compute_v_plus(k, h_values_Im, u_mesh, u_weights)
706
+
707
+ T_plus_result_Re = compute_T_plus(k, h_values_Re, u_mesh, u_weights) - n_plus_result_Re
708
+ T_plus_result_Im = compute_T_plus(k, h_values_Im, u_mesh, u_weights) - n_plus_result_Im
709
+
710
+ sigma_plus_result_Re = compute_sigma_plus(k, h_values_Re, u_mesh, u_weights)
711
+ sigma_plus_result_Im = compute_sigma_plus(k, h_values_Im, u_mesh, u_weights)
712
+
713
+ q_plus_result_Re = compute_q_plus(k, h_values_Re, u_mesh, u_weights) - 5/2*v_plus_result_Re
714
+ q_plus_result_Im = compute_q_plus(k, h_values_Im, u_mesh, u_weights) - 5/2*v_plus_result_Im
715
+
716
+ current_result = (omega_mesh, n_plus_result_Re, n_plus_result_Im, v_plus_result_Re, v_plus_result_Im, T_plus_result_Re, T_plus_result_Im )
717
+
718
+ macro_values.append(current_result)
719
+ # append the current_result to a file
720
+ jax.clear_caches()
721
+
722
+
723
+ #h_values_Res.append(h_values_Re)
724
+ #h_values_Ims.append(h_values_Im)
725
+
726
+ #plt.plot( omega_plt, impulse*2*rhoRe, label = "NS")
727
+ #plt.plot( omega_plt, impulse*rho_spec_S, label = "N = "+str(N) )
728
+ #plt.xlim(-2*peakwidth /(denominator_reg(k[0])*(5/3)**0.5), 2*peakwidth /(denominator_reg(k[0])*(5/3)**0.5) )
729
+ #plt.legend()
730
+ #plt.show()
731
+
732
+
733
+
734
+ # save the macro values results
735
+ import pickle
736
+
737
+ #save_data = { "values": macro_values , "k": k_traval, "omega": omega_mesh }
738
+ #with open("Boltzmann3_macro_values_Adapt_FullExp.pkl", "wb") as f:
739
+ # pickle.dump(save_data, f)
740
+
741
+ # load the macro values results
742
+ #"Boltzmann3_macro_values_500.pkl"
743
+
744
+ def denominator_reg(denominator):
745
+ sign = 1-2*(denominator < 0)
746
+ return sign*np.maximum(np.abs(denominator), 1e-10)
747
+
748
+
749
+ with open("Boltzmann3_macro_values_Adapt_FullExp.pkl", "rb") as f:
750
+ save_data = pickle.load(f)
751
+ macro_values = save_data["values"]
752
+ k_traval = save_data["k"]
753
+ omega_mesh = save_data["omega"]
754
+
755
+ def bump_fourier(a, k, b):
756
+ result1 = 1/(2*np.sqrt(2)*np.pi**(3/2))-(a**2*k**2)/(20*(np.sqrt(2)*np.pi**(3/2)))
757
+
758
+ k = denominator_reg(k)
759
+ coefficient = 3/(2*np.sqrt(2)*np.pi**(3/2))
760
+ numerator = -a * k * np.cos(a * k) + np.sin(a * k)
761
+ denominator = a**3 * k**3
762
+ exponential = np.exp(-k**2 * b**2 / 2)
763
+ result2 = (coefficient * numerator / denominator) * exponential
764
+ mask = np.abs(k) < 5e-1
765
+ result = result1*exponential*mask + result2*(1-mask)
766
+ return result
767
+
768
+
769
+ #!/usr/bin/env python
770
+
771
+ import numpy as nnp
772
+ from scipy.special import gamma, spherical_jn
773
+ from scipy.fft import ifft, rfft, irfft
774
+
775
+ # usefull constants
776
+ PI = nnp.pi
777
+ TPI = 2.0 * nnp.pi
778
+ II = 1.0j
779
+
780
+ class pyNumSBT(object):
781
+ '''
782
+ Numerically perform spherical Bessel transform (SBT) in O(Nln(N)) time based
783
+ on the algorithm proposed by J. Talman.
784
+
785
+ Talman, J. Computer Physics Communications 2009, 180, 332-338.
786
+
787
+ For a function "f(r)" defined numerically on a LOGARITHMIC radial grid "r",
788
+ the SBT for the function gives
789
+
790
+ g(k) = \sqrt{2\over\pi} \int_0^\infty j_l(kr) f(r) r^2 dr (c1)
791
+
792
+ and the inverse SBT (iSBT) gives
793
+
794
+ f(r) = \sqrt{2\over\pi} \int_0^\infty j_l(kr) g(k) k^2 dk (c2)
795
+ '''
796
+
797
+ def __init__(self, rr, kmax: float=500, lmax: int=10):
798
+ '''
799
+ Init
800
+ '''
801
+
802
+ self.rr = nnp.asarray(rr, dtype=float) # the real-space logarithmic radial grid
803
+ self.nr = self.rr.size # No. of grid points
804
+ self.nr2 = 2 * self.nr
805
+ self.sbt_init(rr, kmax)
806
+
807
+ self.lmax = lmax
808
+ self.sbt_mltb(self.lmax)
809
+
810
+ def sbt_init(self, rr, kmax: float):
811
+ '''
812
+ Initialize the real-space grid (rr) and momentum-space grid (kk).
813
+
814
+ \rho = \ln(rr)
815
+ \kappa = \ln(kk)
816
+
817
+ The algorithm by Talman requries
818
+
819
+ \Delta\kappa = \Delta\rho
820
+ '''
821
+
822
+ self.r_min = rr[0]
823
+ self.r_max = rr[-1]
824
+
825
+ self.rho_min = nnp.log(self.r_min)
826
+ self.rho_max = nnp.log(self.r_max)
827
+ # \Delta\rho = \ln(rr[1] - rr[0])
828
+ self.drho = (self.rho_max - self.rho_min) / (self.nr - 1)
829
+
830
+ self.kappa_max = nnp.log(kmax)
831
+ self.kappa_min = self.kappa_max - (self.rho_max - self.rho_min)
832
+
833
+ # the reciprocal-space (momentum-space) logarithmic grid
834
+ self.kk = nnp.exp(self.kappa_min) * nnp.exp(nnp.arange(self.nr)*self.drho)
835
+ self.k_min = self.kk[0]
836
+ self.k_max = self.kk[-1]
837
+
838
+ self.rr3 = self.rr**3
839
+ self.kk3 = self.kk**3
840
+
841
+ # r values for the extended mesh as discussed in Sec.4 of Talman paper.
842
+ self.rr_ext = self.r_min * nnp.exp(nnp.arange(-self.nr, 0) * self.drho)
843
+
844
+ # the multiply factor as in Talman paper after Eq.(32)
845
+ self.rr15 = nnp.zeros((2, self.nr), dtype=float)
846
+ self.rr15[0] = self.rr_ext**1.5 / self.r_min**1.5 # the extended r-mesh
847
+ self.rr15[1] = self.rr**1.5 / self.r_min**1.5 # the normal r-mesh
848
+
849
+ # \Delta\rho \times \Delta t = \frac{2\pi}{N}
850
+ # as in Talman paper after Eq.(30), where N = 2 * nr as discussed in
851
+ # Sec. 4
852
+ self.dt = TPI / (self.nr2 * self.drho)
853
+
854
+ # the post-division factor (1 / k^1.5) as in Eq. (32) of Talman paper.
855
+ # Note that the factor is (1 / r^1.5) for inverse-SBT, as a result, we
856
+ # omit the r_min^1.5 / k_min^1.5 here.
857
+ self.post_div_fac = nnp.exp(-nnp.arange(self.nr)*self.drho*1.5)
858
+
859
+ # Simpson integration of a function on the logarithmic radial grid.
860
+ #
861
+ # Setup weights for simpson integration on radial grid any radial integral
862
+ # can then be evaluated by just summing all radial grid points with the
863
+ # weights SI
864
+ #
865
+ # \int dr = \sum_i w(i) * f(i)
866
+ self.simp_wht_rr = nnp.zeros_like(self.rr)
867
+ self.simp_wht_kk = nnp.zeros_like(self.kk)
868
+ for ii in range(self.nr-1, 1, -2):
869
+ self.simp_wht_rr[ii] = self.drho * self.rr[ii] / 3. \
870
+ + self.simp_wht_rr[ii]
871
+ self.simp_wht_rr[ii-1] = self.drho * self.rr[ii-1] * 4. / 3.
872
+ self.simp_wht_rr[ii-2] = self.drho * self.rr[ii-2] / 3.
873
+
874
+ self.simp_wht_kk[ii] = self.drho * self.kk[ii] / 3. \
875
+ + self.simp_wht_kk[ii]
876
+ self.simp_wht_kk[ii-1] = self.drho * self.kk[ii-1] * 4. / 3.
877
+ self.simp_wht_kk[ii-2] = self.drho * self.kk[ii-2] / 3.
878
+
879
+ def sbt_mltb(self, lmax_in: int):
880
+ '''
881
+ construct the M_l(t) table according to Eq. (15), (16) and (24) of
882
+ Talman paper.
883
+
884
+ Note that Talman paper use Stirling's approximaton to evaluate the Gamma
885
+ function, whereas I just call scipy.special.gamma here.
886
+ '''
887
+
888
+ if lmax_in > self.lmax:
889
+ lmax = lmax_in
890
+ self.lmax = lmax
891
+ else:
892
+ lmax = self.lmax
893
+
894
+ tt = nnp.arange(self.nr) * self.dt
895
+
896
+ # M_lt1 is quantity defined by Eq. (12)
897
+ self.M_lt1 = nnp.zeros((lmax+1, self.nr), dtype=complex)
898
+
899
+ # Eq. (15) in Talman paper
900
+ # self.M_lt1[0] = gamma(0.5 - II*tt) * nnp.sin(0.5*PI*(0.5 - II*tt)) / self.nr
901
+
902
+ # Eq. (19) and Eq. (15) in Talman paper are equivalent, while the former
903
+ # is more stable for larger tt
904
+ self.M_lt1[0] = nnp.sqrt(nnp.pi / 2) * nnp.exp(
905
+ II * (
906
+ nnp.log(gamma(0.5 - II*tt)).imag
907
+ # + nnp.log(nnp.sin(0.5*PI*(0.5 - II*tt))).imag
908
+ - nnp.arctan(nnp.tanh(PI*tt/2))
909
+ )
910
+ ) / self.nr
911
+
912
+ self.M_lt1[0,0] /= 2.0
913
+ self.M_lt1[0] *= nnp.exp(II*tt*(self.kappa_min + self.rho_min))
914
+
915
+ # Eq. (16) in Talman paper
916
+ phi = nnp.arctan(nnp.tanh(PI*tt/2)) - nnp.arctan(2*tt)
917
+ self.M_lt1[1] = self.M_lt1[0] * nnp.exp(2*II*phi)
918
+
919
+ # Eq. (24) in Talman paper
920
+ for ll in range(1, lmax):
921
+ phi_l = nnp.arctan(2*tt / (2*ll + 1))
922
+ self.M_lt1[ll+1] = nnp.exp(-2*II*phi_l) * self.M_lt1[ll-1]
923
+
924
+ ll = nnp.arange(lmax+1)
925
+ # Eq. (35) in Talman paper
926
+ xx = nnp.exp(self.rho_min + self.kappa_min + nnp.arange(self.nr2)*self.drho)
927
+
928
+ # M_lt2 is just the Fourier transform of spherical Bessel function j_l
929
+ self.M_lt2 = ifft(
930
+ spherical_jn(ll[:,None], xx[None,:]),
931
+ axis=1
932
+ ).conj()[:,:self.nr+1]
933
+
934
+
935
+ def run(self,
936
+ ff,
937
+ l: int=0,
938
+ direction: int = 1,
939
+ norm: bool=False,
940
+ np_in: int =0,
941
+ return_rr: bool=False,
942
+ include_zero: bool=False,
943
+ ):
944
+ '''
945
+ Perform SBT or inverse-SBT.
946
+
947
+ Input parapeters:
948
+ ff: the function defined on the logarithmic radial grid
949
+ l: the "l" as in the underscript of "j_l(kr)" of Eq. (c1) and (c2)
950
+ direction: 1 for forward SBT and -1 for inverse SBT
951
+ norm: whether to multiply the prefactor \sqrt{2\over\pi} in Eq. (c1) and (c2).
952
+ If False, then subsequent applicaton of SBT and iSBT will yield
953
+ the original data scaled by a factor of 2/pi.
954
+ np_in: the asymptotic bahavior of ff when r -> 0
955
+
956
+ ff(r\to 0) \approx r^{np_in + l}
957
+ include_zero: the SBT does not include the k = 0, i.e. self.kk.min() != 0, term by default.
958
+ '''
959
+
960
+ assert l <= self.lmax, \
961
+ "lmax = {} smaller than l = {}! Increase lmax!".format(self.lmax, l)
962
+
963
+
964
+ ff = nnp.asarray(ff, dtype=float)
965
+ gg = nnp.zeros_like(ff)
966
+
967
+ r2c_in = nnp.zeros(self.nr2, dtype=float)
968
+ r2c_out = nnp.zeros(self.nr + 1, dtype=complex)
969
+
970
+ c2r_in = nnp.zeros(self.nr + 1, dtype=complex)
971
+ c2r_out = nnp.zeros(self.nr2, dtype=float)
972
+
973
+ # The prefactor as in Eq. (c1) and (c2) of the Class docstring.
974
+ sqrt_2_over_pi = nnp.sqrt(2 / PI) if norm else 1.0
975
+
976
+ if direction == 1:
977
+ rmin = self.r_min
978
+ kmin = self.k_min
979
+ C = ff[0] / self.r_min**(np_in + l)
980
+ elif direction == -1:
981
+ rmin = self.k_min
982
+ kmin = self.r_min
983
+ C = ff[0] / self.k_min**(np_in + l)
984
+ else:
985
+ raise ValueError("Use direction=1/-1 for forward- and inverse-SBT!")
986
+
987
+ # SBT for LARGE k values extend the input to the doubled mesh,
988
+ # extrapolating the input as C r^(np_in + l)
989
+
990
+ # Step 1 in the procedure after Eq. (32) of Talman paper
991
+ r2c_in[:self.nr] = C * self.rr_ext**(np_in + l) * self.rr15[0]
992
+ r2c_in[self.nr:] = ff * self.rr15[1]
993
+
994
+ # Step 2 in the procedure after Eq. (32) of Talman paper
995
+ r2c_out = rfft(r2c_in)
996
+
997
+ # Step 3 in the procedure after Eq. (32) of Talman paper
998
+ tmp1 = nnp.zeros(self.nr2, dtype=complex)
999
+ tmp1[:self.nr] = r2c_out[:self.nr].conj() * self.M_lt1[l]
1000
+
1001
+ # Step 4 and 5 in the procedure after Eq. (32) of Talman paper
1002
+ tmp2 = ifft(tmp1) * self.nr2
1003
+ gg = (rmin / kmin)**1.5 * tmp2[self.nr:].real * self.post_div_fac * sqrt_2_over_pi
1004
+
1005
+ # obtain the SMALL k results in the array c2r_out
1006
+
1007
+ if direction == 1:
1008
+ r2c_in[:self.nr] = self.rr3 * ff
1009
+ else:
1010
+ r2c_in[:self.nr] = self.kk3 * ff
1011
+ r2c_in[self.nr:] = 0.0
1012
+ r2c_out = rfft(r2c_in)
1013
+
1014
+ c2r_in = r2c_out.conj() * self.M_lt2[l] * sqrt_2_over_pi
1015
+ c2r_out = irfft(c2r_in) * self.nr2
1016
+ c2r_out[:self.nr] *= self.drho
1017
+
1018
+ # compare the minimum difference between large and small k as described
1019
+ # in the paragraph above Eq. (39) of Talman paper.
1020
+ gdiff = nnp.abs(gg - c2r_out[:self.nr])
1021
+ minloc = nnp.argmin(gdiff)
1022
+ gg[:minloc+1] = c2r_out[:minloc+1]
1023
+
1024
+ # include k = 0 in the SBT and r = 0 in the i-SBT.
1025
+ if include_zero:
1026
+ if direction == 1:
1027
+ gg0 = sqrt_2_over_pi * spherical_jn(l, 0) * nnp.sum(
1028
+ self.simp_wht_rr * self.rr**2 * ff
1029
+ )
1030
+ else:
1031
+ gg0 = sqrt_2_over_pi * spherical_jn(l, 0) * nnp.sum(
1032
+ self.simp_wht_kk * self.kk**2 * ff
1033
+ )
1034
+
1035
+ if return_rr:
1036
+ if direction == 1:
1037
+ return (nnp.r_[0, self.kk], nnp.r_[gg0, gg]) if include_zero else (self.kk, gg)
1038
+ else:
1039
+ return (nnp.r_[0, self.rr], nnp.r_[gg0, gg]) if include_zero else (self.rr, gg)
1040
+ else:
1041
+ return nnp.r_[gg0, gg] if include_zero else gg
1042
+
1043
+
1044
+ def run_int(self,
1045
+ ff,
1046
+ l: int=0,
1047
+ direction: int = 1,
1048
+ norm: bool=False,
1049
+ return_rr: bool=False,
1050
+ include_zero: bool=False,
1051
+ ):
1052
+ '''
1053
+ Perform SBT or inverse-SBT by numerically integrating Eq. (c1) and (c2).
1054
+
1055
+ Input parapeters:
1056
+ ff: the function defined on the logarithmic radial grid
1057
+ l: the "l" as in the underscript of "j_l(kr)" of Eq. (c1) and (c2)
1058
+ direction: 1 for forward SBT and -1 for inverse SBT
1059
+ norm: whether to multiply the prefactor \sqrt{2\over\pi} in Eq. (c1) and (c2).
1060
+ If False, then subsequent applicaton of SBT and iSBT will yield
1061
+ the original data scaled by a factor of 2/pi.
1062
+ include_zero: the SBT does not include the k = 0, i.e. self.kk.min() != 0, term by default.
1063
+ '''
1064
+
1065
+ kr = self.rr[:,None] * self.kk[None,:]
1066
+ jl_kr = spherical_jn(l, kr)
1067
+ ff = nnp.asarray(ff, dtype=float)
1068
+
1069
+ # The prefactor as in Eq. (c1) and (c2) of the Class docstring.
1070
+ sqrt_2_over_pi = nnp.sqrt(2 / PI) if norm else 1.0
1071
+
1072
+ if direction == 1:
1073
+ gg = sqrt_2_over_pi * nnp.sum(
1074
+ jl_kr * (self.rr**2 * ff * self.simp_wht_rr)[:,None],
1075
+ axis=0
1076
+ )
1077
+ # include k = 0 in the SBT and r = 0 in the i-SBT.
1078
+ if include_zero:
1079
+ gg0 = sqrt_2_over_pi * spherical_jn(l, 0) * nnp.sum(
1080
+ self.simp_wht_rr * self.rr**2 * ff
1081
+ )
1082
+ elif direction == -1:
1083
+ gg = sqrt_2_over_pi * nnp.sum(
1084
+ jl_kr * (self.kk**2 * ff * self.simp_wht_kk)[None,:],
1085
+ axis=1
1086
+ )
1087
+ # include k = 0 in the SBT and r = 0 in the i-SBT.
1088
+ if include_zero:
1089
+ gg0 = sqrt_2_over_pi * spherical_jn(l, 0) * nnp.sum(
1090
+ self.simp_wht_kk * self.kk**2 * ff
1091
+ )
1092
+ else:
1093
+ raise ValueError("Use direction=1/-1 for forward- and inverse-SBT!")
1094
+
1095
+ if return_rr:
1096
+ if direction == 1:
1097
+ return (nnp.r_[0, self.kk], nnp.r_[gg0, gg]) if include_zero else (self.kk, gg)
1098
+ else:
1099
+ return (nnp.r_[0, self.rr], nnp.r_[gg0, gg]) if include_zero else (self.rr, gg)
1100
+ else:
1101
+ return nnp.r_[gg0, gg] if include_zero else gg
1102
+
1103
+
1104
+
1105
+ N = 256
1106
+ rmin = 2.0 / 1024 / 32
1107
+ rmax = 30
1108
+ rr = nnp.logspace(nnp.log10(rmin), nnp.log10(rmax), N, endpoint=True)
1109
+ f1 = 2*nnp.exp(-rr)
1110
+
1111
+ xx = pyNumSBT(rr)
1112
+
1113
+ g1 = xx.run(f1, direction=1, norm=False)
1114
+ f2 = xx.run(g1 * g1, direction=-1, norm=False)
1115
+
1116
+
1117
+ import matplotlib.pyplot as plt
1118
+
1119
+ # fig = plt.figure(
1120
+ # dpi=100,
1121
+ # )
1122
+ # ax = plt.subplot()
1123
+
1124
+ # # ax.plot(rr, f1)
1125
+ # ax.plot(rr, f2 * 2 / nnp.pi, ls='-')
1126
+ # ax.plot(rr, nnp.exp(-rr) * (1 + rr + rr**2 / 3), ls='--')
1127
+
1128
+ # ax.set_xlabel('X-label', labelpad=5)
1129
+ # ax.set_ylabel('Y-label', labelpad=5)
1130
+
1131
+ # plt.tight_layout()
1132
+ # plt.show()
1133
+
1134
+ from scipy.interpolate import krogh_interpolate
1135
+ n_plus_resoult_Re_fines = []
1136
+ v_plus_result_Re_fines = []
1137
+ T_plus_result_Re_fines = []
1138
+ omega_mesh = np.linspace(-5* 50 - 1e-6, 5*50 + 1e-6, 10419)
1139
+ for i in range(len(macro_values)):
1140
+ omega_mesh_data = macro_values[i][0]
1141
+ n_plus_resoult_Re = macro_values[i][1][...,0]
1142
+ v_plus_result_Re = macro_values[i][3][...,0]
1143
+ T_plus_result_Re = macro_values[i][5][...,0]
1144
+
1145
+ # interpolate the data
1146
+ n_plus_resoult_Re_fine = np.interp(omega_mesh, omega_mesh_data, n_plus_resoult_Re, left = 0, right = 0)
1147
+ v_plus_result_Re_fine = np.interp(omega_mesh, omega_mesh_data, v_plus_result_Re, left = 0, right = 0)
1148
+ T_plus_result_Re_fine = np.interp(omega_mesh, omega_mesh_data, T_plus_result_Re, left = 0, right = 0)
1149
+ # interpolate the data using the
1150
+ n_plus_resoult_Re_fines.append(n_plus_resoult_Re_fine)
1151
+ v_plus_result_Re_fines.append(v_plus_result_Re_fine)
1152
+ T_plus_result_Re_fines.append(T_plus_result_Re_fine)
1153
+
1154
+ n_plus_resoult_Re_fines = np.array(n_plus_resoult_Re_fines)
1155
+ v_plus_result_Re_fines = np.array(v_plus_result_Re_fines)
1156
+ T_plus_result_Re_fines = np.array(T_plus_result_Re_fines)
1157
+
1158
+
1159
+ kk = np.logspace(-2, 2.79817986094985, 2048, endpoint=True)
1160
+ rho0k = np.array( [ bump_fourier(1, kvalue, 1) for kvalue in kk] )
1161
+ SBT = pyNumSBT(kk.__array__())
1162
+ # plt.plot( kk,rho0k, label = "NS")
1163
+ # plt.show()
1164
+ # g1 = SBT.run(rho0k.__array__(), direction=1, norm=True)
1165
+ # plt.plot( SBT.kk, g1)
1166
+ # plt.xlim(0, 10)
1167
+ # plt.show()
1168
+ # f1 = SBT.run(g1.__array__(), direction=-1, norm=True)
1169
+ # plt.plot( kk, f1 )
1170
+ # plt.plot( kk, rho0k, linestyle = "dotted")
1171
+
1172
+ # plt.xlim(0, 10)
1173
+ # plt.show()
1174
+
1175
+
1176
+
1177
+
1178
+ # Compute delta_rho(k) from delta_rho(r) (Forward Transform)
1179
+ def forward_transform(delta_rho_r, r, k):
1180
+ # Compute kr matrix
1181
+ kr = np.outer(k, r) # Shape: (N_k, N_r)
1182
+
1183
+ # Compute the sine of kr
1184
+ sin_kr = np.sinc(kr / np.pi)
1185
+
1186
+ # Compute the integrand
1187
+ integrand = delta_rho_r * r**2 * sin_kr # Broadcasting over r
1188
+
1189
+ # Compute the integral over r for each k
1190
+ integral = np.trapezoid(integrand, x=r, axis=1) # Shape: (N_k,)
1191
+
1192
+ # Compute the prefactor
1193
+ prefactor = (4 * np.pi) / ((2 * np.pi) ** 1.5 * np.ones_like(k))
1194
+
1195
+ # Compute delta_rho(k)
1196
+ delta_rho_k = prefactor * integral
1197
+
1198
+ return delta_rho_k
1199
+
1200
+
1201
+
1202
+ # Compute delta_rho(r) from delta_rho(k) (Inverse Transform)
1203
+ def inverse_transform(delta_rho_k, k, r):
1204
+ # Compute kr matrix
1205
+ kr = np.outer(r, k) # Shape: (N_r, N_k)
1206
+
1207
+ # Compute the sine of kr
1208
+ sin_kr = np.sinc(kr / np.pi)
1209
+
1210
+ # Compute the integrand
1211
+ integrand = delta_rho_k * k**2 * sin_kr # Broadcasting over k
1212
+
1213
+ # Compute the integral over k for each r
1214
+ integral = np.trapezoid(integrand, x=k, axis=1) # Shape: (N_r,)
1215
+
1216
+ # Compute the prefactor
1217
+ prefactor = (4 * np.pi) / ((2 * np.pi) ** 1.5 * np.ones_like(r) )
1218
+
1219
+
1220
+ # Compute delta_rho(r)
1221
+ delta_rho_r_rec = prefactor * integral
1222
+
1223
+ return delta_rho_r_rec
1224
+
1225
+ rho0k = np.array( [ bump_fourier(2, kvalue, 100) for kvalue in k_traval] )
1226
+ import torch
1227
+ import torch.nn as nn
1228
+ import numpy as nnp
1229
+ device = "cpu"
1230
+ dtype = torch.float
1231
+ sNet= torch.load("./DSMC3ModelsExp/DSMC3LearnModelFull6.pt", weights_only=False, map_location=torch.device('cpu'))
1232
+ #sNet.load_state_dict(torch.load("./DSMC3ModelsV/DSMC3LearnModelN250", map_location=torch.device('cpu')))
1233
+ sNet.eval()
1234
+ kTest = 5
1235
+ with torch.no_grad():
1236
+ net_spectra, net_spectra_omega, _, _, _, _, _ = sNet(torch.tensor( nnp.array( kTest ), device = device, dtype = dtype), torch.tensor( nnp.array(omega_mesh[None,:]/(kTest *(5/3)**0.5) ), device = device, dtype = dtype))
1237
+ net_spectra = net_spectra.cpu().numpy()
1238
+ net_spectra_omega = net_spectra_omega.cpu().numpy()
1239
+
1240
+ # plt.plot( omega_mesh, 2*get_rhoRe(kTest , omega_mesh), label = "NS", linewidth = 2)
1241
+ # plt.plot(omega_mesh, net_spectra[0]/impulse, label = "NN")
1242
+ # plt.legend()
1243
+ # plt.show()
1244
+ #k_traval = np.linspace( 0, 30, 200 )
1245
+ # suppress the outbound omega spectra by a Gaussian filter in omega space
1246
+ #omega_fft_range = np.max( np.abs(omega_mesh) )
1247
+ #fft_omega_filter = np.exp( - (omega_mesh)**2 / (2 * (omega_fft_range/2)**2) )
1248
+
1249
+ rho_k_omega_Bol3_re = 2*n_plus_resoult_Re_fines#*fft_omega_filter
1250
+ rho_k_omega_NS_re = np.array([2*get_rhoRe(k_traval[i], omega_mesh) for i in range(len(k_traval))])#*fft_omega_filter
1251
+ #rho_k_omega_Bol3_re = rho_k_omega_Bol3_re.at[k_traval < 1].set(rho_k_omega_NS_re[k_traval < 1])
1252
+ rho_k_omega_Learn_re = []
1253
+
1254
+
1255
+ #rho_k_omega_Learn_re[0] = 2*get_rhoRe(k_traval[0], omega_mesh)
1256
+
1257
+
1258
+ v_plus_k_omega_Bol3_re = 2*v_plus_result_Re_fines#*fft_omega_filter
1259
+ v_plus_k_omega_NS_re = np.array([2*get_vRe(k_traval[i], omega_mesh) for i in range(len(k_traval))])#*fft_omega_filter
1260
+ #v_plus_k_omega_Bol3_re = v_plus_k_omega_Bol3_re.at[k_traval < 1].set(v_plus_k_omega_NS_re[k_traval < 1])
1261
+
1262
+ T_plus_k_omega_Bol3_re = 2*T_plus_result_Re_fines#*fft_omega_filter
1263
+ T_plus_k_omega_NS_re = np.array([2*get_TRe(k_traval[i], omega_mesh) for i in range(len(k_traval))])#*fft_omega_filter
1264
+ T_plus_k_omega_Learn_re = []
1265
+ for kTest in k_traval:
1266
+ with torch.no_grad():
1267
+ net_spectra, net_spectra_omega, _, rhoSpec, vSpec, TSpec, _ = sNet(torch.tensor( nnp.array( kTest ), device = device, dtype = dtype), torch.tensor( nnp.array(omega_mesh[None,:]/(kTest *(5/3)**0.5) ), device = device, dtype = dtype))
1268
+ net_spectra = net_spectra.cpu().numpy()
1269
+ net_spectra_omega = net_spectra_omega.cpu().numpy()
1270
+ rho_k_omega_Learn_re.append( rhoSpec[0].cpu().numpy()/impulse )
1271
+ T_plus_k_omega_Learn_re.append( TSpec[0].cpu().numpy()/impulse )
1272
+ rho_k_omega_Learn_re = np.array(rho_k_omega_Learn_re)#*fft_omega_filter
1273
+ T_plus_k_omega_Learn_re = np.array(T_plus_k_omega_Learn_re)#*fft_omega_filter
1274
+
1275
+
1276
+
1277
+
1278
+ #T_plus_k_omega_Bol3_re = T_plus_k_omega_Bol3_re.at[k_traval < 1].set(T_plus_k_omega_NS_re[k_traval < 1])
1279
+
1280
+
1281
+ #for i in range(20,25):
1282
+ #plt.plot( rho_k_omega_Bol3_re[i], label = "Bol3")
1283
+ #plt.plot( rho_k_omega_NS_re[i], label = "NS")
1284
+ #plt.legend()
1285
+ #plt.show()
1286
+ # rho_k_omega_Bol3_re = rho_k_omega_Bol3_re.at[i].set(rho_k_omega_NS_re[i])
1287
+ #
1288
+
1289
+ # plt.plot( omega_mesh, rho_k_omega_Bol3_re[100], linewidth = 3, label = "Bol3")
1290
+ # plt.plot( omega_mesh, rho_k_omega_NS_re[100], label = "NS", linewidth = 1)
1291
+ # plt.plot( omega_mesh, rho_k_omega_Learn_re[100], label = "Learn", linewidth = 0.5)
1292
+ # plt.xlim(-30,30)
1293
+ # plt.legend()
1294
+ # plt.show()
1295
+
1296
+ rho0k = np.array( [ bump_fourier(0.5, kvalue, 0.02) for kvalue in k_traval] )
1297
+ v0k = np.zeros_like(rho0k)
1298
+ T0k = np.zeros_like(rho0k)
1299
+ # plt.plot( k_traval,rho0k, label = "NS")
1300
+
1301
+ # plt.show()
1302
+ time_travel = 2*np.pi*np.fft.fftfreq(len(omega_mesh), d = omega_mesh[1] - omega_mesh[0])
1303
+ SBT = pyNumSBT(k_traval.__array__())
1304
+ r_travel = SBT.kk
1305
+ rho0x = SBT.run(rho0k.__array__(), direction=1, norm=True)
1306
+ # plt.plot( r_travel, rho0x)
1307
+ # plt.xlim(0,2)
1308
+ # plt.show()
1309
+ '''
1310
+ r_travel = np.linspace( 0, np.pi/(k_traval[1] - k_traval[0]), len(k_traval) )
1311
+
1312
+ rho0x = inverse_transform(rho0k, k_traval, r_travel)
1313
+ plt.plot( r_travel, rho0x)
1314
+ plt.xlim(0,2)
1315
+ plt.show()
1316
+ '''
1317
+
1318
+ wavelength = 2*np.pi/k_traval*space_scale
1319
+ Kn_number = viscosity_coef/(density_0*wavelength)/np.sqrt(Boltz*Temp_0/molecule_mass)
1320
+ #rho_k_omega_re = np.array([compute_n_plus( None, 2*h_values_Res[i], u_mesh, u_weights)[...,0] for i in range(len(k_traval))])
1321
+
1322
+ #rho_k_omega_re = rho_k_omega_re.at[0].set(2*get_rhoRe(5e-2, omega_mesh))
1323
+ #plt.plot( omega_plt, rho_k_omega_re[0], label = "NS")
1324
+ #rhoRe = get_rhoRe(k_titla_freq[0], omega_mesh)
1325
+ #plt.plot(omega_plt,2*rhoRe)
1326
+ #plt.show()
1327
+ #plt.show()
1328
+ def time_evolution(rho_k_omega_re, rho0k, k_traval, omega_mesh):
1329
+ #print( rho0k )
1330
+ rho_k_omega_re = rho_k_omega_re * rho0k[:,np.newaxis] /(2*np.pi)**0.5
1331
+ rho_k_t = np.real( np.fft.ifft( np.fft.fftshift( rho_k_omega_re[:,:-1] , axes=-1) , axis = -1) ) / (2*np.pi)**0.5 * ( (omega_mesh[1] - omega_mesh[0]) * len(omega_mesh) )
1332
+ rho_k_values = k_traval
1333
+ SBT = pyNumSBT(k_traval.__array__())
1334
+ x_travel = SBT.kk
1335
+ #x_travel = np.linspace(0, np.pi/(k_traval[1] - k_traval[0]), len(k_traval) )
1336
+ rho_x_t = np.array( [SBT.run(rho_k_t[:,i].__array__(), direction=1, norm=True) for i in range( rho_k_t.shape[1] ) ] ).T
1337
+ #rho_x_t = np.array( [ inverse_transform(rho_k_t[:,i], k_traval, x_travel) for i in range( rho_k_t.shape[1] ) ] ).T
1338
+ time_travel = 2*np.pi*np.fft.fftfreq(len(omega_mesh), d = omega_mesh[1] - omega_mesh[0])
1339
+ return x_travel, time_travel, rho_x_t
1340
+
1341
+ x_travel, time_travel, rho_x_t_NS = time_evolution(rho_k_omega_NS_re, rho0k, k_traval, omega_mesh)
1342
+ x_travel, time_travel, rho_x_t_Bol3 = time_evolution(rho_k_omega_Bol3_re, rho0k, k_traval, omega_mesh)
1343
+ x_travel, time_travel, rho_x_t_Learn = time_evolution(rho_k_omega_Learn_re, rho0k, k_traval, omega_mesh)
1344
+
1345
+ x_travel, time_travel, v_x_t_NS = time_evolution(v_plus_k_omega_NS_re, rho0k, k_traval, omega_mesh)
1346
+ x_travel, time_travel, v_x_t_Bol3 = time_evolution(v_plus_k_omega_Bol3_re, rho0k, k_traval, omega_mesh)
1347
+
1348
+ x_travel, time_travel, T_x_t_NS = time_evolution(T_plus_k_omega_NS_re, rho0k, k_traval, omega_mesh)
1349
+ x_travel, time_travel, T_x_t_Bol3 = time_evolution(T_plus_k_omega_Bol3_re, rho0k, k_traval, omega_mesh)
1350
+ x_travel, time_travel, T_x_t_Learn = time_evolution(T_plus_k_omega_Learn_re, rho0k, k_traval, omega_mesh)
1351
+
1352
+ # plot the time evolution in 2 x 2 grid
1353
+ tplots = [0.0, 0.2, 0.4]
1354
+ fig, axs = plt.subplots(len(tplots)+1, 2, figsize=(8, 2.5*(len(tplots)+1)), dpi=200)
1355
+ for i,time in enumerate([0.0, 0.2, 0.4]):
1356
+ time_index = np.argmin(np.abs(time_travel - time))
1357
+ # +1 here is to add reference rho and T back to the perturbation value
1358
+ axs[i, 0].plot(x_travel, rho_x_t_Bol3[:, time_index]+1, label = "SBGK t=" + "{:.2f}".format( time_travel[ time_index ] ) , linewidth = 2)
1359
+ axs[i, 0].plot(x_travel, rho_x_t_NS[:, time_index]+1, linestyle = 'dotted', label = "NS t=" + "{:.2f}".format( time_travel[ time_index ] ) , linewidth = 2)
1360
+ axs[i, 0].plot(x_travel, rho_x_t_Learn[:, time_index]+1, linestyle = 'dashed', label = "Learn t=" + "{:.2f}".format( time_travel[ time_index ] ) , linewidth = 2)
1361
+ axs[i, 0].set_title("Density")
1362
+ axs[i, 0].legend()
1363
+ axs[i, 0].set_xlim(0, 1)
1364
+ axs[i, 0].set_ylim(1-0.1, 1+2.1)
1365
+ axs[i, 0].set_xlabel("r")
1366
+ axs[i, 0].set_ylabel("ρ")
1367
+ axs[i, 1].plot(x_travel, T_x_t_Bol3[:, time_index]+1, label = "SBGK t=" + "{:.2f}".format( time_travel[ time_index ] ) , linewidth = 2)
1368
+ axs[i, 1].plot(x_travel, T_x_t_NS[:, time_index]+1, linestyle = 'dotted', label = "NS t=" + "{:.2f}".format( time_travel[ time_index ] ) , linewidth = 2)
1369
+ axs[i, 1].plot(x_travel, T_x_t_Learn[:, time_index]+1, linestyle = 'dashed', label = "Learn t=" + "{:.2f}".format( time_travel[ time_index ] ) , linewidth = 2)
1370
+ axs[i, 1].set_title("Temperature")
1371
+ axs[i, 1].legend()
1372
+ axs[i, 1].set_xlim(0, 1)
1373
+ axs[i, 1].set_ylim(1-1, 1+0.2)
1374
+ axs[i, 1].set_xlabel("r")
1375
+ axs[i, 1].set_ylabel("T")
1376
+ #axs[0, 1].set_title("Velocity")
1377
+
1378
+ axs[i+1, 0].plot( Kn_number,rho0k, label = "t=0.00")
1379
+ axs[i+1, 0].set_xlim(0,0.5)
1380
+ axs[i+1, 0].set_xlabel("Kn")
1381
+ axs[i+1, 0].set_ylabel("ρ")
1382
+ axs[i+1, 0].set_title("Initial Density (Fourier Space)")
1383
+ axs[i+1, 0].legend()
1384
+ axs[i+1, 1].plot( Kn_number,rho0k, label = "t=0.00")
1385
+ axs[i+1, 1].set_xlim(0.5,2)
1386
+ axs[i+1, 1].set_ylim(-0.001,0.001)
1387
+ axs[i+1, 1].set_xlabel("Kn")
1388
+ axs[i+1, 1].set_ylabel("ρ")
1389
+ from matplotlib.ticker import FormatStrFormatter
1390
+ axs[i+1, 1].xaxis.set_major_formatter(FormatStrFormatter('%.2f'))
1391
+ axs[i+1, 1].yaxis.set_major_formatter(FormatStrFormatter('%.3f'))
1392
+ axs[i+1, 1].set_title("Initial Density (Fourier Space)")
1393
+ axs[i+1, 1].legend()
1394
+ fig.tight_layout()
1395
+
1396
+ fig.savefig("dynamics.png", dpi=200)
1397
+
1398
+
1399
+
1400
+
1401
+ def CE_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k):
1402
+ m = molecule_mass
1403
+ mu1 = 0
1404
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
1405
+ mu2 = -4/3*Kn
1406
+ mu3 = 0
1407
+ kap1 = 0
1408
+ kap2 = 0
1409
+ kap3 = -15/4*Kn
1410
+ kabs = np.abs(k)
1411
+ tau1 = -kabs*(1-kabs**2*mu1)
1412
+ tau2 = kabs**2*mu2
1413
+ tau3 = -kabs*(1-kabs**2*mu3)
1414
+ tau4 = 2/3*kabs**2*kap1
1415
+ tau5 = -2/3*kabs*(1+kap2)
1416
+ tau6 = 2/3*kabs**2*kap3
1417
+ omega = omega_freq
1418
+ Neff = num_effect
1419
+ rho0 = density_0
1420
+ L = delta_x
1421
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
1422
+ return spec
1423
+ #m = molecule_mass*num_effect/(4*np.pi**2*wavelength**3)
1424
+ #spec = -((complex(0,1)*m*(-4*k**2-20*k**4*Kn**2-23*complex(0,1)*k**2*Kn*omega_freq+6*omega_freq**2))/(density_0*(15*complex(0,1)*k**4*Kn-10*k**2*omega_freq-20*k**4*Kn**2*omega_freq-23*complex(0,1)*k**2*Kn*omega_freq**2+6*omega_freq**3)))
1425
+ #return 2*np.real(spec)
1426
+ def R13_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k):
1427
+ m = molecule_mass
1428
+ mu1 = 0
1429
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
1430
+ mu2 = -4/3*Kn
1431
+ mu3 = 0
1432
+ kap1 = 0
1433
+ kap2 = 0
1434
+ kap3 = -15/4*Kn
1435
+ kabs = np.abs(k)
1436
+ tau1 = -kabs*(1-kabs**2*mu1)
1437
+ tau2 = kabs**2*mu2
1438
+ tau3 = -kabs*(1-kabs**2*mu3)
1439
+ tau4 = 2/3*kabs**2*kap1
1440
+ tau5 = -2/3*kabs*(1+kap2)
1441
+ tau6 = 2/3*kabs**2*kap3
1442
+ omega = omega_freq
1443
+ Neff = num_effect
1444
+ rho0 = density_0
1445
+ L = delta_x
1446
+ spec = 2*(15*k**4*Kn*m*Neff*(5*k**2*(5+6*k**2*Kn**2)*(25+210*k**2*Kn**2+162*k**4*Kn**4)+(500+5775*k**2*Kn**2+29295*k**4*Kn**4+17496*k**6*Kn**6)*omega**2+225*Kn**2*(5+6*k**2*Kn**2)*omega**4))/(L**3*np.pi**2*density_0*(5625*k**8*Kn**2*(5+6*k**2*Kn**2)**2+25*k**4*(2500+3*k**2*Kn**2*(3500+35175*k**2*Kn**2+60480*k**4*Kn**4+34992*k**6*Kn**6))*omega**2-30*k**2*(2500+3*k**2*Kn**2*(625+20850*k**2*Kn**2-6030*k**4*Kn**4+34992*k**6*Kn**6))*omega**4+18*(1250-7750*k**2*Kn**2+50775*k**4*Kn**4-125820*k**6*Kn**6+52488*k**8*Kn**8)*omega**6+1125*Kn**2*(65+72*k**2*Kn**2*(-2+9*k**2*Kn**2))*omega**8+50625*Kn**4*omega**10))
1447
+ return spec
1448
+ def TH_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k, mask = -1):
1449
+ m = molecule_mass
1450
+ mu1 = 0
1451
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
1452
+ mu2 = -4/3*Kn
1453
+ mu3 = 0
1454
+ kap1 = 0
1455
+ kap2 = 0
1456
+ kap3 = -15/4*Kn
1457
+ kabs = np.abs(k)
1458
+ print(kabs)
1459
+ tau1 = -0.910858854965221635639183580413607*kabs-0.0681031747662745635208073664825305*kabs**2
1460
+ tau2 = -0.137647159761080650249789096758410*kabs**2+0.00258989586650062128792005410176610*kabs**3
1461
+ tau3 = -0.980736834542179305331651160476348*kabs+0.002878781203443508188808986885745442*kabs**3
1462
+ tau4 = 0.00270043719488066581208735095210*kabs**2-0.000956430940350492874510704526398*kabs**3+0.0000398354558076273539332410866928*kabs**4
1463
+ #tau4 = 2/3*kabs**2*kap1
1464
+ tau5 = -0.677006693600986515897927777975082*kabs-0.02720695551116714037510321445687466*kabs**2
1465
+ tau6 = -0.248523533056964259160237397019776*kabs**2+0.00978711916205478871774188307120469*kabs**3
1466
+
1467
+
1468
+ if mask == 0:
1469
+ tau1 = -kabs*(1-kabs**2*mu1)
1470
+ elif mask == 1:
1471
+ tau2 = kabs**2*mu2
1472
+ elif mask == 2:
1473
+ tau3 = -kabs*(1-kabs**2*mu3)
1474
+ elif mask == 3:
1475
+ tau4 = 2/3*kabs**2*kap1
1476
+ elif mask == 4:
1477
+ tau5 = -2/3*kabs*(1+kap2)
1478
+ elif mask == 5:
1479
+ tau6 = 2/3*kabs**2*kap3
1480
+ omega = omega_freq
1481
+ Neff = num_effect
1482
+ rho0 = density_0
1483
+ L = delta_x
1484
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
1485
+ return spec
1486
+
1487
+ def THBGK_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k, mask = -1):
1488
+ m = molecule_mass
1489
+ mu1 = 0
1490
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
1491
+ mu2 = -4/3*Kn
1492
+ mu3 = 0
1493
+ kap1 = 0
1494
+ kap2 = 0
1495
+ kap3 = -15/4*Kn
1496
+ kabs = np.abs(k)
1497
+ print(kabs)
1498
+ #tau1 = -0.910858854965221635639183580413607*kabs-0.0681031747662745635208073664825305*kabs**2
1499
+ #tau1 = -0.9858867248408030*kabs-0.04701941111476196*kabs**2
1500
+ tau1 = -0.991013044792487766036126122635640*kabs-0.0403239332346867445520412638803096*kabs**2-0.002166184469076816223924007295632155*kabs**3
1501
+ #tau2 = -0.137647159761080650249789096758410*kabs**2+0.00258989586650062128792005410176610*kabs**3
1502
+ #tau2 = -0.129198118429724*kabs**2+0.00400848955369925*kabs**3
1503
+ tau2 = -0.149161289391781081302603295336010*kabs**2 + 0.00594195008578441066220857129869587*kabs**3 - 0.000232348591684703766188347436129974*kabs**4
1504
+ #tau3 = -0.980736834542179305331651160476348*kabs+0.002878781203443508188808986885745442*kabs**3
1505
+ #tau3 = -1.002964233770220*kabs-0.0000911571759799050*kabs**3
1506
+ tau3 = -1.064641200298265511954132389066412*kabs + 0.02791589569574715853735528833289102*kabs**2 + 0.000762400543447067776385421347639320*kabs**3
1507
+ #tau4 = 0.00270043719488066581208735095210*kabs**2-0.000956430940350492874510704526398*kabs**3+0.0000398354558076273539332410866928*kabs**4
1508
+ #tau4 = -0.0084451424529939*kabs**2-0.00060032464997635*kabs**3+0.000017125859875981*kabs**4
1509
+ tau4 = 0.00270043719488066581208735095210*kabs**2 - 0.000956430940350492874510704526398*kabs**3 + 0.0000398354558076273539332410866928*kabs**4
1510
+ #tau4 = 2/3*kabs**2*kap1
1511
+ #tau5 = -0.677006693600986515897927777975082*kabs-0.02720695551116714037510321445687466*kabs**2
1512
+ #tau5 = -0.677965329349480*kabs-0.002348308957845470*kabs**2
1513
+ tau5 = -0.664300463755129273501867308536487*kabs - 0.0316105859215623339424006394153918*kabs^2 + 0.000343388633980720341529015301083001*kabs^3
1514
+ #tau6 = -0.248523533056964259160237397019776*kabs**2+0.00978711916205478871774188307120469*kabs**3
1515
+ #tau6 = -0.185259190536085*kabs**2+0.0068634125525231*kabs**3
1516
+ tau6 = -0.280753259910037449250341065089074*kabs^2 + 0.0191700074349251339913376848978025*kabs^3 - 0.000650377569549622175919978516795108*kabs^4
1517
+
1518
+
1519
+ if mask == 0:
1520
+ tau1 = -kabs*(1-kabs**2*mu1)
1521
+ elif mask == 1:
1522
+ tau2 = kabs**2*mu2
1523
+ elif mask == 2:
1524
+ tau3 = -kabs*(1-kabs**2*mu3)
1525
+ elif mask == 3:
1526
+ tau4 = 2/3*kabs**2*kap1
1527
+ elif mask == 4:
1528
+ tau5 = -2/3*kabs*(1+kap2)
1529
+ elif mask == 5:
1530
+ tau6 = 2/3*kabs**2*kap3
1531
+ omega = omega_freq
1532
+ Neff = num_effect
1533
+ rho0 = density_0
1534
+ L = delta_x
1535
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
1536
+ return spec
1537
+ def MW_spectra(delta_x,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,omega_freq,num_effect,k):
1538
+ m = molecule_mass
1539
+ mu1 = 0
1540
+ Kn = np.sqrt(molecule_mass/(Boltz*Temp_0))*viscosity_coef/density_0/delta_x
1541
+ mu2 = -4/3*Kn
1542
+ mu3 = 0
1543
+ kap1 = 0
1544
+ kap2 = 0
1545
+ kap3 = -15/4*Kn
1546
+ kabs = np.abs(k)
1547
+ tau1 = -kabs*(1-kabs**2*mu1)
1548
+ tau2 = kabs**2*mu2
1549
+ tau3 = -kabs*(1-kabs**2*mu3)
1550
+ tau4 = 2/3*kabs**2*kap1
1551
+ tau5 = -2/3*kabs*(1+kap2)
1552
+ tau6 = 2/3*kabs**2*kap3
1553
+ omega = omega_freq
1554
+ Neff = num_effect
1555
+ rho0 = density_0
1556
+ L = delta_x
1557
+ spec = (k*m*Neff*(-(tau3*tau4-tau1*tau6)*(tau3*tau5+tau2*tau6)+(tau1*tau2+tau3*tau4)*omega**2))/(2*L**3*np.pi**2*rho0*(k**2*(tau3*tau4-tau1*tau6)**2+(k**2*tau1**2+(tau3*tau5+tau2*tau6)**2-2*k*(tau2*tau3*tau4+tau1*tau3*tau5+tau3*tau4*tau6-tau1*tau6**2))*omega**2+(2*k*tau1+tau2**2-2*tau3*tau5+tau6**2)*omega**4+omega**6))
1558
+ return spec
1559
+ #m = molecule_mass*num_effect/(4*np.pi**2*wavelength**3)
1560
+ #spec = -((complex(0,1)*m*(-4*k**2-20*k**4*Kn**2-23*complex(0,1)*k**2*Kn*omega_freq+6*omega_freq**2))/(density_0*(15*complex(0,1)*k**4*Kn-10*k**2*omega_freq-20*k**4*Kn**2*omega_freq-23*complex(0,1)*k**2*Kn*omega_freq**2+6*omega_freq**3)))
1561
+ #return 2*np.real(spec)
1562
+
1563
+
1564
+
1565
+
1566
+
1567
+
1568
+ wavelength = 2*np.pi/k_traval*space_scale
1569
+ Kn_number = viscosity_coef/(density_0*wavelength)/np.sqrt(Boltz*Temp_0/molecule_mass)
1570
+ Kn_number
1571
+
1572
+ plt_grid = (2, 3)
1573
+
1574
+ fig, axs = plt.subplots(2, 3, figsize=(14, 8), dpi = 200)
1575
+ for i, kn_plot in enumerate( [0.01511645, 0.04534935, 0.10116449, 0.63489085, 2.51188643, 10. ] ):
1576
+ ind = np.argmin( np.abs(Kn_number - kn_plot) )
1577
+ k_plot = k_traval[ind]
1578
+ axs[i//plt_grid[1], i%plt_grid[1]].plot(macro_values[ind][0]/(k_plot*(5/3)**0.5), impulse*2*macro_values[ind][1][...,0], label = "SBGK (ref)")
1579
+ axs[i//plt_grid[1], i%plt_grid[1]].plot(macro_values[ind][0]/(k_plot*(5/3)**0.5), impulse*2*get_rhoRe(k_traval[ind], macro_values[ind][0]), label = "NS", linestyle = 'dotted')
1580
+ axs[i//plt_grid[1], i%plt_grid[1]].plot(macro_values[ind][0]/(k_plot*(5/3)**0.5) , R13_spectra(space_scale,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,macro_values[ind][0],num_effect,k_plot) , label = "R13 Equation", linestyle = 'dashed')
1581
+
1582
+ with torch.no_grad():
1583
+ net_spectra, net_spectra_omega, _, rhoSpec, vSpec, TSpec,_ = sNet(torch.tensor( nnp.array( k_plot ), device = device, dtype = dtype), torch.tensor( nnp.array(macro_values[ind][0][None,:]/(k_plot *(5/3)**0.5) ), device = device, dtype = dtype))
1584
+ net_spectra = net_spectra.cpu().numpy()
1585
+ net_spectra_omega = net_spectra_omega.cpu().numpy()
1586
+ axs[i//plt_grid[1], i%plt_grid[1]].plot(net_spectra_omega[0] , net_spectra[0], label = "Learned")
1587
+
1588
+ if k_plot < 50:
1589
+ k_number = np.argmin( np.abs(k_titla_freq - k_plot) )
1590
+ omega_plot = np.fft.fftshift(omega_freq)/(kx_freq[k_number]*speed_of_sound)
1591
+ omega_spacing = np.mean( omega_plot[1:]-omega_plot[:-1] )
1592
+ plot_spectra = np.fft.fftshift( spectra[:,k_number])/space_scale**3/time_scale
1593
+ b, a = signal.butter(1, 20, fs = 1/omega_spacing)
1594
+ filtered_spectra = signal.filtfilt(b, a, plot_spectra)
1595
+ axs[i//plt_grid[1], i%plt_grid[1]].plot(omega_plot , filtered_spectra, label = "DSMC (ref)")
1596
+ if k_plot < 13:
1597
+ #axs[i//plt_grid[1], i%plt_grid[1]].plot(macro_values[ind][0]/(k_plot*(5/3)**0.5) , TH_spectra(space_scale,viscosity_coef,Boltz,Temp_0,molecule_mass,density_0,macro_values[ind][0],num_effect,k_plot) , label = "Hydro Manifold")
1598
+ pass
1599
+
1600
+
1601
+ axs[i//plt_grid[1], i%plt_grid[1]].set_xlim(0,2)
1602
+ axs[i//plt_grid[1], i%plt_grid[1]].set_title("Kn = " + "{:.2f}".format(Kn_number[ind]))
1603
+ axs[i//plt_grid[1], i%plt_grid[1]].set_xlabel("ω")
1604
+ axs[i//plt_grid[1], i%plt_grid[1]].set_ylabel("$<ρ^2>$")
1605
+ axs[i//plt_grid[1], i%plt_grid[1]].legend()
1606
+ # adjust the space between the plots
1607
+ plt.tight_layout()
1608
+ fig.savefig("spectra.png", dpi=200)
1609
+
1610
+
1611
+
1612
+ #rho_k_omega_re = ( np.flip(rho_k_omega_re,axis=-1) + rho_k_omega_re )/2
dynamics.png ADDED

Git LFS Details

  • SHA256: dfb88e04883b938fc48594de66505079cb07f6dde15a57f92fa98ed5b6536d1c
  • Pointer size: 131 Bytes
  • Size of remote file: 306 kB
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ jax
2
+ jaxlib
3
+ numpy
4
+ scipy
5
+ matplotlib
6
+ ipython
7
+ jaxopt
8
+ tqdm
9
+ torch
spectra.png ADDED

Git LFS Details

  • SHA256: b81bc250a5b48c994d7fc167d376d4fa04e0a75a5acf8e0955770fb3b0b62218
  • Pointer size: 131 Bytes
  • Size of remote file: 388 kB