Changeset 4471


Ignore:
Timestamp:
May 21, 2007, 5:56:14 PM (17 years ago)
Author:
ole
Message:

Rewrote quantity.get_vertex_values in C and introduced new data structure for keeping track of which triangles contribute to each node. This addresses ticket:154 by making storing orders of magnitudes faster.
There is no longer the option of specifying 'reduction' as averaging is now hard wired.

Location:
anuga_core
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/documentation/user_manual/anuga_user_manual.tex

    r4404 r4471  
    17731773
    17741774
    1775 \begin{methoddesc} {set\_store\_vertices\_uniquely}{flag, reduction=None}
     1775\begin{methoddesc} {set\_store\_vertices\_uniquely}{flag}
    17761776Decide whether vertex values should be stored uniquely as
    17771777computed in the model or whether they should be reduced to one
    1778 value per vertex using self.reduction.
     1778value per vertex using averaging.
    17791779\end{methoddesc}
    17801780
  • anuga_core/source/anuga/abstract_2d_finite_volumes/general_mesh.py

    r4460 r4471  
    394394        """
    395395
     396        # FIXME (Ole): Refactor this based on algorithm in test and get
     397        # rid of the old vertexlist
     398       
    396399        vertexlist = [None]*self.number_of_nodes
    397400        for i in range(self.number_of_triangles):
     
    410413                vertexlist[v].append( (i, vertex_id) )
    411414
     415
     416        # Register number of triangles touching each nodes
     417        number_of_triangles_per_node = zeros(self.number_of_nodes)       
     418        number_of_entries = 0       
     419        for i, vertices in enumerate(vertexlist):
     420            try:
     421                v = len(vertices)
     422            except:
     423                v = 0 # Lone node - e.g. not part of the mesh
     424               
     425            number_of_triangles_per_node[i] = v
     426            number_of_entries += v
     427               
     428
     429        # Build vertex value index array
     430        vertex_value_indices = zeros(number_of_entries)
     431        k = 0
     432        for vertices in vertexlist:
     433            if vertices is not None:
     434                for i, v_id in vertices:
     435                    vertex_value_indices[k] = 3*i + v_id
     436
     437                    k += 1
     438
     439        assert k == number_of_entries   
    412440        self.vertexlist = vertexlist
     441
     442        self.number_of_triangles_per_node = number_of_triangles_per_node
     443        self.vertex_value_indices = vertex_value_indices
     444        self.vertexlist = vertexlist
     445
     446        #print
     447        #print number_of_triangles_per_node
     448        #print vertex_value_indices
     449        #print vertexlist
    413450
    414451
  • anuga_core/source/anuga/abstract_2d_finite_volumes/neighbour_mesh.py

    r4376 r4471  
    701701        #
    702702        #See domain.set_boundary
     703
     704        # Check integrity of vertex_value_indices
     705        current_node = 0
     706        k = 0 # Track triangles touching on node
     707        for index in self.vertex_value_indices:
     708
     709            if self.number_of_triangles_per_node[current_node] == 0:
     710                # Node is lone - i.e. not part of the mesh
     711                continue
     712           
     713            k += 1
     714           
     715            volume_id = index / 3
     716            vertex_id = index % 3
     717           
     718            msg = 'Triangle %d, vertex %d points to %d. Should have been %d'\
     719                  %(volume_id, vertex_id, self.triangles[volume_id, vertex_id], current_node)
     720            assert self.triangles[volume_id, vertex_id] == current_node, msg
     721                       
     722            if self.number_of_triangles_per_node[current_node] == k:
     723                # Move on to next node
     724                k = 0
     725                current_node += 1
     726
    703727
    704728    def get_lone_vertices(self):
  • anuga_core/source/anuga/abstract_2d_finite_volumes/quantity.py

    r4254 r4471  
    943943               
    944944                # FIXME (Ole): Should we merge this with get_vertex_values
    945                 # and use the concept of a reduction operator?
    946945                sum = 0
    947946                for triangle_id, vertex_id in triangles:
     
    10331032                          xy=True,
    10341033                          smooth=None,
    1035                           precision=None,
    1036                           reduction=None):
     1034                          precision=None):
    10371035        """Return vertex values like an OBJ format i.e. one value per node.
    10381036
     
    10461044
    10471045        if smooth is True, vertex values corresponding to one common
    1048         coordinate set will be smoothed according to the given
    1049         reduction operator. In this case vertex coordinates will be
     1046        coordinate set will be smoothed by taking the average of vertex values for each node.
     1047        In this case vertex coordinates will be
    10501048        de-duplicated corresponding to the original nodes as obtained from
    10511049        the method general_mesh.get_nodes()
     
    10781076
    10791077        if smooth is True:
    1080             # Ensure continuous vertex values by combining
    1081             # values at each node using the reduction operator
     1078            # Ensure continuous vertex values by averaging
     1079            # values at each node
    10821080           
    1083             if reduction is None:
    1084                 # Take default from domain               
    1085                 reduction = self.domain.reduction
    1086 
    10871081            V = self.domain.get_triangles()
    10881082            N = self.domain.number_of_full_nodes # Ignore ghost nodes if any
    1089             A = zeros(N, precision)
     1083            A = zeros(N, Float)
    10901084            points = self.domain.get_nodes()           
    1091 
    1092             # Reduction loop
    1093             for k in range(N):
    1094                 L = self.domain.vertexlist[k]
    1095 
    1096                 # Go through all triangle, vertex pairs
    1097                 # contributing to vertex k and register vertex value
    1098                 if L is None: continue # In case there are unused points
    1099                 contributions = []
    1100                 for volume_id, vertex_id in L:
     1085           
     1086            if 1:
     1087                # Fast C version
     1088                average_vertex_values(ensure_numeric(self.domain.vertex_value_indices),
     1089                                      ensure_numeric(self.domain.number_of_triangles_per_node),
     1090                                      ensure_numeric(self.vertex_values),
     1091                                      A)
     1092                A = A.astype(precision)
     1093            else:   
     1094
     1095                # Slow Python version
     1096               
     1097                current_node = 0
     1098                k = 0 # Track triangles touching on node
     1099                total = 0.0
     1100                for index in self.domain.vertex_value_indices:
     1101                    k += 1
     1102                   
     1103                    volume_id = index / 3
     1104                    vertex_id = index % 3
     1105                 
     1106                    #assert V[volume_id, vertex_id] == current_node
     1107               
    11011108                    v = self.vertex_values[volume_id, vertex_id]
    1102                     contributions.append(v)
    1103 
    1104                 A[k] = reduction(contributions)
     1109                    total += v
     1110
     1111                    #print 'current_node=%d, index=%d, k=%d, total=%f' %(current_node, index, k, total)
     1112                    if self.domain.number_of_triangles_per_node[current_node] == k:
     1113                        A[current_node] = total/k
     1114               
     1115                   
     1116                        # Move on to next node
     1117                        total = 0.0
     1118                        k = 0
     1119                        current_node += 1
     1120
     1121
    11051122
    11061123        else:
     
    14501467
    14511468    from quantity_ext import compute_gradients, limit,\
    1452     extrapolate_second_order, interpolate_from_vertices_to_edges, update
     1469    extrapolate_second_order, interpolate_from_vertices_to_edges, update,\
     1470    average_vertex_values
  • anuga_core/source/anuga/abstract_2d_finite_volumes/quantity_ext.c

    r3730 r4471  
    218218
    219219
     220int _average_vertex_values(int N,
     221                           long* vertex_value_indices,
     222                           long* number_of_triangles_per_node,
     223                           double* vertex_values,
     224                           double* A) {
     225  //Average vertex values to obtain one value per node
     226
     227  int i, index;
     228  int k = 0; //Track triangles touching each node
     229  int current_node = 0;
     230  double total = 0.0;
     231
     232  for (i=0; i<N; i++) {
     233    index = vertex_value_indices[i];
     234    k += 1;
     235           
     236    //volume_id = index / 3
     237    //vertex_id = index % 3
     238    //total += self.vertex_values[volume_id, vertex_id]
     239    total += vertex_values[index];
     240     
     241    //printf("current_node=%d, index=%d, k=%d, total=%f\n", current_node, index, k, total);
     242    if (number_of_triangles_per_node[current_node] == k) {
     243      A[current_node] = total/k;
     244               
     245      // Move on to next node
     246      total = 0.0;
     247      k = 0;
     248      current_node += 1;
     249    }
     250  }
     251                           
     252  return 0;
     253}
     254
     255
    220256/////////////////////////////////////////////////
    221257// Gateways to Python
     
    283319
    284320        err = _interpolate(N,
    285                      (double*) vertex_values -> data,
    286                      (double*) edge_values -> data);
     321                           (double*) vertex_values -> data,
     322                           (double*) edge_values -> data);
    287323
    288324        if (err != 0) {
     
    298334        return Py_BuildValue("");
    299335}
     336
     337
     338PyObject *average_vertex_values(PyObject *self, PyObject *args) {
     339
     340        PyArrayObject
     341          *vertex_value_indices,
     342          *number_of_triangles_per_node,
     343          *vertex_values,
     344          *A;
     345       
     346
     347        int N, err;
     348
     349        // Convert Python arguments to C
     350        if (!PyArg_ParseTuple(args, "OOOO",
     351                              &vertex_value_indices,
     352                              &number_of_triangles_per_node,
     353                              &vertex_values,
     354                              &A)) {
     355          PyErr_SetString(PyExc_RuntimeError,
     356                          "quantity_ext.c: average_vertex_values could not parse input");
     357          return NULL;
     358        }
     359       
     360        N = vertex_value_indices -> dimensions[0];
     361        // printf("Got parameters, N=%d\n", N);
     362        err = _average_vertex_values(N,
     363                                     (long*) vertex_value_indices -> data,
     364                                     (long*) number_of_triangles_per_node -> data,
     365                                     (double*) vertex_values -> data,
     366                                     (double*) A -> data);
     367
     368        if (err != 0) {
     369          PyErr_SetString(PyExc_RuntimeError,
     370                          "average_vertex_values could not be computed");
     371          return NULL;
     372        }
     373
     374        return Py_BuildValue("");
     375}
     376
    300377
    301378
     
    567644                interpolate_from_vertices_to_edges,
    568645                METH_VARARGS, "Print out"},
     646        {"average_vertex_values", average_vertex_values, METH_VARARGS, "Print out"},           
    569647        {NULL, NULL, 0, NULL}   // sentinel
    570648};
  • anuga_core/source/anuga/abstract_2d_finite_volumes/test_general_mesh.py

    r4171 r4471  
    6161                        [triangles[0], triangles[4]])
    6262       
     63
     64    def test_vertex_value_indices(self):
     65        """Check that structures are correct.
     66        """
     67        from mesh_factory import rectangular
     68        from Numeric import zeros, Float
     69
     70        #Create basic mesh
     71        nodes, triangles, _ = rectangular(3, 6)
     72        domain = General_mesh(nodes, triangles)
     73
     74        assert sum(domain.number_of_triangles_per_node) ==\
     75               len(domain.vertex_value_indices)
     76
     77        # Check number of triangles per node
     78        count = [0]*domain.number_of_nodes
     79        for triangle in triangles:
     80            for i in triangle:
     81                count[i] += 1
     82
     83        assert allclose(count, domain.number_of_triangles_per_node)
     84
     85        #print nodes
     86        #print triangles
     87        #print domain.number_of_triangles_per_node
     88        #print domain.vertex_value_indices       
     89
     90
     91        # Check indices
     92        current_node = 0
     93        k = 0 # Track triangles touching on node
     94        for index in domain.vertex_value_indices:
     95            k += 1
     96           
     97            triangle = index / 3
     98            vertex = index % 3
     99
     100            assert triangles[triangle, vertex] == current_node
     101
     102            if domain.number_of_triangles_per_node[current_node] == k:
     103                # Move on to next node
     104                k = 0
     105                current_node += 1
     106               
     107
     108
     109
     110
    63111    def test_areas(self):
    64112        from mesh_factory import rectangular
  • anuga_core/source/anuga/abstract_2d_finite_volumes/test_util.py

    r4469 r4471  
    13311331    suite = unittest.makeSuite(Test_Util,'test')
    13321332#    suite = unittest.makeSuite(Test_Util,'test_store_parameters')
    1333     runner = unittest.TextTestRunner()
     1333    runner = unittest.TextTestRunner(verbosity=0)
    13341334    runner.run(suite)
    13351335
  • anuga_core/source/anuga/shallow_water/test_data_manager.py

    r4462 r4471  
    393393        os.remove(sww.filename)
    394394
    395     def test_sww_variable3(self):
     395    def no_test_sww_variable3(self):
    396396        """Test that sww information can be written correctly
    397397        multiple timesteps using a different reduction operator (min)
    398398        """
    399399
     400        # Different reduction in sww files has been made obsolete.
     401       
    400402        import time, os
    401403        from Numeric import array, zeros, allclose, Float, concatenate
Note: See TracChangeset for help on using the changeset viewer.