/* -*- mode: maxima -*- */
load("ssa_coeffs.mac");

/* Switch from the [-1,0,1] indexing to [1,2,3] indexing: */
/* coefficients of the first equation */
eq1_u_coeffs : genmatrix(lambda([i,j], c1u[i-2,j-2]), 3, 3)$
eq1_v_coeffs : genmatrix(lambda([i,j], c1v[i-2,j-2]), 3, 3)$

/* coefficients of the second equation */
eq2_u_coeffs : genmatrix(lambda([i,j], c2u[i-2,j-2]), 3, 3)$
eq2_v_coeffs : genmatrix(lambda([i,j], c2v[i-2,j-2]), 3, 3)$

/* Convert 3x3 matrix indices to the element number ranging from 1 to 9. */
I[row,col] := col + (row - 1) * 3$

/* build a matrix representing a neighborhood of a cell. S is the set
   of numbers indicating which neighbors are ice-free

   Here S is a set of ice-free cell numbers (from 1 to 9).

   1 2 3
   4 5 6
   7 8 9
 */
gen_neighborhood(S) := genmatrix(lambda([i,j], if elementp(I[i,j], S) then 0 else 1), 3, 3)$

/* "Weights" in expressions of centered differences as sums of
one-sided differences. Recall that *both* cells have to be "icy" for
us to use this one-sided difference. (Hence "a = 1 and b = 1".) */

weight(a,b) := if (a = 1 and b = 1) then 1 else 0$

/* generate "weights" using a matrix N corresponding to a neighborhood */
gen_weights(X) := [
  w[i-1, j-1/2] = weight(X[1,1], X[1,2]),
  w[i-1, j+1/2] = weight(X[1,2], X[1,3]),
  w[i-1/2, j-1] = weight(X[1,1], X[2,1]),
  w[i-1/2, j]   = weight(X[1,2], X[2,2]),
  w[i-1/2, j+1] = weight(X[1,3], X[2,3]),
  w[i, j-1/2]   = weight(X[2,1], X[2,2]),
  w[i, j+1/2]   = weight(X[2,2], X[2,3]),
  w[i+1/2, j-1] = weight(X[2,1], X[3,1]),
  w[i+1/2, j]   = weight(X[2,2], X[3,2]),
  w[i+1/2, j+1] = weight(X[2,3], X[3,3]),
  w[i+1, j-1/2] = weight(X[3,1], X[3,2]),
  w[i+1, j+1/2] = weight(X[3,2], X[3,3])
  ]$

coeffs_from_weights(W) := [
  at(eq1_u_coeffs, W),
  at(eq2_u_coeffs, W),
  at(eq1_v_coeffs, W),
  at(eq2_v_coeffs, W)
  ]$

/* compute coefficients of the SSA discretization corresponding to a
"neighborhood". N is a 3x3 matrix with ones (icy) and zeros
(ice-free). */

coeffs(N) := coeffs_from_weights(gen_weights(N))$

/* keep neighborhoods that result in discretizations with zeros on the diagonal */
check_neighborhood(N) := if every(lambda([M], is(M[2,2] = 0)), coeffs(N))
  then N else false$

check(S) := check_neighborhood(gen_neighborhood(S))$

/* skip 5 (neighborhoods of an ice-free cell are of no interest) */
P : powerset({1,2,3,4,6,7,8,9})$

result : listify(disjoin(false, map(check, P)));

length(result);

printf(true, "\\begin{align*}")$
for j:1 thru length(result) do
  block(
    printf(true, tex1(result[j])),
    if integerp(j / 4) then printf(true, "\\\\~%") else printf(true, " &~%"))$
printf(true, "\\end{align*}")$

