Skip to content

Commit 5b1bd7a

Browse files
committed
updates solvers to adress pickup at boundaries
Tested for circular boundaries.
1 parent e38823c commit 5b1bd7a

File tree

1 file changed

+37
-133
lines changed

1 file changed

+37
-133
lines changed

aeolis/utils.py

Lines changed: 37 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ def calc_mean_grain_size(p, s):
449449
D_mean[yi, xi] = np.sum(diameters*weights)
450450
return D_mean
451451

452-
@njit(cache=True)
452+
# @njit(cache=True) this function is an orchestrator njit will not be faster
453453
def sweep(Ct, Cu, mass, dt, Ts, ds, dn, us, un, w):
454454

455455

@@ -506,7 +506,7 @@ def sweep(Ct, Cu, mass, dt, Ts, ds, dn, us, un, w):
506506
ufn[0,:,:] = (ufn[0,:,:]+ufn[-1,:,:])/2
507507
ufn[-1,:,:] = ufn[0,:,:]
508508

509-
# now make sure that there is no gradients at the bondares
509+
# now make sure that there is no gradients at the bondaries
510510
ufs[:,1,:] = ufs[:,0,:]
511511
ufs[:,-2,:] = ufs[:,-1,:]
512512
ufs[1,:,:] = ufs[0,:,:]
@@ -544,148 +544,52 @@ def sweep(Ct, Cu, mass, dt, Ts, ds, dn, us, un, w):
544544
Ct[:,0,0],Ct[:,-1,0] = Ct[:,-1,0].copy(),Ct[:,0,0].copy()
545545

546546
if recirc_offshore:
547-
# print(Ct[:,1,0])
548-
# print(Ct[:,-2,0])
549-
Ct[:,0,0],Ct[:,-1,0] = np.average(Ct[:,-2,0]),np.average(Ct[:,1,0])
550-
# print(Ct[:,0,0])
551-
# print(Ct[:,-1,0])
547+
Ct[:,0,0],Ct[:,-1,0] = np.mean(Ct[:,-2,0]), np.mean(Ct[:,1,0])
552548

553-
# make an array with a bolean operator. This keeps track of considerd cells. We start with all False (not considered)
554-
q = np.zeros(Cu.shape[:2])
549+
# Track visited cells and quadrant classification
550+
visited = np.zeros(Cu.shape[:2], dtype=np.bool_)
551+
quad = np.zeros(Cu.shape[:2], dtype=np.uint8)
555552

556553
########################################################################################
557554
# in this sweeping algorithm we sweep over the 4 quadrants
558555
# assuming that most cells have no converging/divering charactersitics.
559556
# In the last quadrant we take converging and diverging cells into account.
560557

561-
# The First quadrant
562-
for n in range(1,Ct.shape[0]):
563-
for s in range(1,Ct.shape[1]):
564-
if (not q[n,s]) and (ufn[n,s,0]>=0) and (ufs[n,s,0]>=0) and (ufn[n+1,s,0]>=0) and (ufs[n,s+1,0]>=0):
565-
Ct[n,s,:] = (+ (Ct[n-1,s,:] * ufn[n,s,:] * ds[n,s]) \
566-
+ (Ct[n,s-1,:] * ufs[n,s,:] * dn[n,s]) \
567-
+ w[n,s,:] * Cu[n,s,:] * ds[n,s] * dn [n,s] / Ts ) \
568-
/ ( + (ufn[n+1,s,:] * ds[n,s]) \
569-
+ (ufs[n,s+1,:] * dn[n,s]) \
570-
+ (ds[n,s] * dn [n,s] / Ts) )
571-
#calculate pickup
572-
pickup[n,s,:] = (w[n,s,:] * Cu[n,s,:] - Ct[n,s,:]) * dt/Ts
573-
#check for supply limitations and re-iterate concentration to account for supply limitations
574-
for nfs in range(0,nf):
575-
if pickup[n,s,nfs]>mass[n,s,0,nfs]:
576-
pickup[n,s,nfs] = mass[n,s,0,nfs]
577-
Ct[n,s,nfs] = (+ (Ct[n-1,s,nfs] * ufn[n,s,nfs] * ds[n,s]) \
578-
+ (Ct[n,s-1,nfs] * ufs[n,s,nfs] * dn[n,s]) \
579-
+ pickup[n,s,nfs] * ds[n,s] * dn [n,s] / dt ) \
580-
/ (+(ufn[n+1,s,nfs] * ds[n,s]) \
581-
+ (ufs[n,s+1,nfs] * dn[n,s]))
582-
q[n,s]=1
583-
# The second quadrant
584-
for n in range(1,Ct.shape[0]):
585-
for s in range(Ct.shape[1]-2,-1,-1):
586-
if (not q[n,s]) and (ufn[n,s,0]>=0) and (ufs[n,s,0]<=0) and (ufn[n+1,s,0]>=0) and (ufs[n,s+1,0]<=0):
587-
Ct[n,s,:] = (+ (Ct[n-1,s,:] * ufn[n,s,:] * ds[n,s]) \
588-
+ ( -Ct[n,s+1,:] * ufs[n,s+1,:] * dn[n,s]) \
589-
+ w[n,s,:] * Cu[n,s,:] * ds[n,s] * dn [n,s] / Ts ) \
590-
/ ( + (ufn[n+1,s,:] * ds[n,s]) \
591-
+ (-ufs[n,s,:] * dn[n,s]) \
592-
+ (ds[n,s] * dn [n,s] / Ts) )
593-
#calculate pickup
594-
pickup[n,s,:] = (w[n,s,:] * Cu[n,s,:]-Ct[n,s,:]) * dt/Ts
595-
#check for supply limitations and re-iterate concentration to account for supply limitations
596-
for nfs in range(0,nf):
597-
if pickup[n,s,nfs]>mass[n,s,0,nfs]:
598-
pickup[n,s,nfs] = mass[n,s,0,nfs]
599-
Ct[n,s,nfs] = (+ (Ct[n-1,s,nfs] * ufn[n,s,nfs] * ds[n,s]) \
600-
+ ( -Ct[n,s+1,nfs] * ufs[n,s+1,nfs] * dn[n,s]) \
601-
+ pickup[n,s,nfs] * ds[n,s] * dn [n,s] / dt ) \
602-
/ ( + (ufn[n+1,s,nfs] * ds[n,s]) \
603-
+ (-ufs[n,s,nfs] * dn[n,s]))
604-
q[n,s]=2
605-
# The third quadrant
606-
for n in range(Ct.shape[0]-2,-1,-1):
607-
for s in range(Ct.shape[1]-2,-1,-1):
608-
if (not q[n,s]) and (ufn[n,s,0]<=0) and (ufs[n,s,0]<=0) and (ufn[n+1,s,0]<=0) and (ufs[n,s+1,0]<=0):
609-
Ct[n,s,:] = (+ ( -Ct[n+1,s,:] * ufn[n+1,s,:] * dn[n,s]) \
610-
+ ( -Ct[n,s+1,:] * ufs[n,s+1,:] * dn[n,s]) \
611-
+ w[n,s,:] * Cu[n,s,:] * ds[n,s] * dn [n,s] / Ts ) \
612-
/ ( + (-ufn[n,s,:] * dn[n,s]) \
613-
+ (-ufs[n,s,:] * dn[n,s]) \
614-
+ (ds[n,s] * dn [n,s] / Ts) )
615-
#calculate pickup
616-
pickup[n,s,:] = (w[n,s,:] * Cu[n,s,:]-Ct[n,s,:]) * dt/Ts
617-
#check for supply limitations and re-iterate concentration to account for supply limitations
618-
for nfs in range(0,nf):
619-
if pickup[n,s,nfs]>mass[n,s,0,nfs]:
620-
pickup[n,s,nfs] = mass[n,s,0,nfs]
621-
Ct[n,s,nfs] = (+ ( -Ct[n+1,s,nfs] * ufn[n+1,s,nfs] * dn[n,s]) \
622-
+ ( -Ct[n,s+1,nfs] * ufs[n,s+1,nfs] * dn[n,s]) \
623-
+ pickup[n,s,nfs] * ds[n,s] * dn [n,s] / dt ) \
624-
/ ( + (-ufn[n,s,nfs] * dn[n,s]) \
625-
+ (-ufs[n,s,nfs] * dn[n,s]))
626-
q[n,s]=3
627-
# The fourth guadrant including all remainnig unadressed cells
628-
for n in range(Ct.shape[0]-2,-1,-1):
629-
for s in range(1,Ct.shape[1]):
630-
if (not q[n,s]):
631-
if (ufn[n,s,0]<=0) and (ufs[n,s,0]>=0) and (ufn[n+1,s,0]<=0) and (ufs[n,s+1,0]>=0):
632-
# this is the fourth quadrant
633-
Ct[n,s,:] = (+ (Ct[n,s-1,:] * ufs[n,s,:] * dn[n,s]) \
634-
+ ( -Ct[n+1,s,:] * ufn[n+1,s,:] * dn[n,s]) \
635-
+ w[n,s,:] * Cu[n,s,:] * ds[n,s] * dn [n,s] / Ts ) \
636-
/ ( + (ufs[n,s+1,:] * dn[n,s]) \
637-
+ (-ufn[n,s,:] * dn[n,s]) \
638-
+ (ds[n,s] * dn [n,s] / Ts) )
639-
#calculate pickup
640-
pickup[n,s,:] = (w[n,s,:] * Cu[n,s,:]-Ct[n,s,:]) * dt/Ts
641-
#check for supply limitations and re-iterate concentration to account for supply limitations
642-
for nfs in range(0,nf):
643-
if pickup[n,s,nfs]>mass[n,s,0,nfs]:
644-
pickup[n,s,nfs] = mass[n,s,0,nfs]
645-
Ct[n,s,nfs] = (+ (Ct[n,s-1,nfs] * ufs[n,s,nfs] * dn[n,s]) \
646-
+ ( -Ct[n+1,s,nfs] * ufn[n+1,s,nfs] * dn[n,s]) \
647-
+ pickup[n,s,nfs] * ds[n,s] * dn [n,s] / dt ) \
648-
/ ( + (ufs[n,s+1,nfs] * dn[n,s]) \
649-
+ (-ufn[n,s,nfs] * dn[n,s]))
650-
q[n,s]=4
651-
else:
652-
if (not n==0) and (not s==Ct.shape[1]-1):
653-
# This is where we apply a generic stencil where all posible directions on the cell boundaries are solved for.
654-
# all remaining cells will be calculated for and q=5 is assigned.
655-
# this stencil is nested in the q4 loop which is the final quadrant.
656-
# grid boundaries are filtered in both if statements.
657-
Ct[n,s,:] = (+ (ufn[n,s,0]>0) * (Ct[n-1,s,:] * ufn[n,s,:] * ds[n,s]) \
658-
+ (ufs[n,s,0]>0) * (Ct[n,s-1,:] * ufs[n,s,:] * dn[n,s]) \
659-
+ (ufn[n+1,s,0]<0) * ( -Ct[n+1,s,:] * ufn[n+1,s,:] * dn[n,s]) \
660-
+ (ufs[n,s+1,0]<0) * ( -Ct[n,s+1,:] * ufs[n,s+1,:] * dn[n,s]) \
661-
+ w[n,s,:] * Cu[n,s,:] * ds[n,s] * dn [n,s] / Ts ) \
662-
/ ( + (ufn[n+1,s,0]>0) * (ufn[n+1,s,:] * ds[n,s]) \
663-
+ (ufs[n,s+1,0]>0) * (ufs[n,s+1,:] * dn[n,s]) \
664-
+ (ufn[n,s,0]<0) * (-ufn[n,s,:] * dn[n,s]) \
665-
+ (ufs[n,s,0]<0) * (-ufs[n,s,:] * dn[n,s]) \
666-
+ (ds[n,s] * dn [n,s] / Ts) )
667-
#calculate pickup
668-
pickup[n,s,:] = (w[n,s,:] * Cu[n,s,:]-Ct[n,s,:]) * dt/Ts
669-
#check for supply limitations and re-iterate concentration to account for supply limitations
670-
for nfs in range(0,nf):
671-
if pickup[n,s,nfs]>mass[n,s,0,nfs]:
672-
pickup[n,s,nfs] = mass[n,s,0,nfs]
673-
Ct[n,s,nfs] = (+ (ufn[n,s,0]>0) * (Ct[n-1,s,nfs] * ufn[n,s,nfs] * ds[n,s]) \
674-
+ (ufs[n,s,0]>0) * (Ct[n,s-1,nfs] * ufs[n,s,nfs] * dn[n,s]) \
675-
+ (ufn[n+1,s,0]<0) * ( -Ct[n+1,s,nfs] * ufn[n+1,s,nfs] * dn[n,s]) \
676-
+ (ufs[n,s+1,0]<0) * ( -Ct[n,s+1,nfs] * ufs[n,s+1,nfs] * dn[n,s]) \
677-
+ pickup[n,s,nfs] * ds[n,s] * dn [n,s] / dt ) \
678-
/ ( + (ufn[n+1,s,0]>0) * (ufn[n+1,s,nfs] * ds[n,s]) \
679-
+ (ufs[n,s+1,0]>0) * (ufs[n,s+1,nfs] * dn[n,s]) \
680-
+ (ufn[n,s,0]<0) * (-ufn[n,s,nfs] * dn[n,s]) \
681-
+ (ufs[n,s,0]<0) * (-ufs[n,s,nfs] * dn[n,s]))
682-
q[n,s]=5
558+
# The First quadrant (Numba-optimized)
559+
_solve_quadrant1(Ct, Cu, mass, pickup, dt, Ts, ds, dn, ufs, ufn, w, visited, quad, nf)
560+
561+
# The second quadrant (Numba-optimized)
562+
_solve_quadrant2(Ct, Cu, mass, pickup, dt, Ts, ds, dn, ufs, ufn, w, visited, quad, nf)
563+
564+
# The third quadrant (Numba-optimized)
565+
_solve_quadrant3(Ct, Cu, mass, pickup, dt, Ts, ds, dn, ufs, ufn, w, visited, quad, nf)
566+
567+
# The fourth quadrant (Numba-optimized)
568+
_solve_quadrant4(Ct, Cu, mass, pickup, dt, Ts, ds, dn, ufs, ufn, w, visited, quad, nf)
569+
570+
# Generic stencil for remaining cells including boundaries (Numba-optimized)
571+
_solve_generic_stencil(Ct, Cu, mass, pickup, dt, Ts, ds, dn, ufs, ufn, w, visited, quad, nf)
683572

684573

685574
k+=1
686-
687-
# print(k)
688575

576+
# # plot Ct
577+
# import matplotlib.pyplot as plt
578+
# plt.imshow(quad[:10,:10], origin='lower')
579+
# # plt.colorbar()
580+
# plt.title('Concentration after %d sweeps' % k)
581+
# plt.show()
582+
# plt.imshow(Ct[:50,:50], origin='lower')
583+
# # plt.colorbar()
584+
# plt.title('Concentration after %d sweeps' % k)
585+
# plt.show()
586+
# plt.plot(pickup[0,:,0])
587+
# plt.plot(pickup[-1,:,0])
588+
# plt.show()
589+
590+
# print(k)
591+
592+
689593
# print("q1 = " + str(np.sum(q==1)) + " q2 = " + str(np.sum(q==2)) \
690594
# + " q3 = " + str(np.sum(q==3)) + " q4 = " + str(np.sum(q==4)) \
691595
# + " q5 = " + str(np.sum(q==5)))

0 commit comments

Comments
 (0)