Initial checkin of cornerpoint processing code.

Current status
--------------
Given vectors ZCORN, COORD and ACTNUM as well as the Cartesian
dimensions these vectors implicitly refer to, the code is
currently capable of

 * Identify unique points along each pillar
 * Assign point numbers for each point specified in ZCORN
 * Compute face topology, i.e., the corners that define the geometry
   of the faces as well as the cells that are connected through the face.
 * Identify and compute intesections that occur in the processing of
   face topology.

What remains is

 * Handle the face geometry of boundary faces. (simple)
 * Compute point coordinates of the final point list.
 * Put all pieces together in a tidy manner.
This commit is contained in:
Jostein R. Natvig 2009-06-11 07:33:50 +00:00
commit e04eb2f728
9 changed files with 789 additions and 0 deletions

13
grdecl.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef GRDECL_H
#define GRDECL_H
struct Grdecl{
int n;
int dims[3];
double *coord;
double *zcorn;
int *actnum;
};
#endif

24
matalloc.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdlib.h>
#include "matalloc.h"
double **dmatalloc(int m, int n)
{
double **ret = malloc(m*sizeof *ret);
ret[0] = malloc(m*n*sizeof *ret[0]);
int i;
for (i=1; i<m; ++i) {
ret[i] = ret[i-1]+n*sizeof *ret[0];
}
return ret;
}
int **imatalloc(int m, int n)
{
int **ret = malloc(m*sizeof *ret);
ret[0] = malloc(m*n*sizeof *ret[0]);
int i;
for (i=1; i<m; ++i) {
ret[i] = ret[i-1]+n*sizeof *ret[0];
}
return ret;
}

7
matalloc.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef MATALLOC_H_
#define MATALLOC_H
double **dmatalloc(int m, int n);
int **imatalloc(int m, int n);
#endif

68
mxgrdecl.c Normal file
View File

@ -0,0 +1,68 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <mex.h>
#include "grdecl.h"
/* Get COORD, ZCORN, ACTNUM and DIMS from mxArray. */
/*-------------------------------------------------------*/
void mxInitGrdecl(struct Grdecl *g, const mxArray *prhs[])
{
int i,j,k;
g->coord = mxGetPr(mxGetField(prhs[0], 0, "COORD"));
double *tmp = mxGetPr(mxGetField(prhs[0], 0, "cartDims"));
g->n = 1;
for (i=0; i<3; ++i){
g->dims[i] = tmp[i];
g->n *= tmp[i];
}
mexPrintf("dimensions: %d %d %d\n",
g->dims[0],
g->dims[1],
g->dims[2]);
/* grdecl.actnum = permute(actnum, [3,1,2]); */
int *actnum = mxGetData(mxGetField(prhs[0], 0, "ACTNUM"));
g->actnum = malloc(g->n* sizeof(*g->actnum));
int *iptr = g->actnum;
for (j=0; j<g->dims[1]; ++j){
for (i=0; i<g->dims[0]; ++i){
for (k=0; k<g->dims[2]; ++k){
*iptr++ = actnum[i+g->dims[0]*(j+g->dims[1]*k)];
}
}
}
/* grdecl.zcorn = permute(zcorn, [3,1,2]); */
double *zcorn = mxGetPr(mxGetField(prhs[0], 0, "ZCORN"));
g->zcorn = malloc(g->n*8*sizeof(*g->zcorn));
double *dptr = g->zcorn;
for (j=0; j<2*g->dims[1]; ++j){
for (i=0; i<2*g->dims[0]; ++i){
for (k=0; k<2*g->dims[2]; ++k){
*dptr++ = zcorn[i+2*g->dims[0]*(j+2*g->dims[1]*k)];
}
}
}
}
/* Free stuff that was allocated in initgrdecl. */
/*-------------------------------------------------------*/
void freeGrdecl(struct Grdecl *g)
{
free(g->zcorn); g->zcorn = NULL;
free(g->actnum); g->actnum = NULL;
}

7
mxgrdecl.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef MXGRDECL_H
#define MXGRDECL_H
void mxInitGrdecl (struct Grdecl *g, const mxArray *prhs[]);
void freeGrdecl (struct Grdecl *g);
#endif

437
processgrid.c Normal file
View File

@ -0,0 +1,437 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <mex.h>
#include "grdecl.h"
#include "uniquepoints.h"
#include "mxgrdecl.h"
#include "matalloc.h"
/* No checking of input arguments in this code! */
#define min(i,j) ((i)<(j) ? (i) : (j))
#define max(i,j) ((i)>(j) ? (i) : (j))
/*------------------------------------------------------*/
/* */
/* */
/* Find connections for each pair of pillars */
/* */
/* */
/* */
/*------------------------------------------------------*/
/* Determine face geometry first, then compute intersections. */
/* All intersections that occur are present in the final face geometry.*/
int *computeFaceTopology(int *a1,
int *a2,
int *b1,
int *b2,
int intersect[4],
int *faces)
{
int mask[8];
/* Which pillar points should we use? */
if (a1[1] > b1[1]){ mask[0] = b1[1]; } else { mask[0] = a1[1]; }
if (a2[1] > b2[1]){ mask[2] = b2[1]; } else { mask[2] = a2[1]; }
if (a2[0] > b2[0]){ mask[4] = a2[0]; } else { mask[4] = b2[0]; }
if (a1[0] > b1[0]){ mask[6] = a1[0]; } else { mask[6] = b1[0]; }
/* Get shape of face: */
/* each new intersection will be part of the new face, */
/* but not all pillar points. This is encoded in mask. */
mask[1] = intersect[0]; /* top-top */
mask[3] = 0;
mask[5] = intersect[3]; /* bottom-bottom*/
mask[7] = 0;
/* bottom-top */
if (intersect[1]){
if(a1[0] > b1[1]){ /* intersection[1] left of (any) intersection[0] */
mask[0] = 0;
mask[6] = 0;
mask[7] = intersect[1];
}
else{
mask[2] = 0;
mask[4] = 0;
mask[3] = intersect[1];
}
}
/* top-bottom */
if (intersect[2]){
if(a1[1] < b1[0]){ /* intersection[2] left of (any) intersection[3] */
mask[0] = 0;
mask[6] = 0;
mask[7] = intersect[2];
}
else{
mask[2] = 0;
mask[4] = 0;
mask[3] = intersect[2];
}
}
int k;
int *f = faces;
for (k=0; k<8; ++k){
if(mask[k]){
*f++ = mask[k];
}
}
return f;
}
/* values in za and zb must be increasing. */
/* a) If we assume that the index increase when z increase for
each pillar (but only separately), we can skip the z
b) We assume no intersections occur on the first and last lines.
*/
/* #define overlap(a1,a2,b1,b2) max(a1,b1) < min(a2,b2) */
#define intersection(a1,a2,b1,b2)(((a1>b1)&&(a2<b2))||((a1<b1)&&(a2>b2)))
int faceintersection(int *a1, int *a2, int *b1, int *b2)
{
/* overlap(a1[0], a1[1], b1[0], b1[1]) || */
/* overlap(a2[0], a2[1], b2[0], b2[1]) || */
return
max(a1[0],b1[0]) < min(a1[1], b1[1]) ||
max(a2[0],b2[0]) < min(a2[1],b2[1]) ||
intersection(a1[0], a2[0], b1[0], b2[0]);
}
/* work should be pointer to 2n ints initialised to zero . */
void findconnections(int n, int *pts[4], int *ptnumber, int *intersections,
int *neighbors,
int *faces, int *fptr, int *fpos, int *work)
{
/* vectors of point numbers for faces a(b) on pillar 1(2) */
int *a1 = pts[0];
int *a2 = pts[1];
int *b1 = pts[2];
int *b2 = pts[3];
/* Intersection record for top line and bottomline of a */
int *itop = work; /* calloc(n, sizeof(*itop)); */
int *ibottom = work + n; /* calloc(n, sizeof(*ibottom)); */
int *f = faces + fptr[*fpos];
int *c = neighbors;
int k1 = 0;
int k2 = 0;
int i,j=0;
int intersect[4];
for (i = 0; i<n-1; ++i){
if (a1[i] == a1[i+1] && a2[i] == a2[i+1]) continue;
while(j<n-1 && (b1[j] < a1[i+1] || b2[j] < a2[i+1])){
if (b1[j] == b1[j+1] && b2[j] == b2[j+1]){
itop[j+1] = itop[j];
++j;
continue;
}
/* --------------------------------------------------------- */
/* face a(i,i+1) and face b(j,j+1) have nonzero intersection */
/* --------------------------------------------------------- */
if (faceintersection(a1+i, a2+i, b1+j, b2+j)){
/* Add neighbors to list of neighbors if not any first or */
/* last points are involved in face geometry. */
if (!((i==0) && (j==0)) && !((i==n-2) && (j==n-2))){
fprintf(stderr, "here: %d %d\n", i%2 ? (i-1)/2 : -1,
j%2 ? (j-1)/2 : -1);
*c++ = i%2 ? (i-1)/2 : -1;
*c++ = j%2 ? (j-1)/2 : -1;
}
/* Completely matching faces */
if (a1[i]==b1[j] && a1[i+1]==b1[j+1] &&
a2[i]==b2[j] && a2[i+1]==b2[j+1]){
/* Add face to list of faces if not any first or last points are involved. */
if (!((i==0) && (j==0)) && !((i==n-2) && (j==n-2))){
*f++ = a1[i];
*f++ = a1[i+1];
*f++ = a2[i+1];
*f++ = a2[i];
fptr[++(*fpos)] = f-faces;
}
}
/* Non-matching faces */
else{
/* Find new intersection */
if (intersection(a1[i+1],a2[i+1],b1[j+1],b2[j+1])) {
itop[j+1] = (*ptnumber)++;
/* store point numbers of intersecting lines */
*intersections++ = a1[i+1];
*intersections++ = a2[i+1];
*intersections++ = b1[j+1];
*intersections++ = b2[j+1];
}else{
itop[j+1] = 0;
}
/* Update intersection record */
intersect[0] = ibottom[j ]; /* i x j */
intersect[1] = ibottom[j+1]; /* i x j+1 */
intersect[2] = itop[j ]; /* i+1 x j */
intersect[3] = itop[j+1]; /* i+1 x j+1 */
/* Add face to list of faces if not any first or last points are involved. */
if (!((i==0) && (j==0)) && !((i==n-2) && (j==n-2))){
f = computeFaceTopology(a1+i, a2+i, b1+j, b2+j, intersect, f);
fptr[++(*fpos)] = f-faces;
}
}
}
/* Update candidates for restart of j for in next i-iteration */
if (b1[j] < a1[i+1]) k1 = j;
if (b2[j] < a2[i+1]) k2 = j;
j = j+1;
}
/* Swap intersection records: top line of a is next bottom line of a */
int *tmp;
tmp = itop; itop = ibottom; ibottom = tmp;
for(;j>min(k1,k2);--j) itop[j-1]=0;
/* Now, j = min(k1, k2) */
}
/* free(itop); */
/* free(ibottom); */
/* return (cells-begin)/2; */
}
void interpolate_pillar(double *coord, double *x, double *y, double *z)
{
double a = (*z-coord[2])/(coord[5]-coord[2]);
*x = coord[0] + a*(coord[3]-coord[0]);
*y = coord[1] + a*(coord[4]-coord[1]);
}
/*-------------------------------------------------------*/
static void igetvectors(int dims[3], int i, int j, int *field, 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;
fprintf(stderr, "%d %d %d %d\n", im,ip, jm,jp);
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);
}
/* Gateway routine for Matlab mex function. */
/*-------------------------------------------------------*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int i,j;
/* Set up data passed from Matlab */
struct Grdecl g;
mxInitGrdecl(&g, prhs);
/* Code below assumes k index runs fastests, ie. that dimensions of
table is permuted to (dims[2], dims[0], dims[1]) */
/* ---------------------------------------------------------------*/
/* Set up space for return values */
/* zlist may need extra space temporarily due to simple boundary treatement */
int sz = 8*(g.dims[0]+1)*(g.dims[1]+1)*g.dims[2];
int numpillars = (g.dims[0]+1)*(g.dims[1]+1);
double *zlist = malloc(sz*sizeof(*zlist));
int *zptr = malloc((numpillars+1)*sizeof(*zptr));
int *plist = malloc( 2*g.dims[0]*2*g.dims[1]*(2*g.dims[2]+2)*sizeof(int));
fprintf(stderr, "Allocate %d ints for plist\n", 2*g.dims[0]*2*g.dims[1]*(2*g.dims[2]+2));
finduniquepoints(&g, zlist, zptr, plist);
#if 0
for (i=0; i<numpillars ; ++i){
fprintf(stderr, "pillar %d\n", i);
for (k=zptr[i]; k<zptr[i+1]; ++k){
fprintf(stderr, "%f\n", zlist[k]);
}
mexPrintf("\n");
}
for (i=0; i<8*g.n; ++i) mexPrintf("%d\n", plist[i]);
#endif
/*======================================================*/
fprintf(stderr, "process face geomtery\n");
/* Process face geometry and cell-face topology */
/* internal constant i pillar pairs */
int n = 2 + 2*g.dims[2];
int k;
const int BIGNUM = 100;
int *faces = malloc(BIGNUM*sz*sizeof(int));
int *fptr = malloc(BIGNUM*sz*sizeof(int));
int *pts[4];
int *neighbors = malloc(2* n*n* sizeof(*neighbors));
int *intersections = malloc(4* n*n* sizeof(*intersections));
int *work = calloc(2* n, sizeof(*work));
int d[3] = {2*g.dims[0], 2*g.dims[1], 2+2*g.dims[2]};
int numfaces = 0;
int numpts = zptr[numpillars];
fptr[0]=0;
for (j=0; j<g.dims[1]; ++j) {
/* Add boundary faces */
igetvectors(d, 0, 2*j+1, plist, pts);
findconnections(n, pts, &numpts, intersections,
neighbors+2*numfaces, faces, fptr, &numfaces,
work);
/* internal faces */
for (i=1; i<g.dims[0]; ++i){
/* Vectors of point numbers */
igetvectors(d, 2*i, 2*j+1, plist, pts);
int start = numpts;
findconnections(n, pts, &numpts, intersections,
neighbors+2*numfaces, faces, fptr, &numfaces,
work);
/* Compute cell numbers from cell k-index (stored in neighbors) */
for (k=0; k<numfaces; ++k){
if (neighbors[2*k] != -1){
neighbors[2*k] = i-1 + g.dims[0]*(j + g.dims[1]*neighbors[2*k]);
}
if (neighbors[2*k+1] != -1){
neighbors[2*k+1] = i + g.dims[0]*(j + g.dims[1]*neighbors[2*k+1]);
}
}
#if 1
fprintf(stderr, "\nfaces\nnumfaces %d\n", numfaces);
for (i=0; i<numfaces; ++i){
for (k=fptr[i]; k<fptr[i+1]; ++k){
fprintf(stderr, "%d ", faces[k]);
}
fprintf(stderr, "\n");
}
fprintf(stderr, "\nneighbors\n");
int *iptr = neighbors;
for(k=0; k<numfaces; ++k){
fprintf(stderr, " (%d %d)\n", iptr[0], iptr[1]);
iptr+=2;
}
fprintf(stderr, "\nline intersections:\n");
iptr = intersections;
int numintersections = numpts - start;
for(k=0; k<numintersections; ++k){
fprintf(stderr, " (%d %d %d %d)\n", iptr[0], iptr[1], iptr[2], iptr[3]);
iptr+=4;
}
#endif
/* compute intersections */
}
/* Add boundary face */
}
#if 0
int xstride = 2*g.dims[2];
int ystride = 4*g.dims[2]*g.dims[0];
int zstride = 1;
/* internal constant j pillar pairs */
for (i=0; i<g.dims[0]; ++i){
for (j=0; j<g.dims[1]-1; ++j){
int p1 = 2*i + ystride* (2*j+1);
int p2 = p1 + xstride;
process_pair(p1, p2, g.dims, g.zcorn, ystride, zstride);
}
}
#endif
free (intersections);
free (faces);
free (fptr);
free (neighbors);
free (zptr);
free (plist);
free (zlist);
/* Free whatever was allocated in initGrdecl. */
freeGrdecl(&g);
}

6
test.m Normal file
View File

@ -0,0 +1,6 @@
g=simpleGrdecl([2, 1, 4], @(x) -0.05+0.1*x+0.01 );
G=processGRDECL(g);
%clf,plotGrid(G);view(3);
g.ACTNUM=int32(g.ACTNUM);

219
uniquepoints.c Normal file
View File

@ -0,0 +1,219 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include "grdecl.h"
#include "uniquepoints.h"
#include "matalloc.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)
/* Compar 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,
double *z[], int *a[])
{
fprintf(stderr, "\n");
int i,j;
double *ptr = list;
for (i=0; i<n; ++i){
for (j=0; j<m; ++j){
if (a[j][i/2]) *ptr++ = z[j][i];
/* else fprintf(stderr, "skipping point in inactive cell\n"); */
}
}
qsort(list, ptr-list, sizeof(double), compare);
return ptr-list;
}
/* Remove points that are closer than tolerance in list */
/* of increasing doubles */
/*-------------------------------------------------------*/
static int uniquify(int n, double *list, double tolerance)
{
int i;
int pos = 1; /* Keep first value */
double val = list[pos];
for (i=1; i<n; ++i){
if (list[i] - val > tolerance){
val = list[i];
list[pos++] = val;
}
}
/* Keep last value (one way or the other...) */
if (list[n-1] - val > tolerance){
list[pos-1] = list[n-1];
}
return pos;
}
/* Along single pillar: */
static int* assignPointNumbers(int begin,
int end,
double *zlist,
int n,
double *zcorn,
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. */
double *z = zcorn;
int *a = actnum;
int *p = plist;
k = begin;
*p++ = INT_MIN; /* Padding to ease processing of faults */
for (i=0; i<n; ++i){
/* Skip inactive cells */
if (!a[i/2]) {
p[0] = p[-1]; /* Inactive cells are collapsed leaving void space.*/
++p;
continue;
}
/* Find next k such that zlist[k] < z[i] < zlist[k+1] */
while (k < end && zlist[k] + tolerance < z[i]){
k++;
}
/* assert (k < len && z[i] - zlist[k] <= tolerance) */
if (k == end || z[i] - zlist[k] > tolerance){
fprintf(stderr, "What!?\n");
}
*p++ = k;
}
*p++ = INT_MAX;/* Padding to ease processing of faults */
return p;
}
/*-------------------------------------------------------*/
static void igetvectors(int dims[3], int i, int j, int *field, 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);
}
/*-------------------------------------------------------*/
static void dgetvectors(int dims[3], int i, int j, double *field, 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);
}
/* 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) */
/*-------------------------------------------------------*/
void finduniquepoints(struct Grdecl *g,
/* return values: */
double *zlist, /* list of z-values on each pillar*/
int *zptr, /* pointer to start of each pillar*/
int *plist) /* list of point numbers on each pillar*/
{
int i,j;
int d1[3] = {2*g->dims[0], 2*g->dims[1], 2*g->dims[2]};
int len = 0;
double *zout = zlist;
int pos = 1;
zptr[0] = 0;
/* 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){
int *a[4];
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, 0.0);
/* Increment pointer to sparse table of unique zcorn values */
zout = zout + len;
zptr[pos] = zptr[pos-1] + len;
++pos;
}
}
/* Loop over all vertical sets of zcorn values, assign point numbers */
int *p = plist;
int nz = 2*g->dims[2];
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);
int *a = g->actnum + cix;
double *z = g->zcorn + zix;
p = assignPointNumbers(zptr[pix], zptr[pix+1], zlist,
nz, z, a, p, 0.0);
}
}
}

8
uniquepoints.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef UNIQUEPOINTS_H
#define UNIQUEPOINTS_H
void finduniquepoints(struct Grdecl *g,
double *zout,
int *zptr,
int *plist);
#endif