Changeset 2506


Ignore:
Timestamp:
05/31/23 12:20:29 (13 months ago)
Author:
ymipsl
Message:

Supress limitation of number of vertex max in remaper.
YM

Location:
XIOS2/trunk/extern/remap/src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • XIOS2/trunk/extern/remap/src/elt.hpp

    r1614 r2506  
    33#include <list> 
    44#include "triple.hpp" 
     5#include <vector> 
    56 
    6 #define NMAX 10 /**< maximum number of vertices for polygons */ 
     7#define NMAX 0 /**< maximum number of vertices for polygons */ 
    78 
    89#define NOT_FOUND -1 
     
    5859        { 
    5960                int k = 0; 
     61                vertex.resize(max_num_vert) ; 
    6062                vertex[k++] = xyz(bounds_lon[0], bounds_lat[0]); 
    6163                for (int i = 1; i < max_num_vert; i++) 
     
    7274                } 
    7375                n = k; 
    74                 x = barycentre(vertex, n); 
     76    vertex.resize(n) ; 
     77    vertex.shrink_to_fit(); 
     78          allocate() ; 
     79 
     80                x = barycentre(vertex.data(), n); 
    7581        } 
    76  
     82  void allocate(void) 
     83  { 
     84    vertex.resize(n) ; 
     85    neighbour.resize(n) ; 
     86    d.resize(n) ; 
     87    edge.resize(n) ; 
     88    gradNeigh.resize(n) ; 
     89    neighId.resize(n) ; 
     90  } 
    7791        Elt& operator=(const Elt& rhs) 
    7892        { 
     
    87101                is   = rhs.is; 
    88102 
    89                 for(int i = 0; i < NMAX; i++) 
    90                 { 
    91                         neighbour[i] = rhs.neighbour[i]; 
    92                         d[i]         = rhs.d[i]; 
    93                         edge[i]      = rhs.edge[i]; 
    94                         vertex[i]    = rhs.vertex[i]; 
    95                         gradNeigh[i] = rhs.gradNeigh[i]; 
    96                 } 
     103                neighbour = rhs.neighbour; 
     104                d         = rhs.d; 
     105                edge      = rhs.edge; 
     106                vertex    = rhs.vertex; 
     107                gradNeigh = rhs.gradNeigh; 
    97108                return *this; 
    98109        } 
     
    109120  void insert_vertex(int i, const Coord& v) 
    110121  { 
     122    vertex.resize(n+1) ; 
     123    edge.resize(n+1) ; 
     124    d.resize(n+1) ; 
     125    neighbour.resize(n+1) ; 
     126    gradNeigh.resize(n+1) ; 
     127    neighId.resize(n+1) ; 
     128 
    111129    for(int j=n; j > i ; j--) 
    112130    { 
     
    120138  } 
    121139   
    122         int neighbour[NMAX]; 
    123         double d[NMAX]; /**< distance of centre of small circle to origin, zero if great circle */ 
     140        std::vector<int> neighbour; 
     141        std::vector<double> d; /**< distance of centre of small circle to origin, zero if great circle */ 
    124142        double val;     /**< value (sample if src element, interpolated if dest element) */ 
    125         Coord vertex[NMAX]; 
    126         Coord edge[NMAX]; /**< edge normals: if great circle tangential to sphere, if small circle parallel to pole */ 
     143        std::vector<Coord> vertex; 
     144        std::vector<Coord> edge; /**< edge normals: if great circle tangential to sphere, if small circle parallel to pole */ 
    127145        Coord grad;    /**< gradient of the reconstructed linear function over this element */ 
    128         Coord gradNeigh[NMAX]; /**< for weight computation: gradients for val=1 at individual neighbours */ 
    129         struct GloId neighId[NMAX]; /**< weight computation needs to know global IDs for all sources with "link" */ 
     146        std::vector<Coord> gradNeigh; /**< for weight computation: gradients for val=1 at individual neighbours */ 
     147        std::vector<struct GloId> neighId; /**< weight computation needs to know global IDs for all sources with "link" */ 
    130148        std::list<Polyg*> is; /**< intersections */ 
    131149}; 
  • XIOS2/trunk/extern/remap/src/intersection_ym.cpp

    r1588 r2506  
    4747  Coord *b_gno   = new Coord[nb]; 
    4848 
    49   Coord OC=barycentre(a->vertex,a->n) ; 
     49  Coord OC=barycentre(a->vertex.data(),a->n) ; 
    5050  Coord Oz=OC ; 
    5151  Coord Ox=crossprod(Coord(0,0,1),Oz) ; 
  • XIOS2/trunk/extern/remap/src/libmapper.cpp

    r1639 r2506  
    138138extern "C" void remap_get_weights(double* weights, int* src_indices, int* dst_indices) 
    139139{ 
    140         memcpy(weights, mapper->remapMatrix, mapper->nWeights*sizeof(double)); 
    141         memcpy(src_indices, mapper->srcAddress, mapper->nWeights*sizeof(int)); 
    142         memcpy(dst_indices, mapper->dstAddress, mapper->nWeights*sizeof(int)); 
     140        memcpy(weights, mapper->remapMatrix.data(), mapper->nWeights*sizeof(double)); 
     141        memcpy(src_indices, mapper->srcAddress.data(), mapper->nWeights*sizeof(int)); 
     142        memcpy(dst_indices, mapper->dstAddress.data(), mapper->nWeights*sizeof(int)); 
    143143        delete mapper; 
    144144} 
  • XIOS2/trunk/extern/remap/src/mapper.cpp

    r1639 r2506  
    145145      nIntersections++; 
    146146  } 
     147 
    147148  /* overallocate for NMAX neighbours for each elements */ 
     149/* 
    148150  remapMatrix = new double[nIntersections*NMAX]; 
    149151  srcAddress = new int[nIntersections*NMAX]; 
     
    152154  sourceWeightId =new long[nIntersections*NMAX]; 
    153155  targetWeightId =new long[nIntersections*NMAX]; 
    154  
     156*/ 
    155157 
    156158  if (mpiRank == 0 && verbose) cout << "Remapping..." << endl; 
     
    186188 
    187189  int *nbSendElement = new int[mpiSize]; 
     190  int *nbSendVertex = new int[mpiSize]; 
    188191  int **sendElement = new int*[mpiSize]; /* indices of elements required from other rank */ 
    189192  double **recvValue = new double*[mpiSize]; 
    190193  double **recvArea = new double*[mpiSize]; 
    191194  double **recvGivenArea = new double*[mpiSize]; 
     195  int **recvVertexOffset = new int*[mpiSize]; 
    192196  Coord **recvGrad = new Coord*[mpiSize]; 
    193197  GloId **recvNeighIds = new GloId*[mpiSize]; /* ids of the of the source neighbours which also contribute through gradient */ 
     
    210214    { 
    211215      sendElement[rank] = new int[nbSendElement[rank]]; 
    212       recvValue[rank]   = new double[nbSendElement[rank]]; 
    213       recvArea[rank]    = new double[nbSendElement[rank]]; 
    214       recvGivenArea[rank] = new double[nbSendElement[rank]]; 
    215       if (order == 2) 
    216       { 
    217         recvNeighIds[rank] = new GloId[nbSendElement[rank]*(NMAX+1)]; 
    218         recvGrad[rank]    = new Coord[nbSendElement[rank]*(NMAX+1)]; 
    219       } 
    220       else 
    221         recvNeighIds[rank] = new GloId[nbSendElement[rank]]; 
    222  
    223216      last = -1; 
    224217      index = -1; 
     
    235228  /* communicate sizes of source elements to be sent (index lists and later values and gradients) */ 
    236229  int *nbRecvElement = new int[mpiSize]; 
     230  int *nbRecvVertex = new int[mpiSize]; 
    237231  MPI_Alltoall(nbSendElement, 1, MPI_INT, nbRecvElement, 1, MPI_INT, communicator); 
    238232 
     
    244238  double **sendArea = new double*[mpiSize]; 
    245239  double **sendGivenArea = new double*[mpiSize]; 
     240  int    **sendVertexOffset = new int*[mpiSize]; 
    246241  Coord **sendGrad = new Coord*[mpiSize]; 
    247242  GloId **sendNeighIds = new GloId*[mpiSize]; 
    248   MPI_Request *sendRequest = new MPI_Request[5*mpiSize]; 
    249   MPI_Request *recvRequest = new MPI_Request[5*mpiSize]; 
     243  MPI_Request *sendRequest = new MPI_Request[6*mpiSize]; 
     244  MPI_Request *recvRequest = new MPI_Request[6*mpiSize]; 
    250245  for (int rank = 0; rank < mpiSize; rank++) 
    251246  { 
     
    259254    { 
    260255      recvElement[rank] = new int[nbRecvElement[rank]]; 
     256      MPI_Irecv(recvElement[rank], nbRecvElement[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
     257      nbRecvRequest++; 
     258    } 
     259  } 
     260  MPI_Status *status = new MPI_Status[6*mpiSize]; 
     261   
     262  MPI_Waitall(nbSendRequest, sendRequest, status); 
     263  MPI_Waitall(nbRecvRequest, recvRequest, status); 
     264 
     265  nbSendRequest = 0; 
     266  nbRecvRequest = 0; 
     267 
     268  for (int rank = 0; rank < mpiSize; rank++) 
     269  { 
     270    if (nbRecvElement[rank] > 0) 
     271    { 
     272      nbRecvVertex[rank]=0 ; 
     273      for (int j = 0; j < nbRecvElement[rank]; j++) nbRecvVertex[rank]+=sstree.localElements[recvElement[rank][j]].n+1; 
     274      MPI_Issend(&nbRecvVertex[rank], 1, MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 
     275      nbSendRequest++; 
     276    } 
     277   
     278    if (nbSendElement[rank] > 0) 
     279    { 
     280      MPI_Irecv(&nbSendVertex[rank], 1, MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
     281      nbRecvRequest++; 
     282    } 
     283  } 
     284   
     285  MPI_Waitall(nbSendRequest, sendRequest, status); 
     286  MPI_Waitall(nbRecvRequest, recvRequest, status); 
     287 
     288 
     289  /* for all indices that have been received from requesting ranks: pack values and gradients, then send */ 
     290  nbSendRequest = 0; 
     291  nbRecvRequest = 0; 
     292  for (int rank = 0; rank < mpiSize; rank++) 
     293  { 
     294    if (nbRecvElement[rank] > 0) 
     295    { 
    261296      sendValue[rank]   = new double[nbRecvElement[rank]]; 
    262297      sendArea[rank]   = new double[nbRecvElement[rank]]; 
    263298      sendGivenArea[rank] = new double[nbRecvElement[rank]]; 
     299      sendVertexOffset[rank] = new int[nbRecvElement[rank]]; 
     300 
    264301      if (order == 2) 
    265302      { 
    266         sendNeighIds[rank] = new GloId[nbRecvElement[rank]*(NMAX+1)]; 
    267         sendGrad[rank]    = new Coord[nbRecvElement[rank]*(NMAX+1)]; 
    268       } 
    269       else 
    270       { 
    271         sendNeighIds[rank] = new GloId[nbRecvElement[rank]]; 
    272       } 
    273       MPI_Irecv(recvElement[rank], nbRecvElement[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
    274       nbRecvRequest++; 
    275     } 
    276   } 
    277   MPI_Status *status = new MPI_Status[5*mpiSize]; 
    278    
    279   MPI_Waitall(nbSendRequest, sendRequest, status); 
    280         MPI_Waitall(nbRecvRequest, recvRequest, status); 
    281  
    282   /* for all indices that have been received from requesting ranks: pack values and gradients, then send */ 
    283   nbSendRequest = 0; 
    284   nbRecvRequest = 0; 
    285   for (int rank = 0; rank < mpiSize; rank++) 
    286   { 
    287     if (nbRecvElement[rank] > 0) 
    288     { 
     303        sendNeighIds[rank] = new GloId[nbRecvVertex[rank]]; 
     304        sendGrad[rank]    = new Coord[nbRecvVertex[rank]]; 
     305      } 
     306      else sendNeighIds[rank] = new GloId[nbRecvElement[rank]]; 
     307 
    289308      int jj = 0; // jj == j if no weight writing 
     309      sendVertexOffset[rank][0]=0 ; 
    290310      for (int j = 0; j < nbRecvElement[rank]; j++) 
    291311      { 
     
    293313        sendArea[rank][j] = sstree.localElements[recvElement[rank][j]].area; 
    294314        sendGivenArea[rank][j] = sstree.localElements[recvElement[rank][j]].given_area; 
     315         
     316        if (j==0)  
     317        { 
     318          if (order==2) sendVertexOffset[rank][j]=sstree.localElements[recvElement[rank][j]].n+1 ; 
     319          else sendVertexOffset[rank][j]=1 ; 
     320        } 
     321        else  
     322        { 
     323          if (order == 2) sendVertexOffset[rank][j] = sendVertexOffset[rank][j-1]+sstree.localElements[recvElement[rank][j]].n+1 ; 
     324          else sendVertexOffset[rank][j] = sendVertexOffset[rank][j-1]+1 ; 
     325        } 
     326 
    295327        if (order == 2) 
    296328        { 
     
    299331          sendNeighIds[rank][jj] = sstree.localElements[recvElement[rank][j]].src_id; 
    300332          jj++; 
    301           for (int i = 0; i < NMAX; i++) 
     333          for (int i = 0; i <  sstree.localElements[recvElement[rank][j]].n ; i++) 
    302334          { 
    303335            sendGrad[rank][jj] = sstree.localElements[recvElement[rank][j]].gradNeigh[i]; 
     
    316348      MPI_Issend(sendGivenArea[rank],  nbRecvElement[rank], MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 
    317349      nbSendRequest++; 
     350      MPI_Issend(sendVertexOffset[rank],  nbRecvElement[rank], MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 
     351      nbSendRequest++; 
     352 
    318353      if (order == 2) 
    319354      { 
    320         MPI_Issend(sendGrad[rank], 3*nbRecvElement[rank]*(NMAX+1), MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 
     355        MPI_Issend(sendGrad[rank], 3*nbRecvVertex[rank], MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 
    321356        nbSendRequest++; 
    322         MPI_Issend(sendNeighIds[rank], 4*nbRecvElement[rank]*(NMAX+1), MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 
     357        MPI_Issend(sendNeighIds[rank], 4*nbRecvVertex[rank], MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 
    323358//ym  --> attention taille GloId 
    324359        nbSendRequest++; 
     
    333368    if (nbSendElement[rank] > 0) 
    334369    { 
     370      recvValue[rank]   = new double[nbSendElement[rank]]; 
     371      recvArea[rank]    = new double[nbSendElement[rank]]; 
     372      recvGivenArea[rank] = new double[nbSendElement[rank]]; 
     373      recvVertexOffset[rank] = new int[nbSendElement[rank]]; 
     374 
     375      if (order == 2) 
     376      { 
     377        recvNeighIds[rank] = new GloId[nbSendVertex[rank]]; 
     378        recvGrad[rank]     = new Coord[nbSendVertex[rank]]; 
     379      } 
     380      else recvNeighIds[rank] = new GloId[nbSendElement[rank]]; 
     381 
     382 
    335383      MPI_Irecv(recvValue[rank],  nbSendElement[rank], MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
    336384      nbRecvRequest++; 
     
    339387      MPI_Irecv(recvGivenArea[rank],  nbSendElement[rank], MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
    340388      nbRecvRequest++; 
     389      MPI_Irecv(recvVertexOffset[rank],  nbSendElement[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
     390      nbRecvRequest++; 
     391 
    341392      if (order == 2) 
    342393      { 
    343         MPI_Irecv(recvGrad[rank], 3*nbSendElement[rank]*(NMAX+1), 
    344             MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
     394        MPI_Irecv(recvGrad[rank], 3*nbSendVertex[rank], MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
    345395        nbRecvRequest++; 
    346         MPI_Irecv(recvNeighIds[rank], 4*nbSendElement[rank]*(NMAX+1), MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
     396        MPI_Irecv(recvNeighIds[rank], 4*nbSendVertex[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 
    347397//ym  --> attention taille GloId 
    348398        nbRecvRequest++; 
     
    357407  } 
    358408         
    359         MPI_Waitall(nbSendRequest, sendRequest, status); 
     409  MPI_Waitall(nbSendRequest, sendRequest, status); 
    360410  MPI_Waitall(nbRecvRequest, recvRequest, status); 
    361411   
     
    388438 
    389439      /* first order: src value times weight (weight = supermesh area), later divide by target area */ 
    390       int kk = (order == 2) ? n1 * (NMAX + 1) : n1; 
    391       GloId neighID = recvNeighIds[rank][kk]; 
     440//      int kk = (order == 2) ? n1 * (NMAX + 1) : n1; 
     441      int offset ; 
     442      int nvertex ; 
     443      if (n1==0)  
     444      { 
     445        offset=0 ; 
     446        nvertex=recvVertexOffset[rank][0] ; 
     447      } 
     448      else  
     449      { 
     450        offset = recvVertexOffset[rank][n1-1]; 
     451        nvertex = recvVertexOffset[rank][n1]-recvVertexOffset[rank][n1-1]; 
     452      } 
     453 
     454      GloId neighID = recvNeighIds[rank][offset]; 
    392455      wgt_map[neighID] += w; 
    393456 
    394457      if (order == 2) 
    395458      { 
    396         for (int k = 0; k < NMAX+1; k++) 
     459        for (int k = 0; k < nvertex; k++) 
    397460        { 
    398           int kk = n1 * (NMAX + 1) + k; 
     461          int kk = offset + k; 
    399462          GloId neighID = recvNeighIds[rank][kk]; 
    400463          if (neighID.ind != -1)  wgt_map[neighID] += w * scalarprod(recvGrad[rank][kk], (*it)->x); 
     
    414477    for (map<GloId,double>::iterator it = wgt_map.begin(); it != wgt_map.end(); it++) 
    415478    { 
    416       if (quantity)  this->remapMatrix[i] = (it->second ) / renorm; 
    417       else this->remapMatrix[i] = (it->second / e.area) / renorm; 
    418       this->srcAddress[i] = it->first.ind; 
    419       this->srcRank[i] = it->first.rank; 
    420       this->dstAddress[i] = j; 
    421       this->sourceWeightId[i]= it->first.globalId ; 
    422       this->targetWeightId[i]= targetGlobalId[j] ; 
     479      if (quantity)  this->remapMatrix.push_back((it->second ) / renorm); 
     480      else this->remapMatrix.push_back((it->second / e.area) / renorm); 
     481      this->srcAddress.push_back(it->first.ind); 
     482      this->srcRank.push_back(it->first.rank); 
     483      this->dstAddress.push_back(j); 
     484      this->sourceWeightId.push_back(it->first.globalId) ; 
     485      this->targetWeightId.push_back(targetGlobalId[j]) ; 
    423486      i++; 
    424487    } 
     
    434497      delete[] recvArea[rank]; 
    435498      delete[] recvGivenArea[rank]; 
     499      delete[] recvVertexOffset[rank]; 
    436500      if (order == 2) 
    437501      { 
     
    446510      delete[] sendArea[rank]; 
    447511      delete[] sendGivenArea[rank]; 
     512      delete[] sendVertexOffset[rank]; 
    448513      if (order == 2) 
    449514        delete[] sendGrad[rank]; 
     
    457522  delete[] nbSendElement; 
    458523  delete[] nbRecvElement; 
     524  delete[] nbSendVertex; 
     525  delete[] nbRecvVertex; 
    459526  delete[] sendElement; 
    460527  delete[] recvElement; 
     
    9391006Mapper::~Mapper() 
    9401007{ 
    941   delete [] remapMatrix; 
    942   delete [] srcAddress; 
    943   delete [] srcRank; 
    944   delete [] dstAddress; 
    945   if (neighbourElements) delete [] neighbourElements; 
    946 } 
    947  
    948 } 
     1008 
     1009} 
     1010 
     1011} 
  • XIOS2/trunk/extern/remap/src/mapper.hpp

    r2088 r2506  
    4141*/ 
    4242       /* where weights are returned after call to `computeWeights` */ 
    43        double *remapMatrix; 
    44        int *srcAddress; 
    45        int *srcRank; 
    46        int *dstAddress; 
     43       std::vector<double> remapMatrix; 
     44       std::vector<int> srcAddress; 
     45       std::vector<int> srcRank; 
     46       std::vector<int> dstAddress; 
    4747       int nWeights; 
    48        long int* sourceWeightId ; 
    49        long int* targetWeightId ; 
     48       std::vector<long int> sourceWeightId ; 
     49       std::vector<long int> targetWeightId ; 
    5050 
    5151private: 
  • XIOS2/trunk/extern/remap/src/meshutil.cpp

    r2502 r2506  
    2424  Coord *a_gno   = new Coord[na]; 
    2525   
    26   Coord OC=barycentre(a.vertex,a.n) ; 
     26  Coord OC=barycentre(a.vertex.data(),a.n) ; 
    2727  Coord Oz=OC ; 
    2828  Coord Ox=crossprod(Coord(0,0,1),Oz) ; 
     
    6767  { 
    6868    bary = bary * (-1.) ; 
    69     switchOrientation(a.n, a.vertex,a.edge,a.d) ; 
     69    switchOrientation(a.n, a.vertex.data(),a.edge.data(),a.d.data()) ; 
    7070  } 
    7171   
     
    7979void cptEltGeom(Elt& elt, const Coord &pole) 
    8080{ 
    81    orient(elt.n, elt.vertex, elt.edge, elt.d, elt.x); 
     81   orient(elt.n, elt.vertex.data(), elt.edge.data(), elt.d.data(), elt.x); 
    8282   normals(elt, pole); 
    8383//  Coord gg; 
     
    205205    elts[j]->val = 0; 
    206206 
    207   Elt *neighbours[NMAX]; 
     207//  Elt *neighbours[NMAX]; 
    208208  for (int j = 0; j < N; j++) 
    209209  { 
     210    vector<Elt*> neighbours(elts[j]->n) ; 
     211 
    210212    for (int i = 0; i < elts[j]->n; i++)  
    211213      if ( elts[j]->neighbour[i]== NOT_FOUND) neighbours[i]=NULL ; // no neighbour 
     
    223225        /* for weight computation all values are always kept zero and only set to one when used .. */ 
    224226        neighbours[i]->val = 1; 
    225         elts[j]->gradNeigh[i] = gradient(*(elts[j]), neighbours); 
     227        elts[j]->gradNeigh[i] = gradient(*(elts[j]), neighbours.data()); 
    226228        /* .. and right after zeroed again */ 
    227229        neighbours[i]->val = 0; 
     
    234236    } 
    235237 
     238/*  not needed anymore 
    236239    for(int i = elts[j]->n ; i < NMAX; i++) 
    237240    { 
     
    239242      elts[j]->neighId[i].ind = -1; // mark end 
    240243    } 
     244*/ 
    241245    /* For the most naive algorithm the case where the element itself is one must also be considered. 
    242246       Thomas says this can later be optimized out. */ 
    243247    elts[j]->val = 1; 
    244     elts[j]->grad = gradient(*(elts[j]), neighbours); 
     248    elts[j]->grad = gradient(*(elts[j]), neighbours.data()); 
    245249    elts[j]->val = 0; 
    246250  } 
  • XIOS2/trunk/extern/remap/src/polyg.cpp

    r2500 r2506  
    298298  e.n = *((int *) & (buffer[pos])); 
    299299  pos += sizeof(int); 
    300  
     300   
     301  e.allocate() ; 
     302   
    301303  for (int i = 0; i < e.n; i++) 
    302304  { 
Note: See TracChangeset for help on using the changeset viewer.