Add preliminary support for wells in 'mex_ip_simple'. This is

untested, so disable direct MEX building for the time being.
This commit is contained in:
Bård Skaflestad 2010-08-11 18:31:01 +00:00
parent caea28b2fb
commit fc082bcc9a
4 changed files with 282 additions and 76 deletions

View File

@ -1,3 +1,4 @@
#include <assert.h>
#include <string.h>
#include <mex.h>
@ -46,24 +47,26 @@ static int
verify_grid_structure(const mxArray *G)
/* ------------------------------------------------------------------ */
{
int nodes_ok, faces_ok, cells_ok, field_no;
int nodes_ok = 0, faces_ok = 0, cells_ok = 0, field_no;
mxArray *pm;
nodes_ok = mxGetFieldNumber(G, "nodes") >= 0;
if (mxIsStruct(G)) {
nodes_ok = mxGetFieldNumber(G, "nodes") >= 0;
field_no = mxGetFieldNumber(G, "faces");
faces_ok = field_no >= 0;
if (faces_ok) {
pm = mxGetFieldByNumber(G, 0, field_no);
faces_ok = verify_faces_structure(pm);
}
field_no = mxGetFieldNumber(G, "faces");
faces_ok = field_no >= 0;
if (faces_ok) {
pm = mxGetFieldByNumber(G, 0, field_no);
faces_ok = verify_faces_structure(pm);
}
field_no = mxGetFieldNumber(G, "cells");
cells_ok = field_no >= 0;
if (cells_ok) {
pm = mxGetFieldByNumber(G, 0, field_no);
cells_ok = verify_cells_structure(pm);
field_no = mxGetFieldNumber(G, "cells");
cells_ok = field_no >= 0;
if (cells_ok) {
pm = mxGetFieldByNumber(G, 0, field_no);
cells_ok = verify_cells_structure(pm);
}
}
return nodes_ok && faces_ok && cells_ok;
@ -72,35 +75,46 @@ verify_grid_structure(const mxArray *G)
/* ------------------------------------------------------------------ */
static int
verify_structural_consistency(int nlhs, int nrhs, const mxArray *prhs[])
verify_well_structure(const mxArray *W)
/* ------------------------------------------------------------------ */
{
int rock_ok;
int grid_ok;
int conn_ok;
int well_ok = mxIsStruct(W);
mxAssert((nlhs == 1) && (nrhs == 4),
"Must be called with exactly four inputs and one output.");
if (well_ok && (mxGetNumberOfElements(W) > 0)) {
/* All STRUCT array elements have the same fields... */
well_ok = (mxGetFieldNumber(W, "cells") >= 0);
well_ok = well_ok && (mxGetFieldNumber(W, "WI" ) >= 0);
}
mxAssert(mxIsStruct(prhs[0]) && mxIsStruct(prhs[1]),
"First two inputs must be STRUCTs.");
return well_ok;
}
mxAssert((mxGetNumberOfElements(prhs[0]) == 1) &&
(mxGetNumberOfElements(prhs[1]) == 1),
"First two inputs must be 1-by-1 STRUCT arrays.");
grid_ok = verify_grid_structure(prhs[0]);
/* ------------------------------------------------------------------ */
static int
args_ok(int nlhs, int nrhs, const mxArray *prhs[])
/* ------------------------------------------------------------------ */
{
int grid_ok = 0, rock_ok = 0, well_ok;
/* rock must contain a field 'perm' */
rock_ok = mxGetFieldNumber(prhs[1], "perm") >= 0;
if (nrhs > 0) {
grid_ok = verify_grid_structure(prhs[0]);
}
/* connection structure */
conn_ok = (mxIsDouble(prhs[2]) || mxIsInt32(prhs[2])) &&
(mxIsDouble(prhs[3]) || mxIsInt32(prhs[3])) &&
(mxGetNumberOfElements(prhs[2]) <
mxGetNumberOfElements(prhs[3]));
if (nrhs > 1) {
/* rock must contain a field 'perm' */
rock_ok = mxIsStruct(prhs[1]) &&
(mxGetFieldNumber(prhs[1], "perm") >= 0);
}
return grid_ok && rock_ok && conn_ok;
/* well structure */
if (nrhs == 2) {
well_ok = 1;
} else {
well_ok = verify_well_structure(prhs[2]);
}
return (nlhs == 3) && grid_ok && rock_ok && well_ok;
}
@ -191,48 +205,163 @@ extract_connection_data(const mxArray *M_nconn, const mxArray *M_conn,
/* ------------------------------------------------------------------ */
static int
extract_cell_data(const mxArray *G,
const mxArray *M_nconn, const mxArray *M_conn,
int *max_ncf, int *sum_nconn, int *sum_nconn2,
int **ncfaces, int **nconn, int **conn,
double **ccentroids, double **cvolumes)
static void
extract_grid_connections(const mxArray *G, int *nc, int *nf,
int **ncf, int **pconn, int **conn)
/* ------------------------------------------------------------------ */
{
int ncells, i, n;
int i;
ncells = getNumberOfCells(G);
*ncfaces = getCellFacePos(G);
*nc = getNumberOfCells(G);
*nf = getNumberOfFaces(G);
extract_connection_data(M_nconn, M_conn, ncells,
nconn, conn, sum_nconn, sum_nconn2);
/* Yes, two calls to getCellFacePos() */
*ncf = getCellFacePos(G);
*pconn = getCellFacePos(G);
*max_ncf = 0;
*conn = getCellFaces(G);
for(i=0; i<ncells; ++i)
{
n = (*ncfaces)[i+1] - (*ncfaces)[i];
(*ncfaces)[i] = n;
*max_ncf = MAX(*max_ncf, n);
}
*ccentroids = getCellCentroids(G);
*cvolumes = getCellVolumes(G);
return ncells;
for (i = 0; i < *nc; i++) {
(*ncf)[i] = (*ncf)[i + 1] - (*ncf)[i];
}
}
/* ------------------------------------------------------------------ */
static void
deallocate_cell_data(int *ncfaces, int *nconn, int *conn, double *ccentroids)
add_well_connections(const mxArray *W, int nc, int nf,
int *nw, int *pconn, int **conn)
/* ------------------------------------------------------------------ */
{
int c, i, np, fld, neconn, w, p, n, dst, src;
int *pi, *cwork, *c2w, *w2c, *tmp;
double *pd;
mxArray *M_perfs;
if ((*nw = mxGetNumberOfElements(W)) > 0) {
fld = mxGetFieldNumber(W, "cells");
}
neconn = 0; /* Number of additional/extra conns */
for (w = 0; w < *nw; w++) {
neconn += mxGetNumberOfElements(mxGetFieldByNumber(W, w, fld));
}
if (neconn > 0) {
cwork = mxCalloc(nc , sizeof *cwork); /* all(cwork == 0) */
c2w = mxMalloc(neconn * sizeof *c2w );
w2c = mxMalloc(neconn * sizeof *w2c );
i = 0;
for (w = 0; w < *nw; w++) {
M_perfs = mxGetFieldByNumber(W, w, fld);
np = mxGetNumberOfElements(M_perfs);
if (mxIsInt32(M_perfs)) {
pi = mxGetData(M_perfs);
for (p = 0; p < np; p++, i++) {
c = pi[p] - 1;
w2c[i] = c;
c2w[i] = w;
cwork[c]++;
}
} else {
pd = mxGetPr(M_perfs);
for (p = 0; p < np; p++, i++) {
c = pd[p] - 1;
w2c[i] = c;
c2w[i] = w;
cwork[c]++;
}
}
}
tmp = mxRealloc(*conn, (pconn[nc] + neconn) * sizeof *tmp);
if (tmp != NULL) {
n = pconn[nc] - pconn[nc - 1]; /* # exisiting conns */
pconn[nc] += neconn; /* ubnd, *LAST* bin */
for (c = nc - 1; c > 0; c--) {
dst = pconn[c + 1] - (n + cwork[c]);
src = pconn[c + 0];
/* Move existing connections to start of new bin.
* Note: Bins may overlap so use memmove(). */
memmove(tmp + dst, tmp + src, n * sizeof *tmp);
/* Set cell's pointer for new connections. */
cwork[c] = dst + n;
n = pconn[c] - pconn[c - 1];
pconn[c] = dst;
}
/* Assign well connections.
* Note: Generally, new DOF is nf + # ext. wells + c2w[i].
* In this case, though, # ext. wells == 0 ... */
for (i = 0; i < neconn; i++) {
assert (cwork[w2c[i]] < pconn[w2c[i] + 1]);
tmp[cwork[w2c[i]]++] = nf + c2w[i];
}
/* Finally, assign updated connection structure. */
*conn = tmp;
}
mxFree(w2c); mxFree(c2w); mxFree(cwork);
}
}
/* ------------------------------------------------------------------ */
static void
count_connections(int nc, const int *pconn,
int *max_nconn, int *sum_nconn2)
/* ------------------------------------------------------------------ */
{
int c, nconn;
*max_nconn = *sum_nconn2 = 0;
for (c = 0; c < nc; c++) {
nconn = pconn[c + 1] - pconn[c];
*max_nconn = MAX(*max_nconn, nconn);
*sum_nconn2 += nconn * nconn;
}
}
/* ------------------------------------------------------------------ */
static int
extract_cell_data(const mxArray *G,
double **ccentroids, double **cvolumes)
/* ------------------------------------------------------------------ */
{
*ccentroids = getCellCentroids(G);
*cvolumes = getCellVolumes(G);
return getNumberOfCells(G);
}
/* ------------------------------------------------------------------ */
static void
deallocate_cell_data(int *ncf, int *pconn, int *conn, double *ccentroids)
/* ------------------------------------------------------------------ */
{
mxFree(ccentroids);
mxFree(conn);
mxFree(nconn);
mxFree(ncfaces);
mxFree(pconn);
mxFree(ncf);
}
@ -245,8 +374,22 @@ deallocate_perm_data(double *K)
}
/* ------------------------------------------------------------------ */
static void
set_connections_M(int nc, const int *pconn, const int *conn,
int *pconn_M, int *conn_M)
/* ------------------------------------------------------------------ */
{
int i;
for (i = 0; i <= nc ; i++) { pconn_M[i] = pconn[i] + 1; }
for (i = 0; i < pconn[nc]; i++) { conn_M [i] = conn [i] + 1; }
}
/*
* BI = mex_ip_simple(G, rock, nconn, conn)
* [BI, connPos, conns] = mex_ip_simple(G, rock)
* [BI, connPos, conns] = mex_ip_simple(G, rock, W)
*/
/* ------------------------------------------------------------------ */
@ -255,6 +398,64 @@ mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
/* ------------------------------------------------------------------ */
{
int d, nc, nf, nw = 0, max_nconn, sum_nconn2;
int *pconn, *conn, *ncf, *fneighbour;
double *fcentroid, *fnormal, *farea, *ccentroids, *cvolumes, *perm;
char errmsg[1023 + 1];
double *Binv;
if (args_ok(nlhs, nrhs, prhs)) {
extract_grid_connections(prhs[0], &nc, &nf, &ncf, &pconn, &conn);
if (nrhs == 3) {
/* [...] = mex_ip_simple(G, rock, W) */
add_well_connections(prhs[2], nc, nf, &nw, pconn, &conn);
} else {
nw = 0;
}
count_connections(nc, pconn, &max_nconn, &sum_nconn2);
extract_face_data(prhs[0], &fneighbour, &farea,
&fnormal, &fcentroid);
extract_cell_data(prhs[0], &ccentroids, &cvolumes);
d = getNumberOfDimensions(prhs[0]);
perm = getPermeability(mxGetField(prhs[1], 0, "perm"), d);
/* Create return values */
plhs[0] = mxCreateDoubleMatrix (sum_nconn2, 1, mxREAL);
plhs[1] = mxCreateNumericMatrix(nc + 1 , 1, mxINT32_CLASS, mxREAL);
plhs[2] = mxCreateNumericMatrix(pconn[nc] , 1, mxINT32_CLASS, mxREAL);
/* Compute IP for all cells (reservoir) */
Binv = mxGetPr(plhs[0]); /* mxCreateDoubleMatrix == ZEROS */
/* mim_ip_simple_all() requires zeroed target array... */
mim_ip_simple_all(nc, d, max_nconn, ncf, pconn, conn,
fneighbour, fcentroid, fnormal, farea,
ccentroids, cvolumes, perm, Binv);
set_connections_M(nc, pconn, conn,
mxGetData(plhs[1]),
mxGetData(plhs[2]));
deallocate_perm_data(perm);
deallocate_cell_data(ncf, pconn, conn, ccentroids);
deallocate_face_data(fneighbour, fnormal, fcentroid);
} else {
sprintf(errmsg,
"Calling sequence is\n"
"\t[BI, connPos, conn] = %s(G, rock)\nor\n"
"\t[BI, connPos, conn] = %s(G, rock, W)\n",
mexFunctionName(), mexFunctionName());
mexErrMsgTxt(errmsg);
}
}
#if 0
int ncells, nfaces, max_ncf, sum_ncf, sum_ncf2, d, structure_ok;
int *fneighbour;
@ -269,6 +470,8 @@ mexFunction(int nlhs, mxArray *plhs[],
structure_ok = verify_structural_consistency(nlhs, nrhs, prhs);
if (structure_ok) {
extract_grid_connections(
d = getNumberOfDimensions(prhs[0]);
nfaces = extract_face_data(prhs[0], &fneighbour, &farea,
@ -298,4 +501,4 @@ mexFunction(int nlhs, mxArray *plhs[],
} else {
plhs[0] = mxCreateDoubleScalar(mxGetNaN());
}
}
#endif

View File

@ -65,6 +65,8 @@ function varargout = mex_ip_simple(varargin)
% $Date$
% $Revision$
error('Currently being re-worked');
buildmex CFLAGS="\$CFLAGS -Wall -Wextra -ansi -pedantic ...
-Wformat-nonliteral -Wcast-align -Wpointer-arith ...
-Wbad-function-cast -Wmissing-prototypes -Wstrict-prototypes ...

View File

@ -16,27 +16,27 @@
/* ------------------------------------------------------------------ */
void
mim_ip_simple_all(int ncells, int d, int max_ncf, int *ncf,
int *nconn, int *cf,
mim_ip_simple_all(int ncells, int d, int max_nconn, int *ncf,
int *pconn, int *conn,
int *fneighbour, double *fcentroid, double *fnormal,
double *farea, double *ccentroid, double *cvol,
double *perm, double *Binv)
/* ------------------------------------------------------------------ */
{
int i, j, c, f, nf, fpos, fpos2, lwork;
int i, j, c, f, nf, nconn, fpos2, lwork;
double *C, *N, *A, *work, s;
double cc[3] = { 0.0 }; /* No more than 3 space dimensions */
lwork = 64 * (max_ncf * d); /* 64 from ILAENV() */
C = malloc((max_ncf * d) * sizeof *C);
N = malloc((max_ncf * d) * sizeof *N);
A = malloc(max_ncf * sizeof *A);
work = malloc(lwork * sizeof *work);
lwork = 64 * (max_nconn * d); /* 64 from ILAENV() */
C = malloc((max_nconn * d) * sizeof *C);
N = malloc((max_nconn * d) * sizeof *N);
A = malloc(max_nconn * sizeof *A);
work = malloc(lwork * sizeof *work);
if ((C != NULL) && (N != NULL) && (A != NULL) && (work != NULL)) {
fpos = fpos2 = 0;
fpos2 = 0;
for (c = 0; c < ncells; c++) {
for (j = 0; j < d; j++) {
@ -46,7 +46,7 @@ mim_ip_simple_all(int ncells, int d, int max_ncf, int *ncf,
nf = ncf[c];
for (i = 0; i < nf; i++) {
f = cf[fpos + i];
f = conn[pconn[c] + i];
s = 2.0*(fneighbour[2 * f] == c) - 1.0;
A[i] = farea[f];
@ -57,11 +57,12 @@ mim_ip_simple_all(int ncells, int d, int max_ncf, int *ncf,
}
}
mim_ip_simple(nf, nconn[c], d, cvol[c], &perm[c * d * d],
nconn = pconn[c + 1] - pconn[c];
mim_ip_simple(nf, nconn, d, cvol[c], &perm[c * d * d],
C, A, N, &Binv[fpos2], work, lwork);
fpos += nconn[c];
fpos2 += nconn[c] * nconn[c];
fpos2 += nconn * nconn;
}
}

View File

@ -21,7 +21,7 @@ void mim_ip_simple(int nf, int nconn, int d,
double *work, int lwork);
void mim_ip_simple_all(int ncells, int d, int max_ncf, int *ncf,
int *nconn, int *conn,
int *pconn, int *conn,
int *fneighbour, double *fcentroid, double *fnormal,
double *farea, double *ccentroid, double *cvol,
double *perm, double *Binv);