Little update:
I tried to implement a fix from this topic for phi1 in [0, 1]:
f = ufl.conditional(
ufl.gt(phi1, 0), ufl.conditional(
ufl.gt(phi1, 1), 0, phi1 / N1 * ufl.ln(phi1) + (1 - phi1) / N2 * ufl.ln(1 - phi1 ) + chi * phi1 * (1 - phi1)
),
0
)
After this fix it stopped crushing, but now I have large negative values in phi1:
After that I tried to make a fix for phi:
phi1 = ufl.variable(
ufl.conditional(ufl.gt(phi1, min_val), ufl.conditional(ufl.gt(phi1, 1), max_val, phi1), min_val)
)
With conditional present at the same time for phi1 and f, the crashes came up again. So by now the only working solution is manually check values:
for i in range(len(u.x.array[:])):
if (u.x.array[:][i] + du.x.array[i]) <= EPS:
du.x.array[i] = 0
u.x.array[:][i] = EPS
if (u.x.array[:][i] + du.x.array[i]) >= max_val:
du.x.array[i] = 0
u.x.array[:][i] = max_val
But in my opinion ignoring updates for finite elements looks like violations of the mass conservation law.