defining a multivariate gaussian initial condition in FiPy

84 Views Asked by At

I'm trying to use a multivariate gaussian initial condition for a Fipy integration.

I'm currently using the following code:

from fipy import CellVariable, Grid2D, Viewer
from scipy.stats import multivariate_normal
import numpy as np
import matplotlib.pyplot as plt
plt.close('all')
# Define the grid and cell variable
nx = 40
ny = 100
dx = 1.0
dy = 1.90
mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
phi = CellVariable(name="phi", mesh=mesh)

# Set the Gaussian initial condition
mean = [nx * dx / 2, ny * dy / 2]  # Center of the Gaussian surface
covariance = [[10, 0], [0, 5]]  # Covariance matrix

# Generate coordinates for the grid
X, Y = mesh.cellCenters[0], mesh.cellCenters[1]

# Evaluate the Gaussian surface
gaussian_surface = multivariate_normal(mean=mean, cov=covariance)
Z = np.zeros_like(X)
Xm=X.value.reshape([nx,ny])
Ym=Y.value.reshape([nx,ny])

Z = gaussian_surface.pdf(np.column_stack((X.value.flat, Y.value.flat)))

# Assign the Gaussian surface to the cell variable
phi.setValue(Z)

plt.pcolor(Xm,Ym,phi.value.reshape((nx, ny)), cmap='plasma')

plt.colorbar(label='phi')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Gaussian Initial Condition')
plt.show()

The code I have works well for square grids: enter image description here

But It does not work well for rectangular ones:

enter image description here

How can I fix it?

2

There are 2 best solutions below

0
On BEST ANSWER

The OP's code gives the following warning:

/tmp/ipykernel_9302/2008401024.py:32: UserWarning: The input coordinates to 
pcolor are interpreted as cell centers, but are not monotonically 
increasing or decreasing. This may lead to incorrectly calculated 
cell edges, in which case, please supply explicit cell edges to 
pcolor.  plt.pcolor(Xm,Ym,phi.value.reshape((nx, ny)), cmap='plasma')

This hints at a reshaping problem, due to row-major matrix storage being treated as column-major (or vice-versa). So, to fix it, we can simply reverse the (nx, ny) in the final steps using nx, ny = ny, nx. As expected, the OP's original code worked fine when nx=ny. The corrected version is shown below for completeness:

from fipy import CellVariable, Grid2D, Viewer
from scipy.stats import multivariate_normal
import numpy as np
import matplotlib.pyplot as plt
plt.close('all')
# Define the grid and cell variable
nx = 40
ny = 100
dx = 1.0
dy = 1.90
mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
phi = CellVariable(name="phi", mesh=mesh)

# Set the Gaussian initial condition
mean = [nx * dx / 2, ny * dy / 2]  # Center of the Gaussian surface
covariance = [[10, 0], [0, 5]]  # Covariance matrix

# Generate coordinates for the grid
X, Y = mesh.cellCenters[0], mesh.cellCenters[1]

# Evaluate the Gaussian surface
gaussian_surface = multivariate_normal(mean=mean, cov=covariance)
Z = np.zeros_like(X)

nx, ny = ny, nx

Xm=X.value.reshape([nx,ny])
Ym=Y.value.reshape([nx,ny])

Z = gaussian_surface.pdf(np.column_stack((X.value.flat, Y.value.flat)))

# Assign the Gaussian surface to the cell variable
phi.setValue(Z)

plt.pcolor(Xm,Ym,phi.value.reshape((nx, ny)), cmap='plasma')

plt.colorbar(label='phi')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Gaussian Initial Condition')
plt.show()

Output:

enter image description here

0
On

As you can see by invoking Viewer(vars=phi).plot(), there is nothing wrong with what's in phi, so I think the issue is in your invocation of plt.pcolor(). I don't use it, so I can't advise, but I'd guess it has something to do with inconsistent data shapes between Xm, Ym, and phi.value.reshape((nx, ny)).

Gaussian distribution on a rectangular FiPy mesh