Merge pull request #1 from bska/master

Bring in more resilient grid processing and geometry calculation
This commit is contained in:
Alf Birger Rustad 2012-06-26 23:02:58 -07:00
commit 90f26cc883
20 changed files with 1921 additions and 1823 deletions

View File

@ -57,8 +57,6 @@ opm/core/grid/cornerpoint_grid.c \
opm/core/grid/cpgpreprocess/facetopology.c \
opm/core/grid/cpgpreprocess/geometry.c \
opm/core/grid/cpgpreprocess/preprocess.c \
opm/core/grid/cpgpreprocess/readvector.cpp \
opm/core/grid/cpgpreprocess/sparsetable.c \
opm/core/grid/cpgpreprocess/uniquepoints.c \
opm/core/linalg/LinearSolverFactory.cpp \
opm/core/linalg/LinearSolverInterface.cpp \
@ -160,8 +158,6 @@ opm/core/grid/cpgpreprocess/facetopology.h \
opm/core/grid/cpgpreprocess/geometry.h \
opm/core/grid/cpgpreprocess/grdecl.h \
opm/core/grid/cpgpreprocess/preprocess.h \
opm/core/grid/cpgpreprocess/readvector.hpp \
opm/core/grid/cpgpreprocess/sparsetable.h \
opm/core/grid/cpgpreprocess/uniquepoints.h \
opm/core/linalg/LinearSolverFactory.hpp \
opm/core/linalg/LinearSolverInterface.hpp \

View File

@ -13,39 +13,38 @@
//===========================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of The Open Reservoir Simulator Project (OpenRS).
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 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.
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 <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocess.h"
#include "sparsetable.h"
#include "facetopology.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))
#define MIN(i,j) ((i)<(j) ? (i) : (j))
#define MAX(i,j) ((i)>(j) ? (i) : (j))
#define DEBUG 1
@ -59,296 +58,309 @@ along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
/*------------------------------------------------------*/
/* Determine face geometry first, then compute intersections. */
/* Determine face topology first, then compute intersection. */
/* All intersections that occur are present in the final face geometry.*/
static int *computeFaceTopology(int *a1,
int *a2,
int *b1,
int *b2,
int intersect[4],
int *faces)
static int *
computeFaceTopology(const int *a1, const int *a2,
const int *b1, const int *b2,
int intersect[4], int *faces)
{
int mask[8] = {-1};
int k, *f;
int mask[8];
int k;
int *f;
/* 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]; }
for (k = 0; k < 8; k++) { mask[k] = -1; }
/* 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]; }
#if DEBUG
/* Illegal situations */
if (mask [0] == mask[2] ||
mask [0] == mask[4] ||
mask [2] == mask[6] ||
mask [4] == mask[6]){
fprintf(stderr, "Illegal Partial pinch!\n");
}
/* Illegal situations */
if (mask [0] == mask[2] ||
mask [0] == mask[4] ||
mask [2] == mask[6] ||
mask [4] == mask[6]){
fprintf(stderr, "Illegal Partial pinch!\n");
}
#endif
/* Partial pinch of face */
if (mask[0] == mask[6]){
mask[6] = -1;
}
if (mask[2] == mask[4]){
mask[4] = -1;
}
/* 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[3]; /* top-top */
mask[3] = -1;
mask[5] = intersect[0]; /* bottom-bottom*/
mask[7] = -1;
/* bottom-top */
if (intersect[1] != -1){
if(a1[0] > b1[1]){ /* intersection[1] left of (any) intersection[0] */
mask[0] = -1;
mask[6] = -1;
mask[7] = intersect[1];
/* Partial pinch of face */
if (mask[0] == mask[6]){
mask[6] = -1;
}
else{
mask[2] = -1;
mask[4] = -1;
mask[3] = intersect[1];
}
}
/* top-bottom */
if (intersect[2] != -1){
if(a1[1] < b1[0]){ /* intersection[2] left of (any) intersection[3] */
mask[0] = -1;
mask[6] = -1;
mask[7] = intersect[2];
if (mask[2] == mask[4]){
mask[4] = -1;
}
else{
mask[2] = -1;
mask[4] = -1;
mask[3] = intersect[2];
/* 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[3]; /* top-top */
mask[3] = -1;
mask[5] = intersect[0]; /* bottom-bottom*/
mask[7] = -1;
/* bottom-top */
if (intersect[1] != -1){
if(a1[0] > b1[1]){ /* intersection[1] left of (any) intersection[0] */
mask[0] = -1;
mask[6] = -1;
mask[7] = intersect[1];
}
else{
mask[2] = -1;
mask[4] = -1;
mask[3] = intersect[1];
}
}
}
f = faces;
for (k=7; k>=0; --k){
if(mask[k] != -1){
*f++ = mask[k];
/* top-bottom */
if (intersect[2] != -1){
if(a1[1] < b1[0]){ /* intersection[2] left of (any) intersection[3] */
mask[0] = -1;
mask[6] = -1;
mask[7] = intersect[2];
}
else{
mask[2] = -1;
mask[4] = -1;
mask[3] = intersect[2];
}
}
f = faces;
for (k=7; k>=0; --k){
if(mask[k] != -1){
*f++ = mask[k];
}
}
}
#if DEBUG>1
/* Check for repeated nodes:*/
{
int i;
fprintf(stderr, "face: ");
for (i=0; i<8; ++i){
fprintf(stderr, "%d ", mask[i]);
for (k=0; k<8; ++k){
if (i!=k && mask[i] != -1 && mask[i] == mask[k]){
fprintf(stderr, "Repeated node in faulted face\n");
}
/* Check for repeated nodes:*/
int i;
fprintf(stderr, "face: ");
for (i=0; i<8; ++i){
fprintf(stderr, "%d ", mask[i]);
for (k=0; k<8; ++k){
if (i!=k && mask[i] != -1 && mask[i] == mask[k]){
fprintf(stderr, "Repeated node in faulted face\n");
}
}
}
}
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
#endif
return f;
return f;
}
/* a) If we assume that the index increase when z increase for
each pillar (but only separately), we can use only the point indices.
/* a) If we assume that the index increase when z increase for each
pillar (but only separately), we can use only the point indices,
since we only need to compare z-values on one pillar at a time.
b) We assume no intersections occur on the first and last lines.
This is convenient in the identification of (unique) intersections.
b) We assume input is preprocessed such that no intersections occur
on the first and last lines, for instance by padding the grid with
extra cells. This is convenient in the identification of (unique)
intersections.
*/
#define lineintersection(a1,a2,b1,b2)(((a1>b1)&&(a2<b2))||((a1<b1)&&(a2>b2)))
static int faceintersection(int *a1, int *a2, int *b1, int *b2)
#define LINE_INTERSECTION(a1, a2, b1, b2) \
(((a1 > b1) && (a2 < b2)) || \
((a1 < b1) && (a2 > b2)))
static int
faceintersection(const int *a1, const int *a2,
const int *b1, const int *b2)
{
return
max(a1[0],b1[0]) < min(a1[1],b1[1]) ||
max(a2[0],b2[0]) < min(a2[1],b2[1]) ||
lineintersection(a1[0], a2[0], b1[0], b2[0]) ||
lineintersection(a1[1], a2[1], b1[1], b2[1]);
return
MAX(a1[0], b1[0]) < MIN(a1[1], b1[1]) ||
MAX(a2[0], b2[0]) < MIN(a2[1], b2[1]) ||
LINE_INTERSECTION(a1[0], a2[0], b1[0], b2[0]) ||
LINE_INTERSECTION(a1[1], a2[1], b1[1], b2[1]);
}
#define meaningful_face !((a1[i] ==INT_MIN) && (b1[j] ==INT_MIN)) && \
!((a1[i+1]==INT_MAX) && (b1[j+1]==INT_MAX))
#define MEANINGFUL_FACE(i, j) \
(! ((a1[i] == INT_MIN) && (b1[j] == INT_MIN)) && \
! ((a1[i+1] == INT_MAX) && (b1[j+1] == INT_MAX)))
/* work should be pointer to 2n ints initialised to zero . */
void findconnections(int n, int *pts[4],
int *intersectionlist,
int *work,
struct processed_grid *out)
int *intersectionlist,
int *work,
struct processed_grid *out)
{
/* 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];
/* 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;
int *ibottom = work + n;
int *f = out->face_nodes + out->face_ptr[out->number_of_faces];
int *c = out->face_neighbors + 2*out->number_of_faces;
int *tmp;
/* Intersection record for top line and bottomline of a */
int *itop = work;
int *ibottom = work + n;
int *f = out->face_nodes + out->face_ptr[out->number_of_faces];
int *c = out->face_neighbors + 2*out->number_of_faces;
int k1 = 0;
int k2 = 0;
int k1 = 0;
int k2 = 0;
int i,j=0;
int intersect[4]= {-1};
/* for (i=0; i<2*n; work[i++]=-1); */
for (i = 0; i<n-1; ++i){
if (a1[i] == a1[i+1] && a2[i] == a2[i+1]) continue;
int i,j=0;
int intersect[4];
int *tmp;
/* for (i=0; i<2*n; work[i++]=-1); */
for (i = 0; i < 4; i++) { intersect[i] = -1; }
for (i = 0; i < n - 1; ++i) {
/* pinched a-cell */
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])))
{
/* pinched b-cell */
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)){
/* Completely matching faces */
if (((a1[i] == b1[j]) && (a1[i+1] == b1[j+1])) &&
((a2[i] == b2[j]) && (a2[i+1] == b2[j+1]))) {
if (MEANINGFUL_FACE(i, j)) {
int cell_a = i%2 != 0 ? (i-1)/2 : -1;
int cell_b = j%2 != 0 ? (j-1)/2 : -1;
if (cell_a != -1 || cell_b != -1){
*c++ = cell_a;
*c++ = cell_b;
/* face */
*f++ = a1[i];
*f++ = a2[i];
/* avoid duplicating nodes in pinched faces */
if (a2[i+1] != a2[i]) { *f++ = a2[i+1]; }
if (a1[i+1] != a1[i]) { *f++ = a1[i+1]; }
out->face_ptr[++out->number_of_faces] = f - out->face_nodes;
}
else{
;
}
}
}
/* Non-matching faces */
else{
/* Find new intersection */
if (LINE_INTERSECTION(a1[i+1], a2[i+1],
b1[j+1], b2[j+1])) {
itop[j+1] = out->number_of_nodes++;
/* store point numbers of intersecting lines */
*intersectionlist++ = a1[i+1];
*intersectionlist++ = a2[i+1];
*intersectionlist++ = b1[j+1];
*intersectionlist++ = b2[j+1];
}else{
itop[j+1] = -1;
}
/* 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 no INT_MIN or
* INT_MAX appear in a or b. */
if (MEANINGFUL_FACE(i,j)) {
/*
Even indices refer to space between cells,
odd indices refer to cells
*/
int cell_a = i%2 != 0 ? (i-1)/2 : -1;
int cell_b = j%2 != 0 ? (j-1)/2 : -1;
if (cell_a != -1 || cell_b != -1){
*c++ = cell_a;
*c++ = cell_b;
while(j<n-1 && (b1[j] < a1[i+1] || b2[j] < a2[i+1])){
f = computeFaceTopology(a1+i, a2+i, b1+j, b2+j, intersect, f);
if (b1[j] == b1[j+1] && b2[j] == b2[j+1]){
itop[j+1] = itop[j];
++j;
continue;
}
out->face_ptr[++out->number_of_faces] = f - out->face_nodes;
}
else{
;
}
}
}
}
/* 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; }
/* --------------------------------------------------------- */
/* face a(i,i+1) and face b(j,j+1) have nonzero intersection */
/* --------------------------------------------------------- */
if (faceintersection(a1+i, a2+i, b1+j, b2+j)){
/* 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 (meaningful_face){
int cell_a = i%2 ? (i-1)/2 : -1;
int cell_b = j%2 ? (j-1)/2 : -1;
if (cell_a != -1 || cell_b != -1){
*c++ = cell_a;
*c++ = cell_b;
/* face */
*f++ = a1[i];
*f++ = a2[i];
/* avoid duplicating nodes in pinched faces */
if (a2[i+1] != a2[i]) *f++ = a2[i+1];
if (a1[i+1] != a1[i]) *f++ = a1[i+1];
out->face_ptr[++out->number_of_faces] = f - out->face_nodes;
}
else{
;
/*
fprintf(stderr,
"Warning. For some reason we get face connecting void spaces\n");
*/
}
}
}
/* Non-matching faces */
else{
/* Find new intersection */
if (lineintersection(a1[i+1],a2[i+1],b1[j+1],b2[j+1])) {
itop[j+1] = out->number_of_nodes++;
/* store point numbers of intersecting lines */
*intersectionlist++ = a1[i+1];
*intersectionlist++ = a2[i+1];
*intersectionlist++ = b1[j+1];
*intersectionlist++ = b2[j+1];
}else{
itop[j+1] = -1;
}
/* 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 no INT_MIN or INT_MAX appear in a or b. */
if (meaningful_face){
/*
Even indices refer to space between cells,
odd indices refer to cells
*/
int cell_a = i%2 ? (i-1)/2 : -1;
int cell_b = j%2 ? (j-1)/2 : -1;
j = j+1;
}
if (cell_a != -1 || cell_b != -1){
*c++ = cell_a;
*c++ = cell_b;
f = computeFaceTopology(a1+i, a2+i, b1+j, b2+j, intersect, f);
/* Swap intersection records: top line of a[i,i+1] is bottom
* line of a[i+1,i+2] */
tmp = itop; itop = ibottom; ibottom = tmp;
out->face_ptr[++out->number_of_faces] = f - out->face_nodes;
}
else{
;
/*
fprintf(stderr,
"Warning. For some reason we get face connecting void spaces\n");
*/
}
}
}
}
/* Zero out the "new" itop */
for(j=0;j<n; ++j) { itop[j]=-1; }
/* 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;
/* Set j to appropriate start position for next i */
j = MIN(k1, k2);
}
/* Swap intersection records: top line of a[i,i+1] is bottom line of a[i+1,i+2] */
tmp = itop; itop = ibottom; ibottom = tmp;
/* Zero out the "new" itop */
for(j=0;j<n; ++j) itop[j]=-1;
/* Set j to appropriate start position for next i */
j = min(k1, k2);
}
}
/* Local Variables: */

View File

@ -13,35 +13,35 @@
//===========================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of The Open Reservoir Simulator Project (OpenRS).
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 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.
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 <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENRS_FACETOPOLOGY_HEADER
#define OPENRS_FACETOPOLOGY_HEADER
#ifndef OPM_FACETOPOLOGY_HEADER
#define OPM_FACETOPOLOGY_HEADER
void findconnections(int n, int *pts[4],
int *intersectionlist,
int *intersectionlist,
int *work,
struct processed_grid *out);
struct processed_grid *out);
#endif /* OPENRS_FACETOPOLOGY_HEADER */
#endif /* OPM_FACETOPOLOGY_HEADER */
/* Local Variables: */
/* c-basic-offset:4 */

View File

@ -131,6 +131,12 @@ compute_cell_geometry(int ndims, double *coords,
double ccell[3];
double cface[3] = {0};
const double twothirds = 0.666666666666666666666666666667;
int ndigits;
ndigits = ((int) (log(ncells) / log(10.0))) + 1;
for (c=0; c<ncells; ++c)
{
int num_faces;
@ -192,31 +198,25 @@ compute_cell_geometry(int ndims, double *coords,
cross(u,v,w);
tet_volume = 0;
for(i=0; i<ndims; ++i){
tet_volume += 0.5/3 * w[i]*(x[i]-xcell[i]);
/*tet_volume += 0.5/3 * w[i]*(x[i]-xcell[i]);*/
tet_volume += w[i] * (x[i] - xcell[i]);
}
/*tet_volume = fabs(tet_volume);*/
tet_volume *= 0.5 / 3;
subnormal_sign=0.0;
for(i=0; i<ndims; ++i){
subnormal_sign += w[i]*fnormals[3*face+i];
}
if(subnormal_sign<0){
tet_volume*=-1.0;
if (subnormal_sign < 0.0) {
tet_volume = - tet_volume;
}
if(!(neighbors[2*face+0]==c)){
tet_volume*=-1.0;
if (neighbors[2*face + 0] != c) {
tet_volume = - tet_volume;
}
volume += tet_volume;
if(!(volume>0)){
fprintf(stderr, "Internal error in compute_cell_geometry: negative volume\n");
}
/* face centroid of triangle */
for (i=0; i<ndims; ++i) cface[i] = (x[i]+twothirds*0.5*(u[i]+v[i]));
@ -229,6 +229,13 @@ compute_cell_geometry(int ndims, double *coords,
for (i=0; i<ndims; ++i) u[i] = v[i];
}
}
if (! (volume > 0.0)) {
fprintf(stderr,
"Internal error in mex_compute_geometry(%*d): "
"negative volume\n", ndigits, c);
}
for (i=0; i<ndims; ++i) ccentroids[3*c+i] = xcell[i] + ccell[i]/volume;
cvolumes[c] = volume;
}

View File

@ -1,12 +1,16 @@
#ifndef GRDECL_H
#define GRDECL_H
#ifndef GRDECL_H_INCLUDED
#define GRDECL_H_INCLUDED
struct grdecl{
int dims[3];
const double *coord;
const double *zcorn;
const int *actnum;
int dims[3];
const double *coord;
const double *zcorn;
const int *actnum;
};
#endif
#endif /* GRDECL_H_INCLUDED */
/* Local Variables: */
/* c-basic-offset:4 */
/* End: */

View File

@ -1,4 +1,4 @@
//===========================================================================
/*=========================================================================
//
// File: mxgrdecl.c
//
@ -10,97 +10,107 @@
//
// $Revision$
//
//===========================================================================
//=======================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of The Open Reservoir Simulator Project (OpenRS).
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 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.
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 <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <mex.h>
#include <grdecl.h>
#include "grdecl.h"
#include "mxgrdecl.h"
/* Get COORD, ZCORN, ACTNUM and DIMS from mxArray. */
/*-------------------------------------------------------*/
void mx_init_grdecl(struct grdecl *g, const mxArray *s)
{
int i,n;
mxArray *field;
int numel;
int i,n;
size_t numel;
mxArray *cartdims=NULL, *actnum=NULL, *coord=NULL, *zcorn=NULL;
mxArray *cartdims=NULL, *actnum=NULL, *coord=NULL, *zcorn=NULL;
if (!mxIsStruct(s)
|| !(cartdims = mxGetField(s, 0, "cartDims"))
|| !(actnum = mxGetField(s, 0, "ACTNUM"))
|| !(coord = mxGetField(s, 0, "COORD"))
|| !(zcorn = mxGetField(s, 0, "ZCORN"))
)
{
char str[]="Input must be a single Matlab struct with fields\n"
"cartDims, ACTNUM, COORD and ZCORN\n";
mexErrMsgTxt(str);
}
numel = mxGetNumberOfElements(cartdims);
if (!mxIsNumeric(cartdims) || numel != 3){
mexErrMsgTxt("cartDims field must be 3 numbers");
}
double *tmp = mxGetPr(cartdims);
n = 1;
for (i=0; i<3; ++i){
g->dims[i] = tmp[i];
n *= tmp[i];
}
if (!mxIsStruct(s)
|| !(cartdims = mxGetField(s, 0, "cartDims"))
|| !(coord = mxGetField(s, 0, "COORD"))
|| !(zcorn = mxGetField(s, 0, "ZCORN"))
)
{
char str[]="Input must be a single MATLAB struct with fields\n"
"'cartDims', 'COORD' and 'ZCORN'. ACTNUM may be included.\n";
mexErrMsgTxt(str);
}
numel = mxGetNumberOfElements(actnum);
if (mxGetClassID(actnum) != mxINT32_CLASS ||
numel != g->dims[0]*g->dims[1]*g->dims[2] ){
mexErrMsgTxt("ACTNUM field must be nx*ny*nz numbers int32");
}
g->actnum = mxGetData(actnum);
numel = mxGetNumberOfElements(cartdims);
if (!mxIsNumeric(cartdims) || numel != 3){
mexErrMsgTxt("cartDims field must be 3 numbers");
}
if (mxIsDouble(cartdims)) {
double *tmp = mxGetPr(cartdims);
for (i = 0; i < 3; ++i) {
g->dims[i] = (int) tmp[i];
}
}
else if (mxIsInt32(cartdims)) {
int *tmp = mxGetData(cartdims);
memcpy(g->dims, tmp, 3 * sizeof *g->dims);
}
n = g->dims[0];
for (i = 1; i < 3; i++) { n *= g->dims[ i ]; }
field = mxGetField(s, 0, "COORD");
numel = mxGetNumberOfElements(coord);
if (mxGetClassID(coord) != mxDOUBLE_CLASS ||
numel != 6*(g->dims[0]+1)*(g->dims[1]+1)){
mexErrMsgTxt("COORD field must have 6*(nx+1)*(ny+1) doubles.");
}
g->coord = mxGetPr(coord);
if ((actnum = mxGetField(s, 0, "ACTNUM")) != NULL) {
numel = mxGetNumberOfElements(actnum);
if ((! mxIsInt32(actnum)) || (numel != (size_t)(n))) {
mexErrMsgTxt("ACTNUM field must be nx*ny*nz numbers int32");
}
g->actnum = mxGetData(actnum);
}
else {
g->actnum = NULL;
}
numel = mxGetNumberOfElements(zcorn);
if (mxGetClassID(zcorn) != mxDOUBLE_CLASS ||
numel != 8*g->dims[0]*g->dims[1]*g->dims[2]){
mexErrMsgTxt("ZCORN field must have 8*nx*ny*nz doubles.");
}
g->zcorn = mxGetPr(zcorn);
numel = mxGetNumberOfElements(coord);
if ((! mxIsDouble(coord)) ||
numel != (size_t)(6*(g->dims[0]+1)*(g->dims[1]+1))) {
mexErrMsgTxt("COORD field must have 6*(nx+1)*(ny+1) doubles.");
}
g->coord = mxGetPr(coord);
numel = mxGetNumberOfElements(zcorn);
if ((! mxIsDouble(zcorn)) ||
numel != (size_t)(8*g->dims[0]*g->dims[1]*g->dims[2])) {
mexErrMsgTxt("ZCORN field must have 8*nx*ny*nz doubles.");
}
g->zcorn = mxGetPr(zcorn);
}
/* Local Variables: */
/* c-basic-offset:4 */
/* End: */

View File

@ -1,4 +1,4 @@
//===========================================================================
/*=========================================================================
//
// File: mxgrdecl.h
//
@ -10,33 +10,35 @@
//
// $Revision$
//
//===========================================================================
//=======================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of The Open Reservoir Simulator Project (OpenRS).
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 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.
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 <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENRS_MXGRDECL_HEADER
#define OPENRS_MXGRDECL_HEADER
#ifndef OPM_MXGRDECL_HEADER
#define OPM_MXGRDECL_HEADER
void mx_init_grdecl (struct grdecl *g, const mxArray *s);
#endif // OPENRS_MXGRDECL_HEADER
#endif /* OPM_MXGRDECL_HEADER */
/* Local Variables: */
/* c-basic-offset:4 */
/* End: */

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@
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
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,
@ -53,26 +53,26 @@ extern "C" {
/* Output structure holding grid topology */
struct processed_grid{
int m;
int n;
int m; /** Upper bound on "number_of_faces" */
int n; /** Upper bound on "number_of_nodes" */
int dimensions[3]; /* Cartesian dimension */
int number_of_faces;
int *face_nodes; /* Nodes numbers of each face sequentially. */
int *face_ptr; /* Start position for each face in face_nodes. */
int *face_neighbors; /* Global cell numbers. 2 ints per face sequentially */
enum face_tag *face_tag;
int number_of_nodes;
int number_of_nodes_on_pillars;
int number_of_nodes;
int number_of_nodes_on_pillars; /** Total number of unique cell vertices that lie on pillars. */
double *node_coordinates; /* 3 doubles per node, sequentially */
int number_of_cells; /* number of active cells */
int *local_cell_index; /* Global to local map */
};
void process_grdecl (const struct grdecl *g,
double tol,
void process_grdecl (const struct grdecl *g,
double tol,
struct processed_grid *out);
void free_processed_grid(struct processed_grid *g);

View File

@ -13,255 +13,453 @@
//===========================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
Copyright 2009, 2010, 2011, 2012 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010, 2011, 2012 Statoil ASA.
This file is part of The Open Reservoir Simulator Project (OpenRS).
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 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.
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 <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright 2009, 2010 SINTEF ICT, Applied Mathematics. */
/* Mex gateway by Jostein R. Natvig, SINTEF ICT. */
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <mex.h>
#include "preprocess.h"
#include "mxgrdecl.h"
void fill_grid(mxArray **out, struct processed_grid *grid)
/* ---------------------------------------------------------------------- */
static mxArray *
allocate_nodes(size_t nnodes)
/* ---------------------------------------------------------------------- */
{
const char *names[] = {"nodes", "faces", "cells", "cartDims", "type"};
mxArray *G = mxCreateStructMatrix(1,1,sizeof names / sizeof names[0],names);
size_t nflds;
const char *fields[] = { "num", "coords" };
int i,j;
double *ptr;
mxArray *nodes, *num, *coords;
nflds = sizeof(fields) / sizeof(fields[0]);
/* nodes */
const char *n2[] = {"num", "coords"};
mxArray *nodes = mxCreateStructMatrix(1,1,sizeof n2 / sizeof n2[0],n2);
mxSetField(nodes, 0, "num", mxCreateDoubleScalar(grid->number_of_nodes));
nodes = mxCreateStructMatrix(1, 1, nflds, fields);
mxArray *nodecoords = mxCreateDoubleMatrix(grid->number_of_nodes, 3, mxREAL);
ptr = mxGetPr(nodecoords);
num = mxCreateDoubleScalar(nnodes);
coords = mxCreateDoubleMatrix(nnodes, 3, mxREAL);
for (j=0;j<3;++j)
{
for(i=0; i<grid->number_of_nodes; ++i)
{
ptr[i+grid->number_of_nodes*j] = grid->node_coordinates[3*i+j];
if ((nodes != NULL) && (num != NULL) && (coords != NULL)) {
mxSetField(nodes, 0, "num" , num);
mxSetField(nodes, 0, "coords", coords);
} else {
if (coords != NULL) { mxDestroyArray(coords); }
if (num != NULL) { mxDestroyArray(num); }
if (nodes != NULL) { mxDestroyArray(nodes); }
nodes = NULL;
}
}
mxSetField(nodes, 0, "coords", nodecoords);
mxSetField(G, 0, "nodes", nodes);
/* faces */
const char *n3[] = {"num", "neighbors", "nodes", "numNodes", "nodePos", "tag"};
mxArray *faces = mxCreateStructMatrix(1,1,sizeof n3 / sizeof n3[0], n3);
mxSetField(faces, 0, "num", mxCreateDoubleScalar(grid->number_of_faces));
mxArray *faceneighbors = mxCreateNumericMatrix(grid->number_of_faces, 2,
mxINT32_CLASS, mxREAL);
{
int *iptr = mxGetData(faceneighbors);
for(j=0; j<2; ++j)
{
for (i=0; i<grid->number_of_faces; ++i)
{
int ix = grid->face_neighbors[2*i+j];
if (ix == -1)
{
iptr[i+grid->number_of_faces*j] = 0;
}
else
{
iptr[i+grid->number_of_faces*j] = ix+1;
}
}
}
}
mxSetField(faces, 0, "neighbors", faceneighbors);
mxArray *numnodes = mxCreateNumericMatrix(grid->number_of_faces, 1,
mxINT32_CLASS, mxREAL);
mxArray *nodepos = mxCreateNumericMatrix(grid->number_of_faces+1, 1,
mxINT32_CLASS, mxREAL);
{
int *iptr1 = mxGetData(numnodes);
int *iptr2 = mxGetData(nodepos);
iptr2[0] = 1;
for (i=0; i<grid->number_of_faces; ++i)
{
iptr1[i] = grid->face_ptr[i+1] - grid->face_ptr[i];
iptr2[i+1] = iptr2[i] + iptr1[i];
}
}
mxSetField(faces, 0, "numNodes", numnodes);
mxSetField(faces, 0, "nodePos", nodepos);
mxArray *tags = mxCreateNumericMatrix(grid->number_of_faces, 1,
mxINT32_CLASS, mxREAL);
{
int *iptr = mxGetData(tags);
for (i = 0; i < grid->number_of_faces; ++i)
{
iptr[i] = grid->face_tag[i] + 1;
}
}
mxSetField(faces, 0, "tag", tags);
const char *n4[] = {"num", "faces", "facePos", "indexMap"};
mxArray *cells = mxCreateStructMatrix(1,1,sizeof n4 / sizeof n4[0], n4);
mxSetField(cells, 0, "num", mxCreateDoubleScalar(grid->number_of_cells));
mxArray *map = mxCreateNumericMatrix(grid->number_of_cells, 1,
mxINT32_CLASS, mxREAL);
{
int *iptr = mxGetData(map);
for(i=0; i<grid->number_of_cells; ++i)
{
iptr[i] = grid->local_cell_index[i]+1;
}
}
mxSetField(cells, 0, "indexMap", map);
mxArray *facepos = mxCreateNumericMatrix(grid->number_of_cells+1, 1,
mxINT32_CLASS, mxREAL);
{
int *iptr = mxGetData(facepos);
for(i=0; i<grid->number_of_cells+1; ++i)
{
iptr[i] = 0;
}
for (i=0; i<2*grid->number_of_faces; ++i)
{
int c=grid->face_neighbors[i];
if(c != -1)
{
iptr[c+1]++;
}
}
iptr[0] = 1;
for(i=0; i<grid->number_of_cells; ++i)
{
iptr[i+1] += iptr[i];
}
}
mxSetField(cells, 0, "facePos", facepos);
int *counter = calloc(grid->number_of_cells, sizeof(*counter));
int num_half_faces = 0;
{
int *iptr = mxGetData(facepos);
for(i=0; i<grid->number_of_cells; ++i)
{
counter[i] = num_half_faces;
num_half_faces += iptr[i+1]-iptr[i];
}
}
mxArray *cellfaces = mxCreateNumericMatrix(num_half_faces, 1,
mxINT32_CLASS, mxREAL);
{
int *iptr = mxGetData(cellfaces);
for (i=0; i<grid->number_of_faces; ++i)
{
int c1 = grid->face_neighbors[2*i];
int c2 = grid->face_neighbors[2*i+1];
if(c1 != -1) iptr[counter[c1]++] = i+1;
if(c2 != -1) iptr[counter[c2]++] = i+1;
}
}
mxSetField(cells, 0, "faces", cellfaces);
mxSetField(G, 0, "cells", cells);
int n = grid->face_ptr[grid->number_of_faces];
mxArray *facenodes = mxCreateNumericMatrix(n, 1,
mxINT32_CLASS, mxREAL);
{
int *iptr = mxGetData(facenodes);
for (i=0; i<n; ++i)
{
iptr[i] = grid->face_nodes[i]+1;
}
}
mxSetField(faces, 0, "nodes", facenodes);
mxSetField(G, 0, "faces", faces);
free(counter);
/* cartDims */
mxArray *cartDims = mxCreateDoubleMatrix(1, 3, mxREAL);
ptr = mxGetPr(cartDims);
ptr[0] = grid->dimensions[0];
ptr[1] = grid->dimensions[1];
ptr[2] = grid->dimensions[2];
mxSetField(G, 0, "cartDims", cartDims);
/* type */
mxArray *type = mxCreateCellMatrix(1, 1);
mxSetCell(type, 0, mxCreateString("processgrid"));
mxSetField(G, 0, "type", type);
out[0] = G;
return nodes;
}
/* Gateway routine for Matlab mex function. */
/*-------------------------------------------------------*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
static void
fill_nodes(mxArray *nodes, struct processed_grid *grid)
/* ---------------------------------------------------------------------- */
{
/* Set up data passed from Matlab */
struct grdecl g;
struct processed_grid out;
double tolerance = 0.0;
size_t i, j, nnodes;
double *coords;
mx_init_grdecl(&g, prhs[0]);
if (nrhs == 2)
{
tolerance = mxGetScalar (prhs[1]);
}
nnodes = grid->number_of_nodes;
coords = mxGetPr(mxGetField(nodes, 0, "coords"));
process_grdecl(&g, tolerance, &out);
if (plhs >0)
{
/* write to matlab struct */
fill_grid(plhs, &out);
}
/* Free whatever was allocated in initGrdecl. */
free_processed_grid(&out);
for (j = 0; j < 3; ++j) {
for (i = 0; i < nnodes; ++i) {
*coords++ = grid->node_coordinates[3*i + j];
}
}
}
/* ---------------------------------------------------------------------- */
static mxArray *
allocate_faces(size_t nf, size_t nfacenodes)
/* ---------------------------------------------------------------------- */
{
size_t nflds;
const char *fields[] = { "num", "neighbors", "nodePos", "nodes", "tag" };
mxArray *faces, *num, *neighbors, *nodePos, *nodes, *tag;
nflds = sizeof(fields) / sizeof(fields[0]);
faces = mxCreateStructMatrix(1, 1, nflds, fields);
num = mxCreateDoubleScalar (nf);
neighbors = mxCreateNumericMatrix(nf , 2, mxINT32_CLASS, mxREAL);
nodePos = mxCreateNumericMatrix(nf + 1 , 1, mxINT32_CLASS, mxREAL);
nodes = mxCreateNumericMatrix(nfacenodes, 1, mxINT32_CLASS, mxREAL);
tag = mxCreateNumericMatrix(nf , 1, mxINT32_CLASS, mxREAL);
if ((faces != NULL) && (num != NULL) && (neighbors != NULL) &&
(nodePos != NULL) && (nodes != NULL) && (tag != NULL)) {
mxSetField(faces, 0, "num" , num);
mxSetField(faces, 0, "neighbors", neighbors);
mxSetField(faces, 0, "nodePos" , nodePos);
mxSetField(faces, 0, "nodes" , nodes);
mxSetField(faces, 0, "tag" , tag);
} else {
if (tag != NULL) { mxDestroyArray(tag); }
if (nodes != NULL) { mxDestroyArray(nodes); }
if (nodePos != NULL) { mxDestroyArray(nodePos); }
if (neighbors != NULL) { mxDestroyArray(neighbors); }
if (num != NULL) { mxDestroyArray(num); }
if (faces != NULL) { mxDestroyArray(faces); }
faces = NULL;
}
return faces;
}
/* ---------------------------------------------------------------------- */
static void
fill_faces(mxArray *faces, struct processed_grid *grid)
/* ---------------------------------------------------------------------- */
{
size_t i, f, nf, nfn;
int *pi;
nf = grid->number_of_faces;
/* Fill faces.neighbors */
pi = mxGetData(mxGetField(faces, 0, "neighbors"));
for (i = 0; i < 2; i++) {
for (f = 0; f < nf; f++) {
/* Add one for one-based indexing in M */
*pi++ = grid->face_neighbors[2*f + i] + 1;
}
}
/* Fill faces.nodePos */
pi = mxGetData(mxGetField(faces, 0, "nodePos"));
for (i = 0; i <= nf; i++) { pi[i] = grid->face_ptr[i] + 1; }
/* Fill faces.nodes */
pi = mxGetData(mxGetField(faces, 0, "nodes"));
nfn = grid->face_ptr[nf]; /* Total number of face nodes */
for (i = 0; i < nfn; i++) { pi[i] = grid->face_nodes[i] + 1; }
/* Fill faces.tag */
pi = mxGetData(mxGetField(faces, 0, "tag"));
for (f = 0; f < nf; f++) { pi[f] = grid->face_tag[f] + 1; }
}
/* ---------------------------------------------------------------------- */
static size_t
count_halffaces(size_t nf, const int *neighbors)
/* ---------------------------------------------------------------------- */
{
int c1, c2;
size_t nhf, f;
for (f = nhf = 0; f < nf; f++) {
c1 = neighbors[2*f + 0];
c2 = neighbors[2*f + 1];
nhf += c1 >= 0;
nhf += c2 >= 0;
}
return nhf;
}
/* ---------------------------------------------------------------------- */
static mxArray *
allocate_cells(size_t nc, size_t ncf)
/* ---------------------------------------------------------------------- */
{
size_t nflds;
const char *fields[] = { "num", "facePos", "faces", "indexMap" };
mxArray *cells, *num, *facePos, *faces, *indexMap;
nflds = sizeof(fields) / sizeof(fields[0]);
cells = mxCreateStructMatrix(1, 1, nflds, fields);
num = mxCreateDoubleScalar (nc);
facePos = mxCreateNumericMatrix(nc + 1, 1, mxINT32_CLASS, mxREAL);
faces = mxCreateNumericMatrix(ncf , 2, mxINT32_CLASS, mxREAL);
indexMap = mxCreateNumericMatrix(nc , 1, mxINT32_CLASS, mxREAL);
if ((cells != NULL) && (num != NULL) && (facePos != NULL) &&
(faces != NULL) && (indexMap != NULL)) {
mxSetField(cells, 0, "num" , num );
mxSetField(cells, 0, "facePos" , facePos );
mxSetField(cells, 0, "faces" , faces );
mxSetField(cells, 0, "indexMap", indexMap);
} else {
if (indexMap != NULL) { mxDestroyArray(indexMap); }
if (faces != NULL) { mxDestroyArray(faces); }
if (facePos != NULL) { mxDestroyArray(facePos); }
if (num != NULL) { mxDestroyArray(num); }
if (cells != NULL) { mxDestroyArray(cells); }
cells = NULL;
}
return cells;
}
/* ---------------------------------------------------------------------- */
static void
fill_cells(mxArray *cells, struct processed_grid *grid)
/* ---------------------------------------------------------------------- */
{
size_t c, nc, f, nf, i;
int c1, c2, cf_tag, nhf;
int *pi1, *pi2;
nc = grid->number_of_cells;
nf = grid->number_of_faces;
/* Simultaneously fill cells.facePos and cells.faces by transposing the
* neighbours mapping. */
pi1 = mxGetData(mxGetField(cells, 0, "facePos"));
pi2 = mxGetData(mxGetField(cells, 0, "faces" ));
for (i = 0; i < nc + 1; i++) { pi1[i] = 0; }
/* 1) Count connections (i.e., faces per cell). */
for (f = 0; f < nf; f++) {
c1 = grid->face_neighbors[2*f + 0];
c2 = grid->face_neighbors[2*f + 1];
if (c1 >= 0) { pi1[c1 + 1] += 1; }
if (c2 >= 0) { pi1[c2 + 1] += 1; }
}
/* 2) Define start pointers (really, position *end* pointers at start). */
for (c = 1; c <= nc; c++) {
pi1[0] += pi1[c];
pi1[c] = pi1[0] - pi1[c];
}
/* 3) Fill connection structure whilst advancing end pointers. */
nhf = pi1[0];
pi1[0] = 0;
mxAssert (((size_t) nhf) == mxGetM(mxGetField(cells, 0, "faces")),
"Number of half faces (SIZE(cells.faces,1)) incorrectly "
"determined earlier.");
for (f = 0; f < nf; f++) {
cf_tag = 2*grid->face_tag[f] + 1; /* [1, 3, 5] */
c1 = grid->face_neighbors[2*f + 0];
c2 = grid->face_neighbors[2*f + 1];
if (c1 >= 0) {
pi2[ pi1[ c1 + 1 ] + 0*nhf ] = f + 1;
pi2[ pi1[ c1 + 1 ] + 1*nhf ] = cf_tag + 1; /* out */
pi1[ c1 + 1 ] += 1;
}
if (c2 >= 0) {
pi2[ pi1[ c2 + 1 ] + 0*nhf ] = f + 1;
pi2[ pi1[ c2 + 1 ] + 1*nhf ] = cf_tag + 0; /* in */
pi1[ c2 + 1 ] += 1;
}
}
/* Finally, adjust pointer array for one-based indexing in M. */
for (i = 0; i < nc + 1; i++) { pi1[i] += 1; }
/* Fill cells.indexMap. Note that despite the name, 'local_cell_index'
* really *is* the (zero-based) indexMap of the 'processed_grid'. */
pi1 = mxGetData(mxGetField(cells, 0, "indexMap"));
for (c = 0; c < nc; c++) { pi1[c] = grid->local_cell_index[c] + 1; }
}
/* ---------------------------------------------------------------------- */
static mxArray *
allocate_grid(struct processed_grid *grid, const char *func)
/* ---------------------------------------------------------------------- */
{
size_t nflds, nhf;
const char *fields[] = { "nodes", "faces", "cells",
"type", "cartDims", "griddim" };
mxArray *G, *nodes, *faces, *cells;
mxArray *type, *typestr, *cartDims, *griddim;
nflds = sizeof(fields) / sizeof(fields[0]);
nhf = count_halffaces(grid->number_of_faces, grid->face_neighbors);
G = mxCreateStructMatrix(1, 1, nflds, fields);
nodes = allocate_nodes(grid->number_of_nodes);
faces = allocate_faces(grid->number_of_faces,
grid->face_ptr[ grid->number_of_faces ]);
cells = allocate_cells(grid->number_of_cells, nhf);
type = mxCreateCellMatrix(1, 1);
typestr = mxCreateString(func);
cartDims = mxCreateDoubleMatrix(1, 3, mxREAL);
griddim = mxCreateDoubleScalar(3);
if ((G != NULL) && (nodes != NULL) && (faces != NULL) &&
(cells != NULL) && (type != NULL) && (typestr != NULL) &&
(cartDims != NULL) && (griddim != NULL)) {
mxSetCell(type, 0, typestr);
mxSetField(G, 0, "nodes" , nodes );
mxSetField(G, 0, "faces" , faces );
mxSetField(G, 0, "cells" , cells );
mxSetField(G, 0, "type" , type );
mxSetField(G, 0, "cartDims", cartDims);
mxSetField(G, 0, "griddim" , griddim );
} else {
if (griddim != NULL) { mxDestroyArray(griddim); }
if (cartDims != NULL) { mxDestroyArray(cartDims); }
if (typestr != NULL) { mxDestroyArray(typestr); }
if (type != NULL) { mxDestroyArray(type); }
if (cells != NULL) { mxDestroyArray(cells); }
if (faces != NULL) { mxDestroyArray(faces); }
if (nodes != NULL) { mxDestroyArray(nodes); }
if (G != NULL) { mxDestroyArray(G); }
G = NULL;
}
return G;
}
/* ---------------------------------------------------------------------- */
static void
fill_grid(mxArray *G, struct processed_grid *grid)
/* ---------------------------------------------------------------------- */
{
double *pr;
pr = mxGetPr(mxGetField(G, 0, "cartDims"));
pr[0] = grid->dimensions[0];
pr[1] = grid->dimensions[1];
pr[2] = grid->dimensions[2];
fill_nodes(mxGetField(G, 0, "nodes"), grid);
fill_faces(mxGetField(G, 0, "faces"), grid);
fill_cells(mxGetField(G, 0, "cells"), grid);
}
/* ---------------------------------------------------------------------- */
static int
args_ok(int nlhs, int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
{
int ok;
ok = (nlhs == 1) && ((nrhs == 1) || (nrhs == 2));
ok = ok && !mxIsEmpty(prhs[0]);
ok = ok && mxIsStruct(prhs[0]);
ok = ok && (mxGetFieldNumber(prhs[0], "cartDims") >= 0);
ok = ok && (mxGetFieldNumber(prhs[0], "COORD" ) >= 0);
ok = ok && (mxGetFieldNumber(prhs[0], "ZCORN" ) >= 0);
if (ok && (nrhs == 2)) {
ok = mxIsDouble(prhs[1]) && (mxGetNumberOfElements(prhs[1]) == 1);
}
return ok;
}
/* ---------------------------------------------------------------------- */
static double
define_tolerance(int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
{
double tol;
tol = 0.0;
if (nrhs == 2) {
tol = mxGetScalar(prhs[1]);
}
return tol;
}
/* G = processgrid(grdecl)
G = processgrid(grdecl, tolerance)
*/
/* ---------------------------------------------------------------------- */
void
mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
/* ---------------------------------------------------------------------- */
{
double tolerance;
char errmsg[1023 + 1];
struct grdecl grdecl;
struct processed_grid g;
if (args_ok(nlhs, nrhs, prhs)) {
mx_init_grdecl(&grdecl, prhs[0]);
tolerance = define_tolerance(nrhs, prhs);
process_grdecl(&grdecl, tolerance, &g);
plhs[0] = allocate_grid(&g, mexFunctionName());
if (plhs[0] != NULL) {
fill_grid(plhs[0], &g);
} else {
/* Failed to create grid structure. Return empty. */
plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
}
free_processed_grid(&g);
} else {
sprintf(errmsg,
"Calling sequence is\n\t"
"G = %s(grdecl)\t%%or\n\t"
"G = %s(grdecl, tolerance)\n"
"The 'grdecl' must be a valid structure with fields\n"
"\t'cartDims', 'COORD', 'ZCORN'",
mexFunctionName(), mexFunctionName());
mexErrMsgTxt(errmsg);
}
}
/* Local Variables: */
/* c-basic-offset:4 */
/* End: */

View File

@ -1,12 +1,14 @@
function varargout = processgrid(varargin)
function G = processgrid(varargin)
%Compute grid topology and geometry from pillar grid description.
%
% SYNOPSIS:
% G = processGRDECL(grdecl)
% G = processgrid(grdecl)
% G = processgrid(grdecl,ztol)
%
% PARAMETERS:
% grdecl - Raw pillar grid structure, as defined by function
% 'readGRDECL', with fields COORDS, ZCORN and, possibly, ACTNUM.
% ztol - tolerance for unique points
%
% RETURNS:
% G - Valid grid definition containing connectivity, cell
@ -32,10 +34,33 @@ function varargout = processgrid(varargin)
% $Date$
% $Revision$
% Build MEX edition of same.
%
buildmex CFLAGS='$CFLAGS -Wall -fPIC' processgrid.c preprocess.c ...
uniquepoints.c facetopology.c sparsetable.c mxgrdecl.c
G = processgrid_mex(varargin{:});
G.griddim = 3;
G = splitDisconnectedGrid(G, false);
end
% Call MEX edition.
[varargout{1:nargout}] = processgrid(varargin{:});
function G = splitDisconnectedGrid(G, verbose)
% Check if grid is connected
ix = all(G.faces.neighbors~=0, 2);
I = [G.faces.neighbors(ix,1);G.faces.neighbors(ix,2)];
J = [G.faces.neighbors(ix,2);G.faces.neighbors(ix,1)];
N = double(max(G.faces.neighbors(:)));
A = sparse(double(I),double(J),1,N,N)+speye(N);
clear ix I J
[a,b,c,d]=dmperm(A); %#ok
clear A b d
if numel(c) > 2,
dispif(verbose, '\nGrid has %d disconnected components\n', ...
numel(c)- 1);
% Partition grid into connected subgrids
for i = 1:numel(c) - 1,
g(i) = extractSubgrid(G, a(c(i):c(i+1)-1)); %#ok
sz(i) = g(i).cells.num; %#ok
g(i).cartDims = G.cartDims; %#ok
end
% Return largest (in number of cells) grid first
[i,i] = sort(-sz); %#ok
G = g(i);
end
end

View File

@ -1,282 +0,0 @@
/*===========================================================================
//
// Author: Jostein R. Natvig <Jostein.R.Natvig@sintef.no>
//
//==========================================================================*/
/*
Copyright 2011 SINTEF ICT, Applied Mathematics.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <vector>
#include "readvector.hpp"
struct ParserState {
int error;
};
template <typename T>
static void parse_next_token (FILE *fp, struct ParserState *s,
T *v, int *count);
static char *get_token_string (FILE *fp, struct ParserState *s, char *buf);
static void skip_line (FILE *fp, struct ParserState *s);
static char *convert_string (int *value, char *str);
static char *convert_string (double *value, char *str);
static void split_token_string(char *str, char *rstr, char *vstr);
static int get_repeat_count (char *rstr, struct ParserState *s);
template <typename T>
static void get_value (char *vstr, struct ParserState *s, T *v);
/* ------------------------------------------------------------------ */
static const int bufsz = 1024;
/* ------------------------------------------------------------------ */
template <typename T>
static void readvector(FILE *fp, struct ParserState *s, std::vector<T>& v)
{
T value;
int count, i;
count = 1;
s->error = 0;
while (count > 0){
parse_next_token(fp, s, &value, &count);
for (i=0; i<count; ++i)
{
v.push_back(value);
}
}
if (s->error) {
assert(0);
}
}
/* ------------------------------------------------------------------ */
template <typename T>
static void parse_next_token(FILE *fp, struct ParserState *s, T *v, int *r)
{
char str[bufsz];
char rstr[bufsz];
char vstr[bufsz];
str[0]='\0';
while (strlen(str)==0)
{
get_token_string(fp, s, str);
}
if (str[0] == '/')
{
/* end-of-vector marker */
*r = 0;
}
else
{
split_token_string(str, rstr, vstr);
*r = get_repeat_count(rstr, s);
get_value(vstr, s, v);
if (s->error)
{
/* signal abort to caller */
*r = 0;
}
}
}
/* ------------------------------------------------------------------ */
/* split string 'rrrr*vvvv' in strings 'rrrr' and 'vvvv' */
static void split_token_string(char *str, char *rstr, char *vstr)
{
char *ptr;
ptr=strchr(str, '*');
if ((ptr != NULL) && (ptr!=str)) {
while(str!=ptr)
{
*rstr++=*str++;
}
*rstr='\0';
str++;
}
else
{
rstr[0]='\0';
}
while((*vstr++=*str++) )
{
continue ;
}
*vstr='\0';
}
/* ------------------------------------------------------------------ */
static int get_repeat_count(char *rstr, struct ParserState *s)
{
int r;
char *ptr;
if (strlen(rstr)>0)
{
ptr=convert_string(&r, rstr);
if ((ptr==rstr) || (strlen(ptr)>0) || (r<1))
{
s->error = 1;
}
}
else
{
r = 1;
}
return r;
}
/* ------------------------------------------------------------------ */
template <typename T>
static void get_value(char *vstr, struct ParserState *s, T *v)
{
char *ptr;
if (strlen(vstr)>0)
{
/* Convert FORTRAN style floats 3.13D-6 to IEEE */
for(ptr=vstr; *ptr; ++ptr)
{
if (*ptr=='D')
{
*ptr='E';
}
}
ptr = convert_string(v, vstr);
if ((ptr==vstr) || (strlen(ptr)>0))
{
s->error = 1;
}
}
else
{
s->error = 1;
}
}
/* ------------------------------------------------------------------ */
static char *get_token_string(FILE *fp, struct ParserState *s, char *str)
{
char *ptr = str;
int c;
/* Skip leading blanks */
while((c = fgetc(fp)) != EOF && isspace(c))
{
;
}
*ptr++ = c;
/* Catch end marker */
if (c == '/') {
skip_line(fp, s);
*ptr++ = '\0';
return str;
}
while((c = fgetc(fp)) != EOF && !isspace(c))
{
*ptr++ = c;
/* Break and skip rest of line if '--' if encountered */
if (*(ptr-1) == '-' && ptr-str>1 && *(ptr-2) == '-'){
ptr = ptr - 2;
skip_line(fp, s);
break;
}
/* If end marker is encontered, push character back onto stream. */
if (c=='/') {
ungetc(c, fp);
ptr--;
break;
}
assert(ptr-str < bufsz);
}
*ptr='\0';
return str;
}
/* ------------------------------------------------------------------ */
static void skip_line(FILE *fp, struct ParserState *s)
{
static_cast<void>(s);
int c;
while((c = fgetc(fp))!=EOF && c != '\n') {
;
}
}
/* ------------------------------------------------------------------ */
// int version
static char *convert_string(int *value, char *str)
{
char *q;
*value = strtol(str, &q, 10);
return q;
}
/* ------------------------------------------------------------------ */
// double version
static char *convert_string(double *value, char *str)
{
char *q;
*value = strtod(str, &q);
return q;
}
/* ------------------------------------------------------------------ */
template <typename T>
void read_vector_from_file(const std::string& fn, std::vector<T>& v)
{
FILE *fp = fopen(fn.c_str(), "r");
struct ParserState s = { 0 };
readvector(fp, &s, v);
fclose(fp);
}
void read_vector_from_file(const std::string& fn, std::vector<int>& v)
{
read_vector_from_file<int>(fn, v);
}
void read_vector_from_file(const std::string& fn, std::vector<double>& v)
{
read_vector_from_file<double>(fn, v);
}

View File

@ -1,24 +0,0 @@
/*===========================================================================
//
// File: readvector.hpp
//
// Created: 2011-11-30 09:35:14+0100
//
// Author: Jostein R. Natvig <Jostein.R.Natvig@sintef.no>
//
//==========================================================================*/
/*
Copyright 2011 SINTEF ICT, Applied Mathematics.
*/
#ifndef READVECTOR_HPP_HEADER
#define READVECTOR_HPP_HEADER
#include <string>
void read_vector_from_file(const std::string&, std::vector<int>& v);
void read_vector_from_file(const std::string&, std::vector<double>& v);
#endif /* READVECTOR_HPP_HEADER */

View File

@ -1,100 +0,0 @@
/*===========================================================================
//
// File: sparsetable.c
//
// Created: Fri Jun 19 08:48:04 2009
//
// Author: Jostein R. Natvig <Jostein.R.Natvig@sintef.no>
//
// $Date$
//
// $Revision$
//
//==========================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "sparsetable.h"
void free_sparse_table (sparse_table_t *tab)
{
if(tab->ptr) free(tab->ptr);
if(tab->data) free(tab->data);
free(tab);
}
sparse_table_t *malloc_sparse_table(int m, int n, int datasz)
{
size_t alloc_sz;
sparse_table_t *tab = malloc(sizeof *tab);
tab->m = m;
tab->n = n;
tab->position = 0;
if (!(tab->ptr = malloc((m+1) * sizeof (*tab->ptr)))){
fprintf(stderr, "Could not allocate space for sparse ptr\n");
free_sparse_table(tab);
return NULL;
}
alloc_sz = datasz;
alloc_sz *= n;
if(!(tab->data = malloc(alloc_sz))){
fprintf(stderr, "Could not allocate space for sparse data(%d)\n", n);
free_sparse_table(tab);
return NULL;
}
return tab;
}
sparse_table_t *realloc_sparse_table(sparse_table_t *tab, int m, int n, int datasz)
{
void *p = realloc(tab->ptr, (m+1) * sizeof (*tab->ptr));
if (p){
tab->ptr = p;
}else{
fprintf(stderr, "Could not reallocate space for sparse ptr\n");
free_sparse_table(tab);
return NULL;
}
p = realloc(tab->data, n * datasz);
if(p){
tab->data = p;
}else{
fprintf(stderr, "Could not reallocate space for sparse data(%d)\n", n);
free_sparse_table(tab);
return NULL;
}
tab->m = m;
tab->n = n;
return tab;
}

View File

@ -1,53 +0,0 @@
/*===========================================================================
//
// File: sparsetable.h
//
// Created: Fri Jun 19 08:47:45 2009
//
// Author: Jostein R. Natvig <Jostein.R.Natvig@sintef.no>
//
// $Date$
//
// $Revision$
//
//===========================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 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 <http://www.gnu.org/licenses/>.
*/
#ifndef OPENRS_SPARSETABLE_HEADER
#define OPENRS_SPARSETABLE_HEADER
typedef struct{
int m; /* number of rows */
int *ptr; /* row pointer of size m+1 */
int position; /* first position in ptr that is not filled. */
int n; /* size of data */
void *data; /* sparse table data */
} sparse_table_t;
void free_sparse_table (sparse_table_t *tab);
sparse_table_t *malloc_sparse_table (int m, int n, int datasz);
sparse_table_t *realloc_sparse_table (sparse_table_t *tab, int m, int n, int datasz);
#endif /* OPENRS_SPARSETABLE_HEADER */

View File

@ -20,7 +20,7 @@
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
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,
@ -33,326 +33,350 @@
*/
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <limits.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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)
#define MIN(i,j) (((i) < (j)) ? (i) : (j))
#define MAX(i,j) (((i) > (j)) ? (i) : (j))
/*-----------------------------------------------------------------
Compare function passed to qsort
*/
Compare function passed to qsortx */
static int compare(const void *a, const void *b)
{
if (*(const double*)a < *(const double*) b) return -1;
else return 1;
const double a0 = *(const double*) a;
const double b0 = *(const double*) b;
/* { -1, a < b
* compare(a,b) = { 0, a = b
* { 1, a > b */
return (a0 > b0) - (a0 < b0);
}
/*-----------------------------------------------------------------
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[])
Creat sorted list of z-values in zcorn with actnum==1x */
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<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"); */
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;
qsort(list, ptr-list, sizeof(double), compare);
return ptr-list;
}
/*-----------------------------------------------------------------
Remove points less than <tolerance> apart in <list> of increasing
doubles.
*/
Remove points less than <tolerance> apart in <list> of increasing
doubles. */
static int uniquify(int n, double *list, double tolerance)
{
int i, pos = 0;
double val;
int i;
int pos;
double val;
assert (!(tolerance < 0.0));
assert (!(tolerance < 0.0));
if (n<1) return 0;
if (n<1) return 0;
pos = 0;
val = list[pos++];/* Keep first value */
val = list[pos++];/* Keep first value */
for (i=1; i<n; ++i){
if (val + tolerance < list [i]){
val = list[i];
list[pos++] = val;
for (i=1; i<n; ++i){
if (val + tolerance < list [i]){
val = list[i];
list[pos++] = val;
}
}
}
/*
Preserve outer z-boundary.
/*
Preserve outer z-boundary.
This operation is a no-op in the case
This operation is a no-op in the case
list[pos-2] + tolerance < list[n-1].
If, however, the second to last point is less than <tolerance>
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];
list[pos-2] + tolerance < list[n-1].
return pos;
If, however, the second to last point is less than <tolerance>
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)
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. */
/* 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. */
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;
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<n; ++i){
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;
/* 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) || ( zlist[k] + tolerance < z[i])){
fprintf(stderr, "Cannot associate zcorn values with given list\n");
fprintf(stderr, "of z-coordinates to given tolerance\n");
return 0;
}
*p++ = k;
}
/* 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) || ( zlist[k] + tolerance < z[i])){
fprintf(stderr, "Cannot associate zcorn values with given list\n");
fprintf(stderr, "of z-coordinates to given tolerance\n");
return 0;
}
*p++ = k;
}
*p++ = INT_MAX;/* Padding to ease processing of faults */
*p++ = INT_MAX;/* Padding to ease processing of faults */
return 1;
return 1;
}
/*-----------------------------------------------------------------
Given a vector <field> with k index running faster than i running
faster than j, and Cartesian dimensions <dims>, 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[])
/* ---------------------------------------------------------------------- */
static void
vector_positions(const int dims[3] ,
const int i ,
const int j ,
size_t start[4])
/* ---------------------------------------------------------------------- */
{
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);
size_t im, ip, jm, jp;
im = MAX(1, i ) - 1;
jm = MAX(1, j ) - 1;
ip = MIN(dims[0], i+1) - 1;
jp = MIN(dims[1], j+1) - 1;
start[ 0 ] = dims[2] * (im + dims[0]*jm);
start[ 1 ] = dims[2] * (im + dims[0]*jp);
start[ 2 ] = dims[2] * (ip + dims[0]*jm);
start[ 3 ] = dims[2] * (ip + dims[0]*jp);
}
/*-----------------------------------------------------------------
Given a vector <field> with k index running faster than i running
faster than j, and Cartesian dimensions <dims>, 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[])
Given a vector <field> with k index running faster than i running
faster than j, and Cartesian dimensions <dims>, 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);
size_t p, start[4];
vector_positions(dims, i, j, start);
for (p = 0; p < 4; p++) {
v[p] = field + start[p];
}
}
/*-----------------------------------------------------------------
Given a vector <field> with k index running faster than i running
faster than j, and Cartesian dimensions <dims>, 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[])
{
size_t p, start[4];
vector_positions(dims, i, j, start);
for (p = 0; p < 4; p++) {
v[p] = field + start[p];
}
}
/*-----------------------------------------------------------------
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;
}
double a;
if (fabs(coord[5] - coord[2]) > 0) {
a = (pt[2] - coord[2]) / (coord[5] - coord[2]);
} else {
a = 0;
}
#if 0
pt[0] = coord[0] + a*(coord[3]-coord[0]);
pt[1] = coord[1] + a*(coord[4]-coord[1]);
pt[0] = coord[0] + a*(coord[3]-coord[0]);
pt[1] = coord[1] + a*(coord[4]-coord[1]);
#else
pt[0] = (1.0 - a)*coord[0] + a*coord[3];
pt[1] = (1.0 - a)*coord[1] + a*coord[4];
pt[0] = (1.0 - a)*coord[0] + a*coord[3];
pt[1] = (1.0 - a)*coord[1] + a*coord[4];
#endif
}
/*-----------------------------------------------------------------
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)
*/
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)
/* 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));
const int nx = out->dimensions[0];
const int ny = out->dimensions[1];
const int nz = out->dimensions[2];
const int nc = g->dims[0]*g->dims[1]*g->dims[2];
/* zlist may need extra space temporarily due to simple boundary
* treatement */
int npillarpoints = 8*(nx+1)*(ny+1)*nz;
int npillars = (nx+1)*(ny+1);
double *zlist = malloc(npillarpoints*sizeof *zlist);
int *zptr = malloc((npillars+1)*sizeof *zptr);
int nc = g->dims[0]*g->dims[1]*g->dims[2];
double *zlist = ztab->data; /* casting void* to double* */
int *zptr = ztab->ptr;
int i,j,k;
int i,j,k;
int d1[3];
int len = 0;
double *zout = zlist;
int pos = 0;
double *pt;
const double *z[4];
const int *a[4];
int *p;
int pix, cix;
int zix;
int d1[3];
int len = 0;
double *zout = zlist;
int pos = 0;
const double *coord = g->coord;
const double *coord = g->coord;
double *pt;
int *p;
d1[0] = 2*g->dims[0];
d1[1] = 2*g->dims[1];
d1[2] = 2*g->dims[2];
d1[0] = 2*g->dims[0]; d1[1] = 2*g->dims[1]; d1[2] = 2*g->dims[2];
out->node_coordinates = malloc (3*8*nc*sizeof(*out->node_coordinates));
out->node_coordinates = malloc (3*8*nc*sizeof(*out->node_coordinates));
zptr[pos++] = zout - zlist;
zptr[pos++] = zout - zlist;
pt = out->node_coordinates;
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){
/* 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);
/* 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);
len = createSortedList( zout, d1[2], 4, z, a);
len = uniquify (len, zout, tolerance);
/* Assign unique points */
for (k=0; k<len; ++k){
pt[2] = zout[k];
interpolate_pillar(coord, pt);
pt += 3;
}
/* Assign unique points */
for (k=0; k<len; ++k){
pt[2] = zout[k];
interpolate_pillar(coord, pt);
pt += 3;
}
/* Increment pointer to sparse table of unique zcorn values */
zout = zout + len;
zptr[pos++] = zout - zlist;
/* Increment pointer to sparse table of unique zcorn
* values */
zout = zout + len;
zptr[pos++] = zout - zlist;
coord += 6;
coord += 6;
}
}
}
out->number_of_nodes_on_pillars = zptr[pos-1];
out->number_of_nodes = zptr[pos-1];
out->number_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 */
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]);
/* Loop over all vertical sets of zcorn values, assign point
* numbers */
p = plist;
for (j=0; j < 2*g->dims[1]; ++j){
for (i=0; i < 2*g->dims[0]; ++i){
/* 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;
/* pillar index */
pix = (i+1)/2 + (g->dims[0]+1)*((j+1)/2);
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;
}
/* cell column position */
cix = g->dims[2]*((i/2) + (j/2)*g->dims[0]);
p += 2 + 2*g->dims[2];
/* zcorn column position */
zix = 2*g->dims[2]*(i+2*g->dims[0]*j);
if (!assignPointNumbers(zptr[pix], zptr[pix+1], zlist,
2*g->dims[2],
g->zcorn + zix, g->actnum + cix,
p, tolerance)){
fprintf(stderr, "Something went wrong in assignPointNumbers");
return 0;
}
p += 2 + 2*g->dims[2];
}
}
}
free(zptr);
free(zlist);
free_sparse_table(ztab);
return 1;
return 1;
}
/* Local Variables: */
/* c-basic-offset:4 */
/* End: */

View File

@ -13,34 +13,34 @@
//==========================================================================*/
/*
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
Copyright 2009, 2010 Statoil ASA.
This file is part of The Open Reservoir Simulator Project (OpenRS).
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 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.
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 <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENRS_UNIQUEPOINTS_HEADER
#define OPENRS_UNIQUEPOINTS_HEADER
#ifndef OPM_UNIQUEPOINTS_HEADER
#define OPM_UNIQUEPOINTS_HEADER
int finduniquepoints(const struct grdecl *g, /* input */
int *p, /* for each z0 in zcorn, z0 = z[p0] */
double t, /* tolerance*/
struct processed_grid *out);
int *p, /* for each z0 in zcorn, z0 = z[p0] */
double t, /* tolerance*/
struct processed_grid *out);
#endif /* OPENRS_UNIQUEPOINTS_HEADER */
#endif /* OPM_UNIQUEPOINTS_HEADER */
/* Local Variables: */
/* c-basic-offset:4 */

View File

@ -37,13 +37,13 @@ extern "C" {
*/
struct CSRMatrix
{
size_t m; /** Number of rows */
size_t nnz; /** Number of structurally non-zero elements */
size_t m; /**< Number of rows */
size_t nnz; /**< Number of structurally non-zero elements */
int *ia; /** Row pointers */
int *ja; /** Column indices */
int *ia; /**< Row pointers */
int *ja; /**< Column indices */
double *sa; /** Matrix elements */
double *sa; /**< Matrix elements */
};

View File

@ -19,7 +19,6 @@ test_column_extract \
test_lapack \
test_read_vag \
test_readpolymer \
test_readvector \
test_sf2p \
test_writeVtkData \
unit_test
@ -49,8 +48,6 @@ test_lapack_LDADD = $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS) $(FLIBS)
test_readpolymer_SOURCES = test_readpolymer.cpp
test_read_vag_SOURCES = test_read_vag.cpp
test_readvector_SOURCES = test_readvector.cpp
test_sf2p_SOURCES = test_sf2p.cpp
test_writeVtkData_SOURCES = test_writeVtkData.cpp

View File

@ -1,67 +0,0 @@
#include <iostream>
#include <string>
#include <vector>
#include <opm/core/grid.h>
#include <opm/core/grid/cpgpreprocess/preprocess.h>
#include <opm/core/grid/cornerpoint_grid.h>
#include <opm/core/grid/cpgpreprocess/readvector.hpp>
static struct UnstructuredGrid*
read_grid(const std::string& dir)
{
std::string fn;
fn = dir + '/' + "zcorn.txt";
std::vector<double> zcorn;
read_vector_from_file(fn, zcorn);
fn = dir + '/' + "coord.txt";
::std::vector<double> coord;
read_vector_from_file(fn, coord);
fn = dir + '/' + "actnum.txt";
std::vector<int> actnum;
read_vector_from_file(fn, actnum);
fn = dir + '/' + "dimens.txt";
::std::vector<int> dimens;
read_vector_from_file(fn, dimens);
struct grdecl grdecl;
grdecl.zcorn = &zcorn[0];
grdecl.coord = &coord[0];
grdecl.actnum = &actnum[0];
grdecl.dims[0] = dimens[0];
grdecl.dims[1] = dimens[1];
grdecl.dims[2] = dimens[2];
struct UnstructuredGrid *g = create_grid_cornerpoint(&grdecl, 0.0);
double vol = 0.0;
for (int c = 0; c < g->number_of_cells; c++) {
vol += g->cell_volumes[c];
}
std::cout << "Sum volumes = " << vol << '\n';
for (int c = 0, i = 0; c < g->number_of_cells; c++) {
for (; i < g->cell_facepos[c + 1]; i++) {
std::cout << "(c,i) = (" << c << "," << g->cell_facetag[i] << ")\n";
}
}
return g;
}
int main()
{
struct UnstructuredGrid *g;
g = read_grid(std::string("example"));
destroy_grid(g);
return 0;
}