opm-core/mex_generate_coarsegrid.c
Bård Skaflestad 4f1939b81b Don't use cutesy contractions in error messages. Refer to the same
parameter names as in the documentation.
2010-08-31 14:00:43 +00:00

289 lines
7.8 KiB
C

#include <stddef.h>
#include <mex.h>
#include "mrst_api.h"
#include "coarse_conn.h"
/* ---------------------------------------------------------------------- */
static int
args_ok(int nlhs, int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
{
int ok;
ok = ((nlhs == 1) && ((nrhs == 2) || (nrhs == 3)));
ok = ok && (mxIsStruct(prhs[0]));
ok = ok && (mxIsDouble(prhs[1]) || mxIsInt32(prhs[1]));
ok = ok && ((nrhs == 2) || (mxIsNumeric(prhs[2]) &&
(mxGetNumberOfElements(prhs[2]) == 1)));
return ok;
}
/* ---------------------------------------------------------------------- */
static int *
extract_partition(size_t n, const mxArray *M_p)
/* ---------------------------------------------------------------------- */
{
size_t i;
int *p;
int *pi;
double *pd;
n = mxGetNumberOfElements(M_p);
p = mxMalloc(n * sizeof *p);
if (p != NULL) {
if (mxIsDouble(M_p)) {
pd = mxGetPr(M_p);
for (i = 0; i < n; i++) { p[i] = pd[i] - 1; }
} else {
pi = mxGetData(M_p);
for (i = 0; i < n; i++) { p[i] = pi[i] - 1; }
}
}
return p;
}
/* ---------------------------------------------------------------------- */
static void
assign_int_vec(int *v, mxArray *M_v)
/* ---------------------------------------------------------------------- */
{
size_t i, n;
int *pi;
double *pd;
n = mxGetNumberOfElements(M_v);
if (mxIsDouble(M_v)) {
pd = mxGetPr(M_v);
for (i = 0; i < n; i++) { pd[i] = v[i] + 1; }
} else {
pi = mxGetData(M_v);
for (i = 0; i < n; i++) { pi[i] = v[i] + 1; }
}
}
/* ---------------------------------------------------------------------- */
static mxArray *
generate_coarse_cells(struct coarse_topology *topo)
/* ---------------------------------------------------------------------- */
{
mxArray *cells;
mxArray *fld;
const char *fields[] = {"num", "facePos", "faces"};
int nfields = sizeof(fields) / sizeof(fields[0]);
mwSize dims[] = { 1, 1 };
mwSize ndims = sizeof(dims) / sizeof(dims[0]);
cells = mxCreateStructArray(ndims, dims, nfields, fields);
if (cells != NULL) {
fld = mxCreateDoubleScalar(topo->nblocks);
if (fld != NULL) {
mxSetField(cells, 0, "num", fld);
}
fld = mxCreateNumericMatrix(topo->nblocks + 1, 1,
mxINT32_CLASS, mxREAL);
if (fld != NULL) {
assign_int_vec(topo->blkfacepos, fld);
mxSetField(cells, 0, "facePos", fld);
}
fld = mxCreateNumericMatrix(topo->blkfacepos[topo->nblocks], 1,
mxINT32_CLASS, mxREAL);
if (fld != NULL) {
assign_int_vec(topo->blkfaces, fld);
mxSetField(cells, 0, "faces", fld);
}
}
return cells;
}
/* ---------------------------------------------------------------------- */
static mxArray *
generate_coarse_faces(struct coarse_topology *topo)
/* ---------------------------------------------------------------------- */
{
mxArray *faces;
mxArray *fld;
int fld_no;
size_t f;
int *pi;
const char *fields[] = {"num", "neighbors", "tag"};
int nfields = sizeof(fields) / sizeof(fields[0]);
mwSize dims[] = { 1, 1 };
mwSize ndims = sizeof(dims) / sizeof(dims[0]);
faces = mxCreateStructArray(ndims, dims, nfields, fields);
if (faces != NULL) {
fld = mxCreateDoubleScalar(topo->nfaces);
if (fld != NULL) {
mxSetField(faces, 0, "num", fld);
}
fld = mxCreateNumericMatrix(topo->nfaces, 2, mxINT32_CLASS, mxREAL);
if (fld != NULL) {
pi = mxGetData(fld);
for (f = 0; f < (size_t)topo->nfaces; f++) {
pi[f + 0*topo->nfaces] = topo->neighbours[2*f + 0] + 1;
pi[f + 1*topo->nfaces] = topo->neighbours[2*f + 1] + 1;
}
mxSetField(faces, 0, "neighbors", fld);
}
fld = mxCreateNumericMatrix(topo->nfaces, 1, mxINT32_CLASS, mxREAL);
if (fld != NULL) {
pi = mxGetData(fld);
for (f = 0; f < (size_t)topo->nfaces; f++) {
pi[f] = 0;
}
mxSetField(faces, 0, "tag", fld);
}
if (topo->subfacepos != NULL) {
fld_no = mxAddField(faces, "subfacePos");
if (fld_no >= 0) {
fld = mxCreateNumericMatrix(topo->nfaces + 1, 1,
mxINT32_CLASS, mxREAL);
if (fld != NULL) {
assign_int_vec(topo->subfacepos, fld);
mxSetFieldByNumber(faces, 0, fld_no, fld);
}
}
}
if (topo->subfaces != NULL) {
fld_no = mxAddField(faces, "subfaces");
if (fld_no >= 0) {
fld = mxCreateNumericMatrix(topo->subfacepos[topo->nfaces], 1,
mxINT32_CLASS, mxREAL);
if (fld != NULL) {
assign_int_vec(topo->subfaces, fld);
mxSetFieldByNumber(faces, 0, fld_no, fld);
}
}
}
}
return faces;
}
/* ---------------------------------------------------------------------- */
static mxArray *
generate_coarse_grid(struct coarse_topology *topo,
const mxArray *p)
/* ---------------------------------------------------------------------- */
{
mxArray *CG;
mxArray *fld;
const char *fields[] = {"cells", "faces", "partition"};
int nfields = sizeof(fields) / sizeof(fields[0]);
mwSize dims[] = { 1, 1 };
mwSize ndims = sizeof(dims) / sizeof(dims[0]);
CG = mxCreateStructArray(ndims, dims, nfields, fields);
if (CG != NULL) {
fld = generate_coarse_cells(topo);
if (fld != NULL) {
mxSetField(CG, 0, "cells", fld);
}
fld = generate_coarse_faces(topo);
if (fld != NULL) {
mxSetField(CG, 0, "faces", fld);
}
fld = mxDuplicateArray(p);
if (fld != NULL) {
mxSetField(CG, 0, "partition", fld);
}
}
return CG;
}
/*
* CG = mex_generate_coarsegrid(G, p)
* CG = mex_generate_coarsegrid(G, p, expct_nconn)
*/
/* ---------------------------------------------------------------------- */
void
mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
{
int nc, nf, *p, *fneighbours;
int expct_nconn;
char errmsg[1023 + 1];
struct coarse_topology *topo;
if (args_ok(nlhs, nrhs, prhs)) {
nc = getNumberOfCells(prhs[0]);
nf = getNumberOfFaces(prhs[0]);
p = extract_partition(nc, prhs[1]);
fneighbours = getFaceCellNeighbors(prhs[0]);
if ((p != NULL) && (fneighbours != NULL)) {
if (nrhs == 2) {
expct_nconn = 0;
} else {
expct_nconn = mxGetScalar(prhs[2]);
}
if (expct_nconn < 0) {
expct_nconn = 0;
}
topo = coarse_topology_create(nc, nf, expct_nconn,
p, fneighbours);
plhs[0] = generate_coarse_grid(topo, prhs[1]);
coarse_topology_destroy(topo);
mxFree(fneighbours); mxFree(p);
}
} else {
sprintf(errmsg,
"Calling sequence is\n"
"\tCG = %s(G, p) %% or\n"
"\tCG = %s(G, p, expected_nconn)",
mexFunctionName(), mexFunctionName());
mexErrMsgTxt(errmsg);
}
}