On 2014-01-08 15:21, Anders Logg wrote:
I would claim that the connectivity is stored very efficiently. The
simplest example is D--0 connectivity for a mesh which is for each
cell which vertices belong to it. That data is stored as one big array
of integers, something like
0 1 2 3 0 1 2 4 ...
which means that tetrahedron 0 has vertices 0 1 2 3, tetrahedron 1 has
vertices 0 1 2 4 etc.
There are D + 1 different kinds of entities in a mesh. For a
tetrahedron we have vertex, edge, face, cell and so the total number
of connectivities that may be computed is (D + 1)*(D + 1). Not all
these are needed, but they can all be computed.
For solving Poisson's equation, we first need D--0. To see which
connectivities are computed, one can do info(mesh, True) to print the
following little table:
0 1 2 3
0 - - - -
1 - - - -
2 - - - -
3 x - - -
To set boundary conditions, one needs to create the faces of the mesh
(which are not stored a priori). One will then get the following
connectivities:
0 1 2 3
0 - - - x
1 - - - -
2 x - - -
3 x - x x
Here we see the following connectivities:
3--0 = the vertices of all cells = the cells
0--3 = the cells connected to all vertices
3--3 = the cells connected to all cells (via vertices)
2--0 = the vertices of all faces = the faces
3--2 = the faces of all cells
These get computed in order:
0--3 is computed from 3--0 (by "inversion")
3--3 is computed from 3--0 and 0--3
2--0 and 3--2 are computed from 3--3 by a local search
3--3 is needed in order for a cell to communicate with its neighboring
cells to decide on how to number the common face (if any).
3--3 connectivity is *undefined*. DOLFIN presently assumes that 3--3 ==
3--0--3. To number a common face, what's required is 3--2 and 2--3. In
Chris's test, 3--3 uses ~17 times more memory than 3--2.
Garth
Once the faces have been computed, the other information can be thrown
away to save memory. I suggest experimenting with initializing the
connectivities explicitly before setting boundary conditions, then
clear those that are not needed:
mesh.topology()(3,3).clear()
That should save some memory. It is conceivable that we can make
improvements to TopologyComputation.cpp so that connectivities no
longer needed are deleted on the fly once they have been used to build
up the connectivities actually requested.
--
Anders
On Wed, Jan 08, 2014 at 02:50:43PM +0000, Chris Richardson wrote:
On 08/01/2014 14:43, Garth N. Wells wrote:
>On 2014-01-08 14:29, Chris Richardson wrote:
>>I patched MeshTopology.cpp to print out more information.
>>Looks like most of the memory is being using in MeshConnectivity 3--3.
>>I'm not sure what that means...
>>
>
>I recall some discussions on this before. d--d connectivity doesn't
>make sense because what constitutes a connection is undefined. For the
>d--d case, DOLFIN (in TopologyComputation.cpp) is assuming a shared
>vertex constitutes a connection, which in 3D and for d=3 gives a lot
>of connections.
>
Seems like it was explicitly wanted for some reason:-
TopologyComputation.cpp line 84
// Compute connectivity dim - dim if not already computed
compute_connectivity(mesh, mesh.topology().dim(),
mesh.topology().dim());
Chris
>Garth
>
>>
>>--- a/dolfin/mesh/MeshTopology.cpp
>>+++ b/dolfin/mesh/MeshTopology.cpp
>>@@ -16,7 +16,7 @@
>> // along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
>> //
>> // First added: 2006-05-08
>>-// Last changed: 2013-02-03
>>+// Last changed: 2014-01-08
>>
>> #include <numeric>
>> #include <sstream>
>>@@ -236,8 +236,22 @@ std::string MeshTopology::str(bool verbose) const
>> }
>> }
>> else
>>- s << "<MeshTopology of dimension " << _dim << ">";
>>-
>>+ {
>>+ s << "<MeshTopology of dimension " << _dim << ">\n";
>>+ s << "num_entities.size() = " << num_entities.size() << "\n";
>>+ s << "global_num_entities.size() = " <<
>>global_num_entities.size() << "\n";
>>+ s << "_global_indices.size() = " << _global_indices.size()
>><< "\n";
>>+ s << "_shared_entities.size() = " <<
>>_shared_entities.size() << "\n";
>>+ for(unsigned int i = 0; i < connectivity.size(); ++i)
>>+ {
>>+ s << "connectivity [" << i << "].size() = " <<
>>connectivity[i].size();
>>+ for (unsigned int j = 0; j<connectivity[i].size(); ++j)
>>+ {
>>+ s << connectivity[i][j].str(false) << "\n";
>>+ }
>>+ }
>>+ }
>>+
>> return s.str();
>> }
>>//-----------------------------------------------------------------------------
>>
>>
>>
>>from dolfin import *
>>from commands import getoutput
>>from os import getpid
>>set_log_active(False)
>>
>>def getRSSMemoryUsage():
>> mypid = getpid()
>> return eval(getoutput("ps -o rss %s" % mypid).split()[1])
>>
>>class MemoryUsage:
>> def __init__(self, s):
>> self.memory = 0
>> info_blue(' '*21+'RSS memory Increment Total')
>> self(s)
>>
>> def __call__(self, s):
>> self.prev = self.memory
>> self.memory = getRSSMemoryUsage()
>> #self.memory = memory_usage(False)[0]
>> info_blue('{0:26s} {1:10d} KB {2:10d} KB'.format(s,
>> self.memory-self.prev, self.memory))
>>
>>memoryusage = MemoryUsage('Starting weight of dolfin')
>>
>>mesh = UnitCubeMesh(40, 40, 40)
>>
>>memoryusage("Mesh")
>>
>>V = FunctionSpace(mesh, 'CG', 1)
>>
>>memoryusage('FunctionSpace')
>>
>>u, v = TrialFunction(V), TestFunction(V)
>>A = assemble(inner(grad(u), grad(v))*dx)
>>
>>memoryusage("Matrix assembly")
>>
>>b = assemble(Constant(6)*v*dx)
>>u = Function(V)
>>
>>memoryusage("Function")
>>
>>solve(A, u.vector(), b, 'gmres', 'hypre_amg')
>>
>>memoryusage('Solve')
>>
>>mesh.init(2)
>>print 'nfacets = ', mesh.num_facets()
>>print 'ncells = ', mesh.num_cells()
>>
>>print mesh.topology().str(False)
>>
>>memoryusage('mesh.init(2)')
>>
>>mesh.init(2, 3)
>>
>>memoryusage('mesh.init(2, 3)')
>>
>>bc = DirichletBC(V, Constant(0), DomainBoundary())
>>bc.apply(A, b)
>>
>>memoryusage('Boundary condition')
>>
>>solve(A, u.vector(), b, 'gmres', 'hypre_amg')
>>
>>memoryusage('New solve')
>>
>>
>>
>>
>> RSS memory Increment Total
>>Starting weight of dolfin 120684 KB 120684 KB
>>Mesh 16648 KB 137332 KB
>>FunctionSpace 35908 KB 173240 KB
>>Matrix assembly 14920 KB 188160 KB
>>Function 376 KB 188536 KB
>>Solve 21360 KB 209896 KB
>>nfacets = 777600
>>ncells = 384000
>><MeshTopology of dimension 3>
>>num_entities.size() = 4
>>global_num_entities.size() = 4
>>_global_indices.size() = 4
>>_shared_entities.size() = 1
>>connectivity [0].size() = 4<MeshConnectivity 0 -- 0 of size 0>
>><MeshConnectivity 0 -- 1 of size 0>
>><MeshConnectivity 0 -- 2 of size 0>
>><MeshConnectivity 0 -- 3 of size 1536000>
>>connectivity [1].size() = 4<MeshConnectivity 1 -- 0 of size 0>
>><MeshConnectivity 1 -- 1 of size 0>
>><MeshConnectivity 1 -- 2 of size 0>
>><MeshConnectivity 1 -- 3 of size 0>
>>connectivity [2].size() = 4<MeshConnectivity 2 -- 0 of size 2332800>
>><MeshConnectivity 2 -- 1 of size 0>
>><MeshConnectivity 2 -- 2 of size 0>
>><MeshConnectivity 2 -- 3 of size 0>
>>connectivity [3].size() = 4<MeshConnectivity 3 -- 0 of size 1536000>
>><MeshConnectivity 3 -- 1 of size 0>
>><MeshConnectivity 3 -- 2 of size 1536000>
>><MeshConnectivity 3 -- 3 of size 25707504>
>>
>>mesh.init(2) 302072 KB 511968 KB
>>mesh.init(2, 3) 0 KB 511968 KB
>>Boundary condition 216 KB 512184 KB
>>New solve 4 KB 512188 KB
>>
>>
>>
>>_______________________________________________
>>fenics mailing list
>>[email protected]
>>http://fenicsproject.org/mailman/listinfo/fenics
_______________________________________________
fenics mailing list
[email protected]
http://fenicsproject.org/mailman/listinfo/fenics