0

I am currently using a sweep loop to solve a differential equation (eq0) with respect to my cell variable phi using FiPy in python. Because my equation is non-linear, I am using a sweep loop as shown in an extract of my code below.

while  res0 > resphi_tol:    
        res0 = eq0.sweep(var=phi, dt=dt)

But I keep getting the following error:

C:\Python27\lib\site-packages\fipy\variables\variable.py:1100: RuntimeWarning: invalid value encountered in power return self._BinaryOperatorVariable(lambda a,b: pow(a,b), other, value1mattersForUnit=True)
C:\Python27\lib\site-packages\fipy\variables\variable.py:1186: RuntimeWarning: invalid value encountered in less_equal return self._BinaryOperatorVariable(lambda a,b: a<=b, other)
Traceback (most recent call last):
.. File "SBM_sphere3.py", line 59, in
....res0 = eq0.sweep(var=phi, dt=dt)
.. File "C:\Python27\lib\site-packages\fipy\terms\term.py", line 207, in sweep
....solver._solve()
.. File "C:\Python27\lib\site-packages\fipy\solvers\pysparse\pysparseSolver.py", line 68, in _solve
....self.solve(self.matrix, array, self.RHSvector)
.. File "C:\Python27\lib\site-packages\fipy\solvers\pysparse\linearLUSolver.py", line 53, in _solve__
....LU = superlu.factorize(L.matrix.to_csr())
.. File "C:\Python27\lib\site-packages\pysparse\misc__init__.py", line 29, in newFunc
....return func(*args, **kwargs)
.. File "C:\Python27\lib\site-packages\pysparse__init__.py", line 47, in factorize
....return self.factorizeFnc(*args, **kwargs)
RuntimeError: Factor is exactly singular

I am pretty sure this error is due to term phi^(2/3) present in eq0. If I replace this term by abs(phi)^(2/3), the error goes away.

I assume the sweep loop returns a negative value for a few cells in phi at some point, resulting in error since we can't power a negative value with a non-integer exponent.

So my question is: is there a way to force sweep to avoid negative solutions?

I have tried to include a line that sets all negative values to 0 before sweeping:

while  res0 > resphi_tol:    
        phi.setValue(0.,where=phi<0.)
        res0 = eq0.sweep(var=phi, dt=dt)

The error is still there (because sweep tries to calculate the new matrix of coefficients just after solving the linearized system?).

Edit: I'm using Python 2.7.14 with FiPy 3.2. I'm sharing below the parts of my code which I think are relevant for the query. The entire code is quite extense. Some context: I'm solving balance equations for suspension flow. eq0 corresponds to the mass balance equation for the particle phase, and phi is the volume fraction of particles.

from pylab import *
from fipy import *
from fipy.tools import numerix
from scipy import misc
import osmotic_pressure_functions as opf

kic=96.91
lic=0.049

dt=1.e-2
steps=10

tol=1.e-6

Nx=8
Ny=4
Lx=Nx/Ny
dL=1./Ny

mesh = PeriodicGrid2DTopBottom(nx=Nx, ny=Ny, dx=dL, dy=dL)
x, y = mesh.cellCenters

phi = CellVariable(mesh=mesh, hasOld=True, value=0.,name='Volume fraction')

phi.constrain(0.01, mesh.facesLeft)
phi.constrain(0., mesh.facesRight)

rad=0.1

var1 = DistanceVariable(name='distance to center', mesh=mesh, value=numerix.sqrt((x-Nx*dL/2.)**2+(y-Ny*dL/2.)**2))

pi_ci = CellVariable(mesh=mesh, value=0.,name='Colloid-interface energy map')
pi_ci.setValue(kic*exp(-1.*(var1-rad)/(1.*lic)), where=(var1 > rad))
pi_ci.setValue(kic, where=(var1 <= rad))

def pi_cc_entr(x):
    return opf.vantHoff(x)

def pi_cc_vdw(x):
    return opf.van_der_waals(x,0.74,0.1)

def pi_cc(x):
    return pi_cc_entr(x) + pi_cc_vdw(x)

diffusioncoeff = misc.derivative(pi_cc,phi,dx=1.e-6)

eq0 = TransientTerm() + ConvectionTerm(-pi_ci.faceGrad) == DiffusionTerm(coeff=diffusioncoeff)

step=0
t=0.

for step in range(steps):
    print 'Step ', step

    phi.updateOld()
    res0 = 1e+10
    while res0 > tol :
        phi.setValue(0., where=phi<0)
        res0 = eq0.sweep(var=phi, dt=dt) #ERROR HAPPENS HERE

Functions vantHoff and van_der_waals are being defined in a separate file.

def vantHoff(phi):
    return phi

def van_der_waals(phi,phi_cp,nd_v):
    return (nd_v*phi**3) / ((phi_cp-(phi_cp)**(1./3.)*(phi)**(2./3.))**2)
  • Thank you for providing more details. I'm afraid though, that this is still not a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), so I can't reproduce the error you're seeing. (1) `phi.setValue(0.,where=phi<0.)` should avoid this error, but you say it doesn't work. (2) Negative values of `phi` shouldn't happen; try a smaller value of dt (3) Please post the entire traceback before the error so we can see exactly what code is triggering it. – jeguyer Sep 19 '19 at 19:47
  • Hi again, Mr Guyer. I have included the traceback from the error and a reproducible code if you wish to run it from your computer. – Sergio Cunha Sep 23 '19 at 14:59

1 Answers1

0

The error arises because the coefficient of the DiffusionTerm is all nan. This, in turn, is because the diffusion coefficient is defined as

(((((((Volume fraction + -1e-06) + (((pow((Volume fraction + -1e-06), 3)) * 0.1) / (pow((0.74 - ((pow((Volume fraction + -1e-06), 0.6666666666666666)) * 0.9045041696510275)), 2)))) * -0.5) + 0.0) + (((Volume fraction + 0.0) + (((pow((Volume fraction + 0.0), 3)) * 0.1) / (pow((0.74 - ((pow((Volume fraction + 0.0), 0.6666666666666666)) * 0.9045041696510275)), 2)))) * 0.0)) + (((Volume fraction + 1e-06) + (((pow((Volume fraction + 1e-06), 3)) * 0.1) / (pow((0.74 - ((pow((Volume fraction + 1e-06), 0.6666666666666666)) * 0.9045041696510275)), 2)))) * 0.5)) / 1e-06)

and Volume fraction (phi) is all zero, so -1e-06 is being raised to fractional powers, which is undefined.

The factors of -1e-06 arise from your use of scipy.misc.derivative() to apparently calculate symbolic derivatives? I don't believe it's intended for that. You'll likely have better luck with SymPy.

jeguyer
  • 2,379
  • 1
  • 11
  • 15
  • My intention was not to calculate symbolic derivatives, but numeric derivatives of pi_cc(x) computed at x = phi. I believe the factor -1e-06 you mentioned is the dx from the central derivative scheme scipy is using. The derivatives are calculated correctly as long as I set phi to values higher than 1.e-06. Just for information, I modified my code to use forward differences to recalculate diffusioncoeff values that are nan. Also, thank you for your replies. They have been very helpful for my project. – Sergio Cunha Sep 26 '19 at 12:04