1 # SPDX-License-Identifier: GPL-2.0-or-later
10 from .utils_pip
import Pip
11 Pip
._ensure
_user
_site
_package
()
12 from numba
import jit
, njit
, guvectorize
, float64
, int32
, prange
13 from numba
.typed
import List
19 from .utils_pip import Pip
21 Pip.install('llvmlite')
23 from numba import jit, njit, guvectorize, float64, int32, prange
25 print('Tissue: Numba successfully installed!')
27 print('Tissue: Numba not loaded correctly. Try restarting Blender')
31 #from numba import jit, njit, guvectorize, float64, int32, prange
34 def numba_reaction_diffusion(n_verts
, n_edges
, edge_verts
, a
, b
, brush
, diff_a
, diff_b
, f
, k
, dt
, time_steps
):
35 arr
= np
.arange(n_edges
)*2
37 id1
= edge_verts
[arr
+1]
38 for i
in range(time_steps
):
39 lap_a
, lap_b
= rd_init_laplacian(n_verts
)
40 numba_rd_laplacian(id0
, id1
, a
, b
, lap_a
, lap_b
)
41 numba_rd_core(a
, b
, lap_a
, lap_b
, diff_a
, diff_b
, f
, k
, dt
)
42 numba_set_ab(a
,b
,brush
)
46 def integrate_field(n_edges
, id0
, id1
, values
, edge_flow
, mult
, time_steps
):
47 #n_edges = len(edge_flow)
48 for i
in range(time_steps
):
50 for j
in range(n_edges
):
53 values
[v0
] -= values0
[v1
] * edge_flow
[j
] * 0.001#mult[v1]
54 values
[v1
] += values0
[v0
] * edge_flow
[j
] * 0.001#mult[v0]
55 for j
in range(n_edges
):
58 values
[v0
] = max(values
[v0
],0)
59 values
[v1
] = max(values
[v1
],0)
63 def numba_reaction_diffusion_anisotropic(n_verts
, n_edges
, edge_verts
, a
, b
, brush
, diff_a
, diff_b
, f
, k
, dt
, time_steps
, grad
):
64 arr
= np
.arange(n_edges
)*2
66 id1
= edge_verts
[arr
+1]
67 #grad = weight_grad[id0] - weight_grad[id1]
69 #grad /= abs(np.max(grad))
70 #grad = grad*0.98 + 0.02
71 for i
in range(time_steps
):
72 lap_a
, lap_b
= rd_init_laplacian(n_verts
)
73 numba_rd_laplacian_anisotropic(id0
, id1
, a
, b
, lap_a
, lap_b
, grad
)
74 numba_rd_core(a
, b
, lap_a
, lap_b
, diff_a
, diff_b
, f
, k
, dt
)
75 numba_set_ab(a
,b
,brush
)
78 #@guvectorize(['(float64[:] ,float64[:] , float64[:], float64[:], float64[:], float64[:], float64[:], float64[:], float64)'],'(n),(n),(n),(n),(n),(n),(n),(n),()',target='parallel')
80 def numba_rd_core(a
, b
, lap_a
, lap_b
, diff_a
, diff_b
, f
, k
, dt
):
82 _f
= np
.full(n
, f
[0]) if len(f
) == 1 else f
83 _k
= np
.full(n
, k
[0]) if len(k
) == 1 else k
84 _diff_a
= np
.full(n
, diff_a
[0]) if len(diff_a
) == 1 else diff_a
85 _diff_b
= np
.full(n
, diff_b
[0]) if len(diff_b
) == 1 else diff_b
93 a
[i
] += (diff_ai
* lap_a
[i
] - ab2
+ fi
*(1-a
[i
]))*dt
94 b
[i
] += (diff_bi
* lap_b
[i
] + ab2
- (ki
+fi
)*b
[i
])*dt
97 def numba_rd_core_(a
, b
, lap_a
, lap_b
, diff_a
, diff_b
, f
, k
, dt
):
99 a
+= (diff_a
*lap_a
- ab2
+ f
*(1-a
))*dt
100 b
+= (diff_b
*lap_b
+ ab2
- (k
+f
)*b
)*dt
103 def numba_set_ab(a
, b
, brush
):
105 _brush
= np
.full(n
, brush
[0]) if len(brush
) == 1 else brush
106 for i
in prange(len(b
)):
108 if b
[i
] < 0: b
[i
] = 0
109 elif b
[i
] > 1: b
[i
] = 1
110 if a
[i
] < 0: a
[i
] = 0
111 elif a
[i
] > 1: a
[i
] = 1
114 #@guvectorize(['(float64[:] ,float64[:] ,float64[:] , float64[:], float64[:], float64[:])'],'(m),(m),(n),(n),(n),(n)',target='parallel')
116 def numba_rd_laplacian(id0
, id1
, a
, b
, lap_a
, lap_b
):
117 for i
in prange(len(id0
)):
120 lap_a
[v0
] += a
[v1
] - a
[v0
]
121 lap_a
[v1
] += a
[v0
] - a
[v1
]
122 lap_b
[v0
] += b
[v1
] - b
[v0
]
123 lap_b
[v1
] += b
[v0
] - b
[v1
]
127 def numba_rd_laplacian_anisotropic(id0
, id1
, a
, b
, lap_a
, lap_b
, grad
):
128 for i
in prange(len(id0
)):
131 lap_a
[v0
] += (a
[v1
] - a
[v0
])
132 lap_a
[v1
] += (a
[v0
] - a
[v1
])
133 lap_b
[v0
] -= (b
[v1
] - b
[v0
])*grad
[i
]
134 lap_b
[v1
] += (b
[v0
] - b
[v1
])*grad
[i
]
138 def numba_rd_neigh_vertices(edge_verts
):
139 n_edges
= len(edge_verts
)/2
140 id0
= np
.zeros(n_edges
)
141 id1
= np
.zeros(n_edges
)
142 for i
in prange(n_edges
):
143 id0
[i
] = edge_verts
[i
*2] # first vertex indices for each edge
144 id1
[i
] = edge_verts
[i
*2+1] # second vertex indices for each edge
147 #@guvectorize(['(float64[:] ,float64[:] , float64[:], float64[:], float64[:])'],'(m),(n),(n),(n),(n)',target='parallel')
150 def numba_rd_laplacian_(edge_verts
, a
, b
, lap_a
, lap_b
):
151 for i
in prange(len(edge_verts
)/2):
153 v1
= edge_verts
[i
*2+1]
154 lap_a
[v0
] += a
[v1
] - a
[v0
]
155 lap_a
[v1
] += a
[v0
] - a
[v1
]
156 lap_b
[v0
] += b
[v1
] - b
[v0
]
157 lap_b
[v1
] += b
[v0
] - b
[v1
]
161 def rd_fill_laplacian(lap_a
, lap_b
, id0
, id1
, lap_a0
, lap_b0
):
162 #for i, j, la0, lb0 in zip(id0,id1,lap_a0,lap_b0):
163 for index
in prange(len(id0
)):
174 def rd_init_laplacian(n_verts
):
175 lap_a
= np
.zeros(n_verts
)
176 lap_b
= np
.zeros(n_verts
)
181 def numba_reaction_diffusion(n_verts, n_edges, edge_verts, a, b, diff_a, diff_b, f, k, dt, time_steps, db):
182 arr = np.arange(n_edges)*2
183 id0 = edge_verts[arr] # first vertex indices for each edge
184 id1 = edge_verts[arr+1] # second vertex indices for each edge
185 #dgrad = abs(grad[id1] - grad[id0])
186 for i in range(time_steps):
187 lap_a = np.zeros(n_verts)
188 lap_b = np.zeros(n_verts)
190 lap_a0 = a[id1] - a[id0] # laplacian increment for first vertex of each edge
191 lap_b0 = b[id1] - b[id0] # laplacian increment for first vertex of each edge
195 for i, j, la0, lb0 in zip(id0,id1,lap_a0,lap_b0):
201 #a += eval("(diff_a*lap_a - ab2 + f*(1-a))*dt")
202 #b += eval("(diff_b*lap_b + ab2 - (k+f)*b)*dt")
203 a += (diff_a*lap_a - ab2 + f*(1-a))*dt
204 b += (diff_b*lap_b + ab2 - (k+f)*b)*dt
209 def numba_lerp2_(v00, v10, v01, v11, vx, vy):
211 co2 = np.zeros((sh[0],len(vx),sh[-1]))
212 for i in prange(len(v00)):
213 for j in prange(len(vx)):
214 for k in prange(len(v00[0][0])):
215 co0 = v00[i][0][k] + (v10[i][0][k] - v00[i][0][k]) * vx[j][0]
216 co1 = v01[i][0][k] + (v11[i][0][k] - v01[i][0][k]) * vx[j][0]
217 co2[i][j][k] = co0 + (co1 - co0) * vy[j][0]
222 def numba_lerp2_vec(v0, vx, vy):
223 n_faces = v0.shape[0]
224 co2 = np.zeros((n_faces,len(vx),3))
225 for i in prange(n_faces):
226 for j in prange(len(vx)):
228 co0 = v0[i][0][k] + (v0[i][1][k] - v0[i][0][k]) * vx[j][0]
229 co1 = v0[i][3][k] + (v0[i][2][k] - v0[i][3][k]) * vx[j][0]
230 co2[i][j][k] = co0 + (co1 - co0) * vy[j][0]
234 def numba_lerp2__(val, vx, vy):
236 co2 = np.zeros((n_faces,len(vx),1))
237 for i in prange(n_faces):
238 for j in prange(len(vx)):
239 co0 = val[i][0] + (val[i][1] - val[i][0]) * val[j][0]
240 co1 = val[i][3] + (val[i][2] - val[i][3]) * val[j][0]
241 co2[i][j][0] = co0 + (co1 - co0) * vy[j][0]
246 def numba_combine_and_flatten(arrays
):
247 n_faces
= len(arrays
)
248 n_verts
= len(arrays
[0])
249 new_list
= [0.0]*n_faces
*n_verts
*3
250 for i
in prange(n_faces
):
251 for j
in prange(n_verts
):
253 new_list
[i
*n_verts
*3+j
*3+k
] = arrays
[i
][j
,k
]
257 def numba_calc_thickness_area_weight(co2
,n2
,vz
,a
,weight
):
264 nw
= weight
.shape
[1]-1
265 co3
= np
.zeros((n_patches
,n_verts
,n_co
))
266 for i
in prange(n_patches
):
267 for j
in prange(n_verts
):
268 for k
in prange(n_co
):
269 co3
[i
,j
,k
] = co2
[i
,j
,k
] + n2
[i
,min(j
,nn
),k
] * vz
[0,j
,0] * a
[i
,min(j
,na
),0] * weight
[i
,min(j
,nw
),0]
273 def numba_calc_thickness_area(co2,n2,vz,a):
278 #co3 = [0.0]*n_patches*n_verts*n_co #np.zeros((n_patches,n_verts,n_co))
279 co3 = np.zeros((n_patches,n_verts,n_co))
280 for i in prange(n_patches):
281 for j in prange(n_verts):
282 for k in prange(n_co):
283 #co3[i,j,k] = co2[i,j,k] + n2[i,j,k] * vz[0,j,0] * a[i,j,0]
284 co3[i,j,k] = co2[i,j,k] + n2[i,min(j,nor_len),k] * vz[0,j,0] * a[i,j,0]
288 def numba_calc_thickness_weight(co2
,n2
,vz
,weight
):
294 nw
= weight
.shape
[1]-1
295 co3
= np
.zeros((n_patches
,n_verts
,n_co
))
296 for i
in prange(n_patches
):
297 for j
in prange(n_verts
):
298 for k
in prange(n_co
):
299 co3
[i
,j
,k
] = co2
[i
,j
,k
] + n2
[i
,min(j
,nn
),k
] * vz
[0,j
,0] * weight
[i
,min(j
,nw
),0]
303 def numba_calc_thickness(co2
,n2
,vz
):
309 co3
= np
.zeros((n_patches
,n_verts
,n_co
))
310 for i
in prange(n_patches
):
311 for j
in prange(n_verts
):
312 for k
in prange(n_co
):
313 co3
[i
,j
,k
] = co2
[i
,j
,k
] + n2
[i
,min(j
,nn
),k
] * vz
[0,j
,0]
317 def numba_interp_points(v00
, v10
, v01
, v11
, vx
, vy
):
318 n_patches
= v00
.shape
[0]
319 n_verts
= vx
.shape
[1]
320 n_verts0
= v00
.shape
[1]
322 vxy
= np
.zeros((n_patches
,n_verts
,n_co
))
323 for i
in prange(n_patches
):
324 for j
in prange(n_verts
):
325 j0
= min(j
,n_verts0
-1)
326 for k
in prange(n_co
):
327 co0
= v00
[i
,j0
,k
] + (v10
[i
,j0
,k
] - v00
[i
,j0
,k
]) * vx
[0,j
,0]
328 co1
= v01
[i
,j0
,k
] + (v11
[i
,j0
,k
] - v01
[i
,j0
,k
]) * vx
[0,j
,0]
329 vxy
[i
,j
,k
] = co0
+ (co1
- co0
) * vy
[0,j
,0]
333 def numba_interp_points_sk(v00
, v10
, v01
, v11
, vx
, vy
):
334 n_patches
= v00
.shape
[0]
336 n_verts
= v00
.shape
[2]
338 vxy
= np
.zeros((n_patches
,n_sk
,n_verts
,n_co
))
339 for i
in prange(n_patches
):
340 for sk
in prange(n_sk
):
341 for j
in prange(n_verts
):
342 for k
in prange(n_co
):
343 co0
= v00
[i
,sk
,j
,k
] + (v10
[i
,sk
,j
,k
] - v00
[i
,sk
,j
,k
]) * vx
[0,sk
,j
,0]
344 co1
= v01
[i
,sk
,j
,k
] + (v11
[i
,sk
,j
,k
] - v01
[i
,sk
,j
,k
]) * vx
[0,sk
,j
,0]
345 vxy
[i
,sk
,j
,k
] = co0
+ (co1
- co0
) * vy
[0,sk
,j
,0]
349 def numba_lerp(v0
, v1
, x
):
350 return v0
+ (v1
- v0
) * x
353 def numba_lerp2(v00
, v10
, v01
, v11
, vx
, vy
):
354 co0
= numba_lerp(v00
, v10
, vx
)
355 co1
= numba_lerp(v01
, v11
, vx
)
356 co2
= numba_lerp(co0
, co1
, vy
)
360 def numba_lerp2_________________(v00
, v10
, v01
, v11
, vx
, vy
):
364 co2
= np
.zeros((ni
,nj
,nk
))
372 co0
= _v00
+ (_v10
- _v00
) * vx
[i
,j
,k
]
373 co1
= _v01
+ (_v11
- _v01
) * vx
[i
,j
,k
]
374 co2
[i
,j
,k
] = co0
+ (co1
- co0
) * vy
[i
,j
,k
]
378 def numba_lerp2_4(v00
, v10
, v01
, v11
, vx
, vy
):
382 nw
= len(v00
[0][0][0])
383 co2
= np
.zeros((ni
,nj
,nk
,nw
))
392 co0
= _v00
+ (_v10
- _v00
) * vx
[i
,j
,k
]
393 co1
= _v01
+ (_v11
- _v01
) * vx
[i
,j
,k
]
394 co2
[i
,j
,k
] = co0
+ (co1
- co0
) * vy
[i
,j
,k
]
399 # print("Tissue: Numba cannot be installed. Try to restart Blender.")