Iterating over a mesh with a Python `for` loop is, as you've found, an incredibly inefficient way to do things. FiPy, like numpy it relies on, is intended to be used with vectorized operations.
As far as your approach, things that start with `_` in Python are internal implementation details and you should not depend on them. If you find cases in FiPy that absolutely require that you access `some._propertyName` or `some._methodName()`, then please file an issue explaining your need so that we can provide a public interface. In this case, there's no need to access `_array`. Just write >>> sourceGrid[..., i] = sourceRate >>> sinkGrid[..., i] = sinkRate HOWEVER, you are still relying on an internal implementation detail, specifically that a Grid is an array with known fastest and slowest varying axes. We have in FiPy's history switched from Fortran to C ordering, and we might conceivably switch back at some point. Further, if you every wanted to run your script on an unstructured mesh, then your system wouldn't work at all. `sourceCoords` presumably comes from some definition in terms of geometry rather than discrete mesh indices. FiPy is intended to work best with those geometric descriptions. If you described where `sourceCoords` came from, we could help with a more FiPyish way to get what you want. > On Apr 6, 2019, at 9:02 AM, Dario Panada <[email protected]> wrote: > > Good Afternoon (Morning) to all, > > I have an equation of type > > eq = TransientTerm() == DiffusionTerm(coeff=D) + sourceGrid - sinkGrid > > Where sourceGrid and sinkGrid are derived from values in a 3D grid. > > Is there any downside to declaring the grids as > > sourceGrid = CellVariable(name="source", mesh=Grid3D(dx=1, dy=1, dz=1, nx=20, > ny=20, nz=20)) > sinkGrid = CellVariable(name="sink", mesh=Grid3D(dx=1, dy=1, dz=1, > nx=20, ny=20, nz=20)) > > And populating them as: > > i = np.ravel_multi_index([coordinate[0], coordinate[1], coordinate[2]], (20, > 20, 20)) > > sourceGrid._array[i] = sourceRate > sinkGrid._array[i] = sinkRate > > The original procedure I was using (given below) where I called .setValue on > each coordinate is extremely time-consuming. Results seem to align, but of > course this doesn't mean it's right... Or if it's wrong, any specific advice > on how to achieve this? > > Thanks, > Dario > > Original approach (and there is an equivalent function for setupSinkGrid): > def setupSourceGrid_(self, sourceCoords, mesh): > sourceGrid = CellVariable(name="source", mesh=mesh, value=0) > sourceGrid.setValue(0.) > for pos, v in sourceCoords.iteritems(): > tmpGrid = [False for _ in range(8000)] > i = np.ravel_multi_index([pos[0], pos[1], pos[2]], (20, 20, 20)) > tmpGrid[i] = True > sourceGrid.setValue(v, where=tmpGrid) > > _______________________________________________ > fipy mailing list > [email protected] > http://www.ctcms.nist.gov/fipy > [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ] _______________________________________________ fipy mailing list [email protected] http://www.ctcms.nist.gov/fipy [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ]
