Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
iterate_coag.py
1import sys
2import time
3
4import numpy as np
5from scipy.special import legendre
6
7from .compute_coag import *
8from .generate_flux_intflux import *
9
10# import numba_progress
11# from progressbar import Bar,Percentage,ProgressBar
12from .generate_tabflux_tabintflux import *
13from .L2_proj import *
14from .limiter import *
15from .utils_polynomials import *
16
17
18def iterate_coag(kernel, K0, nbins, kpol, dthydro, ndthydro, coeff_CFL, Q, eps, massgrid, massbins):
19 """
20 Function to iterate coagulation solver to reach the time ndthydro x dthydro
21
22 DG scheme k=0, piecewise constant approximation
23
24 Parameters
25 ----------
26 kernel : scalar, type -> integer
27 select the collisional kernel function
28 K0 : scalar, type -> float
29 constant value of the kernel function (used to adapt to code unit)
30 nbins : scalar, type -> integer
31 number of dust bins
32 kpol : scalar, type -> integer
33 degree of polynomials for approximation
34 dthydro : scalar, type -> float
35 hydro timestep, used as timestep to reach for coagulation process
36 ndthydro : scalar, type -> integer
37 number of hydro timestep
38 coeff_CFL : scalar, type -> float
39 timestep coefficient for stability of the SSPRK order 3 scheme
40 Q : scalar, type -> integer
41 number of points for Gauss-Legendre quadrature
42 eps : scalar, type -> float
43 minimum value for mass distribution approximation gij
44 massgrid : 1D array (dim = nbins+1), type -> float
45 grid of masses given borders value of mass bins
46 massbins : 1D array (dim = nbins), type -> float
47 arithmetic mean value of massgrid for each mass bins
48
49
50 Returns
51 -------
52 gij_init : 1D array (dim = nbins) or 2D array (dim = (nbins.kpol+1)), type -> float
53 initial components of g on the polynomial basis
54 gij : 1D array (dim = nbins) or 2D array (dim = (nbins.kpol+1)), type -> float
55 evolved components of g on the polynomial basis
56 time_coag : scalar, type -> float
57 final time ndthydro x dthydro
58
59 """
60
61 vecnodes, vecweights = np.polynomial.legendre.leggauss(Q)
62
63 # Legendre polynomial coefficients
64 mat_coeffs_leg = np.zeros((kpol + 1, kpol + 1))
65 mat_coeffs_leg = legendre_coeffs(kpol)
66
67 start = time.time()
68 match kernel:
69 # simple kernels
70 case 0 | 1 | 2:
71 if kpol == 0:
72 tensor_tabflux_coag = np.zeros((nbins, nbins, nbins))
73
74 # original version
75 # print("Computing coagtabflux k=0 ...")
76 # compute_coagtabflux_k0(kernel,K0,Q,vecnodes,vecweights,nbins,massgrid,mat_coeffs_leg,tensor_tabflux_coag)
77 # print("coagtabflux k=0 done")
78
79 # numba version
80 # with numba_progress.ProgressBar(total=nbins, desc="Precomputing coagtabflux k=%d with numba"%(kpol)) as progress:
81 compute_coagtabflux_k0_numba(
82 kernel,
83 K0,
84 Q,
85 vecnodes,
86 vecweights,
87 nbins,
88 massgrid,
89 mat_coeffs_leg,
90 tensor_tabflux_coag,
91 ) # ,progress)
92
93 else:
94 tensor_tabflux_coag = np.zeros((nbins, nbins, nbins, kpol + 1, kpol + 1))
95
96 # original version
97 # print("Computing coagtabflux k=%d ..."%(kpol))
98 # compute_coagtabflux(kernel,K0,Q,vecnodes,vecweights,nbins,kpol,massgrid,mat_coeffs_leg,tensor_tabflux_coag)
99 # print("coagtabflux k=%d done"%(kpol))
100
101 # numba version
102 # with numba_progress.ProgressBar(total=nbins, desc="Precomputing coagtabflux k=%d with numba"%(kpol)) as progress:
103 compute_coagtabflux_numba(
104 kernel,
105 K0,
106 Q,
107 vecnodes,
108 vecweights,
109 nbins,
110 kpol,
111 massgrid,
112 mat_coeffs_leg,
113 tensor_tabflux_coag,
114 ) # ,progress)
115
116 tensor_tabintflux_coag = np.zeros(
117 (nbins, kpol + 1, nbins, nbins, kpol + 1, kpol + 1)
118 )
119
120 # original version
121 # print("Computing coagtabintflux k=%d ..."%(kpol))
122 # compute_coagtabintflux(kernel,K0,Q,vecnodes,vecweights,nbins,kpol,massgrid,mat_coeffs_leg,tensor_tabintflux_coag)
123 # print("coagtabintflux k=%d done"%(kpol))
124
125 # with numba_progress.ProgressBar(total=nbins, desc="Precomputing coagtabintflux k=%d with numba"%(kpol)) as progress:
126 compute_coagtabintflux_numba(
127 kernel,
128 K0,
129 Q,
130 vecnodes,
131 vecweights,
132 nbins,
133 kpol,
134 massgrid,
135 mat_coeffs_leg,
136 tensor_tabintflux_coag,
137 ) # ,progress)
138
139 # sys.exit()
140
141 case _:
142 return "Need to choose a kernel in the list among values 0,1,2."
143
144 # continue
145
146 finish = time.time()
147 if kpol == 0:
148 print("Tensor tabflux generated in %.5f s" % (finish - start))
149 else:
150 print("Tensor tabflux tabintflux generated in %.5f s" % (finish - start))
151
152 # generate gij component on Legendre polynomials basis
153 # initial condition
154 start = time.time()
155 if kpol == 0:
156 gij = L2projDL_k0(eps, nbins, massgrid, massbins, Q, vecnodes, vecweights)
157 else:
158 gij = L2projDL(eps, nbins, kpol, massgrid, massbins, Q, vecnodes, vecweights)
159
160 # apply scale limiter
161 tabgamma = gammafunction(eps, nbins, kpol, massgrid, massbins, gij)
162 gij[:, 1:] = np.transpose(tabgamma * np.transpose(gij[:, 1:]))
163
164 # limit to eps value
165 if gij[:, 0][gij[:, 0] < 0.0].any():
166 print("gij", gij)
167 sys.exit()
168 else:
169 gij[:, 0][gij[:, 0] < eps] = eps
170 gij[:, 1:][gij[:, 0] < eps] = 0.0
171
172 finish = time.time()
173 gij_init = np.copy(gij)
174 print("gij generated in %.5f s" % (finish - start))
175 print("gij t0 =", gij)
176
177 # total mass density
178 if kpol == 0:
179 M1_t0 = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij)
180 else:
181 M1_t0 = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij[:, 0])
182 print("M1 t0 = ", M1_t0)
183
184 tot_nsub = 0
185 tot_ndt = 0
186
187 print("Time solver in progress")
188 # time solver DG
189 start = time.time()
190 time_coag = 0.0
191
192 match kernel:
193 # analytical kernels
194 case 0 | 1 | 2:
195 # bar = ProgressBar(widgets=[Percentage(), Bar()], maxval=ndthydro).start()
196 if kpol == 0:
197 for i in range(ndthydro):
198 gij, nsub, ndt = compute_coag_k0(
199 eps, coeff_CFL, nbins, massgrid, gij, tensor_tabflux_coag, dthydro
200 )
201 tot_nsub += nsub
202 tot_ndt += ndt
203 time_coag += dthydro
204 # bar.update(i+1)
205 else:
206 for i in range(ndthydro):
207 gij, nsub, ndt = compute_coag(
208 eps,
209 coeff_CFL,
210 nbins,
211 kpol,
212 massgrid,
213 massbins,
214 gij,
215 tensor_tabflux_coag,
216 tensor_tabintflux_coag,
217 dthydro,
218 )
219
220 tot_nsub += nsub
221 tot_ndt += ndt
222 time_coag += dthydro
223 # bar.update(i+1)
224
225 # bar.finish()
226
227 case _:
228 return "Need to choose a kernel in the list."
229
230 finish = time.time()
231
232 print("")
233 print("total nsub =", tot_nsub)
234 print("total ndt =", tot_ndt)
235 print("total number time-steps =", tot_ndt + tot_nsub)
236
237 print("")
238 print("gij tend =", gij)
239
240 if kpol == 0:
241 M1_tend = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij)
242 else:
243 M1_tend = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij[:, 0])
244 print("M1 t0 = ", M1_t0)
245 print("M1 tend = ", M1_tend)
246 print("diff M1 = ", M1_tend - M1_t0)
247
248 print("Time solver in %.5f" % (finish - start))
249
250 return gij_init, gij, time_coag
251
252
253def iterate_coag_kdv(
254 kernel, K0, nbins, kpol, dthydro, ndthydro, coeff_CFL, Q, eps, massgrid, massbins, dv
255):
256 """
257 Function to iterate coagulation solver to reach the time ndthydro x dthydro
258
259 Function for ballistic kernel with differential velocities dv
260
261 DG scheme k=0, piecewise constant approximation
262
263 Parameters
264 ----------
265 kernel : scalar, type -> integer
266 select the collisional kernel function
267 K0 : scalar, type -> float
268 constant value of the kernel function (used to adapt to code unit)
269 nbins : scalar, type -> integer
270 number of dust bins
271 kpol : scalar, type -> integer
272 degree of polynomials for approximation
273 dthydro : scalar, type -> float
274 hydro timestep, used as timestep to reach for coagulation process
275 ndthydro : scalar, type -> integer
276 number of hydro timestep
277 coeff_CFL : scalar, type -> float
278 timestep coefficient for stability of the SSPRK order 3 scheme
279 Q : scalar, type -> integer
280 number of points for Gauss-Legendre quadrature
281 eps : scalar, type -> float
282 minimum value for mass distribution approximation gij
283 massgrid : 1D array (dim = nbins+1), type -> float
284 grid of masses given borders value of mass bins
285 massbins : 1D array (dim = nbins), type -> float
286 arithmetic mean value of massgrid for each mass bins
287 dv : 2D array (dim = (nbins,nbins)), type -> float
288 array of the differential velocity between grains
289
290
291 Returns
292 -------
293 gij_init : 1D array (dim = nbins) or 2D array (dim = (nbins.kpol+1)), type -> float
294 initial components of g on the polynomial basis
295 gij : 1D array (dim = nbins) or 2D array (dim = (nbins.kpol+1)), type -> float
296 evolved components of g on the polynomial basis
297 time_coag : scalar, type -> float
298 final time ndthydro x dthydro
299
300 """
301
302 vecnodes, vecweights = np.polynomial.legendre.leggauss(Q)
303
304 # Legendre polynomial coefficients
305 mat_coeffs_leg = np.zeros((kpol + 1, kpol + 1))
306 mat_coeffs_leg = legendre_coeffs(kpol)
307
308 # print("mat_coeffs_leg=",mat_coeffs_leg)
309
310 start = time.time()
311 if kernel == 3:
312 if kpol == 0:
313 tensor_tabflux_coag = np.zeros((nbins, nbins, nbins))
314
315 # original version
316 # print("Computing coagtabflux k=0 ...")
317 # compute_coagtabflux_k0(kernel,K0,Q,vecnodes,vecweights,nbins,massgrid,mat_coeffs_leg,tensor_tabflux_coag)
318 # print("coagtabflux k=0 done")
319
320 # numba version
321 # with numba_progress.ProgressBar(total=nbins, desc="Precomputing coagtabflux k=%d with numba"%(kpol)) as progress:
322 compute_coagtabflux_k0_numba(
323 kernel,
324 K0,
325 Q,
326 vecnodes,
327 vecweights,
328 nbins,
329 massgrid,
330 mat_coeffs_leg,
331 tensor_tabflux_coag,
332 ) # ,progress)
333
334 else:
335 tensor_tabflux_coag = np.zeros((nbins, nbins, nbins, kpol + 1, kpol + 1))
336
337 # original version
338 # print("Computing coagtabflux k=%d ..."%(kpol))
339 # compute_coagtabflux(kernel,K0,Q,vecnodes,vecweights,nbins,kpol,massgrid,mat_coeffs_leg,tensor_tabflux_coag)
340 # print("coagtabflux k=%d done"%(kpol))
341
342 # numba version
343 # with numba_progress.ProgressBar(total=nbins, desc="Precomputing coagtabflux k=%d with numba"%(kpol)) as progress:
344 compute_coagtabflux_numba(
345 kernel,
346 K0,
347 Q,
348 vecnodes,
349 vecweights,
350 nbins,
351 kpol,
352 massgrid,
353 mat_coeffs_leg,
354 tensor_tabflux_coag,
355 ) # ,progress)
356
357 tensor_tabintflux_coag = np.zeros((nbins, kpol + 1, nbins, nbins, kpol + 1, kpol + 1))
358
359 # original version
360 # print("Computing coagtabintflux k=%d ..."%(kpol))
361 # compute_coagtabintflux(kernel,K0,Q,vecnodes,vecweights,nbins,kpol,massgrid,mat_coeffs_leg,tensor_tabintflux_coag)
362 # print("coagtabintflux k=%d done"%(kpol))
363
364 # with numba_progress.ProgressBar(total=nbins, desc="Precomputing coagtabintflux k=%d with numba"%(kpol)) as progress:
365 compute_coagtabintflux_numba(
366 kernel,
367 K0,
368 Q,
369 vecnodes,
370 vecweights,
371 nbins,
372 kpol,
373 massgrid,
374 mat_coeffs_leg,
375 tensor_tabintflux_coag,
376 ) # ,progress)
377
378 else:
379 print("Need to choose a kernel = 3 for ballistic kernel with dv array.")
380 sys.exit()
381
382 finish = time.time()
383 if kpol == 0:
384 print("Tensor tabflux generated in %.5f s" % (finish - start))
385 else:
386 print("Tensor tabflux tabintflux generated in %.5f s" % (finish - start))
387
388 # generate gij component on Legendre polynomials basis
389 # initial condition
390 start = time.time()
391 if kpol == 0:
392 gij = L2projDL_k0(eps, nbins, massgrid, massbins, Q, vecnodes, vecweights)
393 else:
394 gij = L2projDL(eps, nbins, kpol, massgrid, massbins, Q, vecnodes, vecweights)
395
396 # print("gij before limiter",gij)
397
398 # apply scale limiter
399 tabgamma = gammafunction(eps, nbins, kpol, massgrid, massbins, gij)
400 # print("tabgamma = ",tabgamma)
401 gij[:, 1:] = np.transpose(tabgamma * np.transpose(gij[:, 1:]))
402
403 # sys.exit()
404
405 # limit to eps value
406 if gij[:, 0][gij[:, 0] < 0.0].any():
407 print("gij", gij)
408 sys.exit()
409 else:
410 gij[:, 0][gij[:, 0] < eps] = eps
411 gij[:, 1:][gij[:, 0] < eps] = 0.0
412
413 finish = time.time()
414 gij_init = np.copy(gij)
415 print("gij generated in %.5f s" % (finish - start))
416 print("gij t0 =", gij)
417
418 # test flux kdv
419 # flux_test = compute_flux_coag_kdv(gij,tensor_tabflux_coag,dv)
420 # for i in range(nbins):
421 # print("i=",i,",flux =",flux_test[i])
422
423 # intflux_test = compute_intflux_coag_kdv(gij,tensor_tabintflux_coag,dv)
424 # for i in range(nbins):
425 # print("i=",i,",intflux =",intflux_test[i,:])
426
427 # sys.exit()
428
429 # total mass density
430 if kpol == 0:
431 M1_t0 = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij)
432 else:
433 M1_t0 = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij[:, 0])
434 print("M1 t0 = ", M1_t0)
435
436 tot_nsub = 0
437 tot_ndt = 0
438
439 print("Time solver in progress")
440 # time solver DG
441 start = time.time()
442 time_coag = 0.0
443
444 if kernel == 3:
445 # bar = ProgressBar(widgets=[Percentage(), Bar()], maxval=ndthydro).start()
446 if kpol == 0:
447 for i in range(ndthydro):
448 gij, nsub, ndt = compute_coag_k0_kdv(
449 eps, coeff_CFL, nbins, massgrid, gij, tensor_tabflux_coag, dv, dthydro
450 )
451
452 tot_nsub += nsub
453 tot_ndt += ndt
454 time_coag += dthydro
455 # bar.update(i+1)
456 else:
457 for i in range(ndthydro):
458 gij, nsub, ndt = compute_coag_kdv(
459 eps,
460 coeff_CFL,
461 nbins,
462 kpol,
463 massgrid,
464 massbins,
465 gij,
466 tensor_tabflux_coag,
467 tensor_tabintflux_coag,
468 dv,
469 dthydro,
470 )
471
472 tot_nsub += nsub
473 tot_ndt += ndt
474 time_coag += dthydro
475 # bar.update(i+1)
476
477 # bar.finish()
478
479 else:
480 print("Need to choose a kernel = 3 for ballistic kernel with dv array.")
481 sys.exit()
482
483 finish = time.time()
484
485 print("")
486 print("total nsub =", tot_nsub)
487 print("total ndt =", tot_ndt)
488 print("total number time-steps =", tot_ndt + tot_nsub)
489
490 print("")
491 print("gij tend =", gij)
492
493 if kpol == 0:
494 M1_tend = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij)
495 else:
496 M1_tend = np.sum((massgrid[1:] - massgrid[0:nbins]) * gij[:, 0])
497 print("M1 t0 = ", M1_t0)
498 print("M1 tend = ", M1_tend)
499 print("diff M1 = ", M1_tend - M1_t0)
500
501 print("Time solver in %.5f" % (finish - start))
502
503 return gij_init, gij, time_coag