! apply red-black iteration to a nonlinear diffusion equation extracted from a
! variational principle via symbolic differentiation.
! ============================================================================
! minimize mu∗(nabla u)^2 - px∗u, with mu=0.05+exp[-(nabla u)^2/m]

USE gnuplot
USE symbolic
! USE rtchecks
m=10   ! define some constants
REAL u(0..nx,0..nx)=0, px=1   ! u is the unknown
INTEGER f(0..nx,0..nx)    !( f is a quantized level function defining (at first
  order) the solution domain as the one where f=1 !)
DO f(ix,iy)=IF (ix/nx-0.5)^2+(iy/nx-0.5)^2<0.25 THEN 1 ELSE 0 FOR ALL ix,iy
! circular domain is defined here
DO u(i,j)=3∗f(i,j) FOR i=5 TO nx DIV 2 AND j=5 TO nx DIV 2
! initialize the iteration
    ! mod here is centered in i+1/2, j+1/2
! these three == deferred assignments define the symbolic function J
! (of yet undeclared array lu) to be minimized.
LOOP iter FOR n=1 TO 100000
  REAL maxrsd=0
  LOOP FOR parity=0 TO 1 AND ix=1 TO nx-1 AND iy=2-(ix+parity) MOD 2 TO nx-1 BY 2 EXCEPT f(ix,iy)=0
  !(this is the red-black iteration. Notice use of EXCEPT to exclude the region where f=0!)
    lu=^u(ix+(-1..1),iy+(-1..1))   !( define lu as a subarray of u centered
      in ix,iy. ^ specifies that this is not a copy but a pointer !)
    rsd=SUM D(J,lu(0,0))-px FOR i=-1 TO 0 AND j=-1 TO 0 !( current residual
      calculated as the symbolic derivative of J, and then averaged in 0,0.
      i,j are passed implicitly to J which acts as a macro or INLINE FUNCTION!)
      mu0=SUM mu FOR i=-1 TO 0 AND j=-1 TO 0   !( viscosity in 0,0. Here too,
      mu is expanded at compile time and contains i,j implicitly !)    
    lu(0,0)=~-dx∗dx/2/mu0∗rsd   ! under-relaxed Gauss-Seidel update
    maxrsd=MAX(maxrsd,ABS(rsd))   ! residual for convergence verification
  fr=dx^2∗(SUM u(ix,iy) FOR ALL ix,iy)
  px=px∗(0.8+0.2/fr)   ! feed back upon px so as to normalize the mean velocity
  IF n MOD 10 =0 THEN WRITE maxrsd; SPLOT u
  IF maxrsd<1E-2 THEN EXIT iter   ! loops can be exited by name