//=========================================================================== // // File: uniquepoints.c // // Created: Fri Jun 19 08:46:05 2009 // // Author: Jostein R. Natvig // // $Date$ // // $Revision$ // //=========================================================================== /* Copyright 2009 SINTEF ICT, Applied Mathematics. Copyright 2009 Statoil ASA. This file is part of The Open Reservoir Simulator Project (OpenRS). OpenRS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenRS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenRS. If not, see . */ #include #include #include #include #include #include #include #include "sparsetable.h" #include "preprocess.h" #include "uniquepoints.h" #define min(i,j) ((i)<(j) ? (i) : (j)) #define max(i,j) ((i)>(j) ? (i) : (j)) #define overlap(a1,a2,b1,b2) max(a1,b1) < min(a2,b2) /*----------------------------------------------------------------- Compare function passed to qsort */ static int compare(const void *a, const void *b) { if (*(double*)a < *(double*) b) return -1; else return 1; } /*----------------------------------------------------------------- Creat sorted list of z-values in zcorn with actnum==1 */ static int createSortedList(double *list, int n, int m, const double *z[], const int *a[]) { int i,j; double *ptr = list; for (i=0; i apart in of increasing doubles. */ static int uniquify(int n, double *list, double tolerance) { assert (!(tolerance < 0.0)); if (n<1) return 0; int i; int pos = 0; double val = list[pos++];/* Keep first value */ for (i=1; i away from the last point (list[n-1]), we remove this second-to-last point as it cannot be distinguished from "final" point. */ list[pos-1] = list[n-1]; return pos; } /*----------------------------------------------------------------- Along single pillar: */ static int assignPointNumbers(int begin, int end, const double *zlist, int n, const double *zcorn, const int *actnum, int *plist, double tolerance) { /* n - number of cells */ /* zlist - list of len unique z-values */ /* start - number of unique z-values processed before. */ int i, k; /* All points should now be within tolerance of a listed point. */ const double *z = zcorn; const int *a = actnum; int *p = plist; k = begin; *p++ = INT_MIN; /* Padding to ease processing of faults */ for (i=0; i with k index running faster than i running faster than j, and Cartesian dimensions , find pointers to the (i-1, j-1, 0), (i-1, j, 0), (i, j-1, 0) and (i, j, 0) elements of field. */ static void igetvectors(const int dims[3], int i, int j, const int *field, const int *v[]) { int im = max(1, i ) - 1; int ip = min(dims[0], i+1) - 1; int jm = max(1, j ) - 1; int jp = min(dims[1], j+1) - 1; v[0] = field + dims[2]*(im + dims[0]* jm); v[1] = field + dims[2]*(im + dims[0]* jp); v[2] = field + dims[2]*(ip + dims[0]* jm); v[3] = field + dims[2]*(ip + dims[0]* jp); } /*----------------------------------------------------------------- Given a vector with k index running faster than i running faster than j, and Cartesian dimensions , find pointers to the (i-1, j-1, 0), (i-1, j, 0), (i, j-1, 0) and (i, j, 0) elements of field. */ static void dgetvectors(const int dims[3], int i, int j, const double *field, const double *v[]) { int im = max(1, i ) - 1; int ip = min(dims[0], i+1) - 1; int jm = max(1, j ) - 1; int jp = min(dims[1], j+1) - 1; v[0] = field + dims[2]*(im + dims[0]* jm); v[1] = field + dims[2]*(im + dims[0]* jp); v[2] = field + dims[2]*(ip + dims[0]* jm); v[3] = field + dims[2]*(ip + dims[0]* jp); } /*----------------------------------------------------------------- Given a z coordinate, find x and y coordinates on line defined by coord. Coord points to a vector of 6 doubles [x0,y0,z0,x1,y1,z1]. */ static void interpolate_pillar(const double *coord, double *pt) { double a = (pt[2]-coord[2])/(coord[5]-coord[2]); if (isinf(a) || isnan(a)){ a = 0; } pt[0] = coord[0] + a*(coord[3]-coord[0]); pt[1] = coord[1] + a*(coord[4]-coord[1]); } /*----------------------------------------------------------------- Assign point numbers p such that "zlist(p)==zcorn". Assume that coordinate number is arranged in a sequence such that the natural index is (k,i,j) */ int finduniquepoints(const struct grdecl *g, /* return values: */ int *plist, /* list of point numbers on each pillar*/ double tolerance, struct processed_grid *out) { int nx = out->dimensions[0]; int ny = out->dimensions[1]; int nz = out->dimensions[2]; /* ztab->data may need extra space temporarily due to simple boundary treatement */ int npillarpoints = 8*(nx+1)*(ny+1)*nz; int npillars = (nx+1)*(ny+1); sparse_table_t *ztab = malloc_sparse_table(npillars, npillarpoints, sizeof(double)); int nc = g->dims[0]*g->dims[1]*g->dims[2]; out->node_coordinates = malloc (3*8*nc*sizeof(*out->node_coordinates)); double *zlist = ztab->data; /* casting void* to double* */ int *zptr = ztab->ptr; int i,j,k; int d1[3] = {2*g->dims[0], 2*g->dims[1], 2*g->dims[2]}; int len = 0; double *zout = zlist; int pos = 0; zptr[pos++] = zout - zlist; double *coord = (double*)g->coord; double *pt = out->node_coordinates; /* Loop over pillars, find unique points on each pillar */ for (j=0; j < g->dims[1]+1; ++j){ for (i=0; i < g->dims[0]+1; ++i){ const int *a[4]; const double *z[4]; /* Get positioned pointers for actnum and zcorn data */ igetvectors(g->dims, i, j, g->actnum, a); dgetvectors(d1, 2*i, 2*j, g->zcorn, z); len = createSortedList( zout, d1[2], 4, z, a); len = uniquify (len, zout, tolerance); /* Assign unique points */ for (k=0; knumber_of_nodes_on_pillars = zptr[pos-1]; out->number_of_nodes = zptr[pos-1]; /* Loop over all vertical sets of zcorn values, assign point numbers */ int *p = plist; for (j=0; j < 2*g->dims[1]; ++j){ for (i=0; i < 2*g->dims[0]; ++i){ /* pillar index */ int pix = (i+1)/2 + (g->dims[0]+1)*((j+1)/2); /* cell column position */ int cix = g->dims[2]*((i/2) + (j/2)*g->dims[0]); /* zcorn column position */ int zix = 2*g->dims[2]*(i+2*g->dims[0]*j); const int *a = g->actnum + cix; const double *z = g->zcorn + zix; if (!assignPointNumbers(zptr[pix], zptr[pix+1], zlist, 2*g->dims[2], z, a, p, tolerance)){ fprintf(stderr, "Something went wrong in assignPointNumbers"); return 0; } p += 2 + 2*g->dims[2]; } } free_sparse_table(ztab); return 1; }