* routines to read string records, and interpret as welldate. (unfinished)
 * Routine to read chunks of data from file, with '--' as comment mark,
   '3*3.1415' for repeated values and '/' for termination of read.
This commit is contained in:
Jostein R. Natvig 2011-11-29 16:24:53 +01:00
parent a401f72ca7
commit a2aaf9c590
2 changed files with 896 additions and 0 deletions

614
common/io/readtokens.cpp Normal file
View File

@ -0,0 +1,614 @@
/* Copyright 2010 (c) Jostein R. Natvig <Wbfgrva.angivt@tznvy.pbz> */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cassert>
#include <vector>
#include <cmath>
/* ------------------------------------------------------------------ */
/* Interface for parsing records of '/'-separated strings */
/* ------------------------------------------------------------------ */
#define BUFSIZE 1024
struct State {
int error;
int lineno;
};
static int parse_next_token (FILE *fp, struct State *s, char **t, int *c);
static char *get_token_string (FILE *fp, struct State *s, char *buf);
static void split_token_string (char *str, char *rstr, char *vstr);
static int get_default_count (char *rstr, struct State *s);
static void skip_line (FILE *fp, struct State *s);
static char *string_to_int (int *value, char *str);
static int
readtokens(FILE *fp, char **tokens, int numtokens, struct State *s)
{
char *token;
int defaultcount;
int i;
int pos;
int finish;
defaultcount = 0;
s->error = 0;
pos = 0;
while ((finish=parse_next_token(fp, s, &token, &defaultcount)) && pos < numtokens)
{
if (defaultcount == 0)
{
tokens[pos++] = token;
}
else
{
if (defaultcount > numtokens - pos)
{
fprintf(stderr, "Too many default values '%s' on line %d. ", token, s->lineno);
break;
}
for (i=0; i<defaultcount; ++i)
{
tokens[pos++] = NULL; /* strdup("DEFAULT"); */
}
free(token);
}
}
for (; pos < numtokens; ++pos)
{
tokens[pos] = NULL; /* strdup("DEFAULT"); */
}
if (finish != 0)
{
fprintf(stderr, "Too many tokens?\n");
}
return finish == 0;
}
/* ------------------------------------------------------------------ */
static int
parse_next_token(FILE *fp, struct State *s, char **tok,
int *count)
{
char str[BUFSIZE];
char rstr[BUFSIZE];
char vstr[BUFSIZE];
int ok = 1;
str[0]='\0';
while (strlen(str)==0)
{
get_token_string(fp, s, str);
}
if (str[0] == '/')
{
ok = 0;
}
else
{
*tok = strdup(str);
*count = 0;
split_token_string(str, rstr, vstr);
if ((strlen(rstr)>0) && (strlen(vstr)==0))
{
*count = get_default_count(rstr, s);
if (s->error)
{
fprintf(stderr, "Warning: string token ends with a '*'\n");
/* attempt to proceed */
s->error = 0;
*count = 0;
}
}
}
return ok;
}
/* ------------------------------------------------------------------ */
static void
split_token_string(char *str, char *rstr, char *vstr)
{
/* str:'rrrr*vvvv' -> rstr:'rrrr' vstr:'vvvv' */
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++))
{
;
}
*vstr='\0';
}
/* ------------------------------------------------------------------ */
static int
get_default_count(char *rstr, struct State *s)
{
int r;
char *ptr;
if (strlen(rstr)>0)
{
ptr=string_to_int(&r, rstr);
/* no conversion, extra characters, ... */
if ((ptr==rstr) || (strlen(ptr)>0) || (r<1))
{
s->error = 1;
}
}
else
{
r = 0;
}
return r;
}
/* ------------------------------------------------------------------ */
/* hint: always read '/' as a separate token */
static char *
get_token_string(FILE *fp, struct State *s, char *str)
{
char *ptr = str;
int c;
int quote=0;
/* skip leading blanks */
while((c = fgetc(fp)) != EOF && isspace(c)) {if (c=='\n') s->lineno++;}
/* catch end marker */
if (c == '/') {
skip_line(fp, s);
*ptr++ = c;
*ptr++ = '\0';
return str;
}
/* otherwise, read the wole token in the next block*/
ungetc(c, fp);
while((c = fgetc(fp)) != EOF && (quote || !isspace(c)))
{
*ptr++ = c;
if (c=='\''){
quote = quote ? 0 : 1;
}
/* 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 < BUFSIZE);
}
if (c=='\n')
{
s->lineno++;
}
*ptr='\0';
return str;
}
/* ------------------------------------------------------------------ */
static void
skip_line(FILE *fp, struct State *s)
{
int c;
while((c = fgetc(fp))!=EOF && c != '\n') {
;
}
++s->lineno;
}
/* ------------------------------------------------------------------ */
static char *
string_to_int(int *value, char *str)
{
char *q;
*value = strtol(str, &q, 10);
return q;
}
/* ------------------------------------------------------------------ */
static int
all_defaults(char **t, int n)
{
int i;
for (i=0; i<n; ++i)
{
if (t[i] != NULL)
{
return 0;
}
}
return 1;
}
/* ------------------------------------------------------------------ */
// Convert this to std::vector<std::string>
struct Record {
char **fields;
size_t numfields;
Record(size_t n)
{
numfields = n;
fields = new char*[numfields];
for(size_t i=0; i<numfields; ++i)
{
fields[i] = NULL;
}
}
~Record() {
for (size_t i=0; i<numfields; ++i)
{
free(fields[i]);
fields[i] = NULL;
}
delete fields;
}
Record(const Record& R)
{
numfields = R.numfields;
fields = new char*[numfields];
for(size_t i=0; i<numfields; ++i)
{
if (R.fields[i] != NULL)
{
fields[i] = strdup(R.fields[i]);
}
else
{
fields[i] = NULL;
}
}
}
void display(FILE *stream)
{
fprintf(stream, "[");
for(size_t i=0; i<numfields; ++i)
{
fprintf(stream, "%s, ", fields[i]);
}
fprintf(stream, "\b\b]\n");
}
};
/* ------------------------------------------------------------------ */
void read_records(const char *fn, size_t record_width, std::vector<Record> &v)
{
Record r(record_width);
struct State s = {0, 1};
FILE *fp = fopen(fn, "r");
int ok;
/* read until am empty record is found (which is read as 'only
* default values') */
while ( (1 == (ok=readtokens (fp, r.fields, r.numfields, &s))) &&
(0 == all_defaults (r.fields, r.numfields)) )
{
v.push_back(r);
}
fclose(fp);
}
void
display_records(std::vector<Record> v, FILE *stream)
{
for (size_t i=0; i<v.size(); ++i)
{
v[i].display(stream);
}
}
/* ------------------------------------------------------------------ */
void
read_compdat(const char *fn, std::vector<Record> &v)
{
size_t sz = 14;
read_records(fn, sz, v);
}
void
read_welspecs(const char *fn, std::vector<Record> &v)
{
size_t sz = 16;
read_records(fn, sz, v);
}
void
read_wconinje(const char *fn, std::vector<Record> &v)
{
size_t sz = 14;
read_records(fn, sz, v);
}
static char *trimspace (char *str)
{
char *ibuf, *obuf;
if (str) {
for (ibuf = obuf = str; *ibuf; ) {
while (*ibuf && (isspace (*ibuf))) {
ibuf++;
}
if (*ibuf && (obuf != str)) {
*(obuf++) = ' ';
}
while (*ibuf && (!isspace (*ibuf))) {
*(obuf++) = *(ibuf++);
}
}
*obuf = '\0';
}
return (str);
}
static char* remove_quotes(char *str)
{
int len = strlen(str);
if ((str[0]=='\'') && (str[strlen(str)-1]=='\''))
{
str[0] = ' ';
str[len-1] = '\0';
trimspace(str);
}
return str;
}
static void get_wellnames(std::vector<Record> welspecs, Record &wnames)
{
int n = welspecs.size();
for (int i=0; i<n; ++i)
{
assert(welspecs[i].fields[0] != NULL);
wnames.fields[i] = strdup(remove_quotes(welspecs[i].fields[0]));
}
}
static int get_well_number(Record wnames, char *name)
{
size_t i;
for(i=0; i<wnames.numfields; ++i)
{
if (strcmp(wnames.fields[i], remove_quotes(name))!=0)
{
break;
}
}
return i;
}
static double effective_pressure_radius(const Record &completion,
double dx, double dy, double dz,
double kx, double ky, double kz)
{
double k1,k2,dx1,dx2;
double r0;
// assert( completion != NULL);
if (completion.fields[13] != NULL)
{
sscanf(completion.fields[13], "%lf", &r0);
}
else
{
/* if a field is NULL, use the default value */
if ((completion.fields[12] == NULL) ||
(strcmp(completion.fields[12], "Z")==0))
{
dx1=dx;dx2=dy;k1=kx;k2=ky;
}
else if (strcmp(completion.fields[12], "X")==0)
{
dx1=dy;dx2=dz;k1=ky;k2=kz;
}
else if(strcmp(completion.fields[12], "Y")==0)
{
dx1=dx;dx2=dz;k1=kx;k2=kz;
}
else
{
fprintf(stderr, "ERROR: unsupported completion direction (item 13)\n");
exit(EXIT_FAILURE);
}
/* Effective pressure radius used in Peaceman formula for
* rectangular grid block and permeability aligned with axes
* of grid cell */
r0 = 0.28;
r0 *= sqrt(sqrt(k2/k1)*dx1*dx1 + sqrt(k1/k2)*dx2*dx2);
r0 /= sqrt(sqrt(k1/k2)) + sqrt(sqrt(k2/k1));
}
return r0;
}
static double compute_transmissibility(const Record &completion)
{
double r;
double r0;
double kh;
double skin = 0;
double twopi = 6.283185307179586;
double trans = -1.0;
if (completion.fields[7] != NULL )
{
sscanf(completion.fields[7], "%lf", &trans);
}
if (completion.fields[7] == NULL || trans == 0)
{
if(completion.fields[8] !=NULL)
{
sscanf(completion.fields[8], "%lf", &r);
}
else
{
r = 0.3048;
}
if(completion.fields[9] !=NULL)
{
sscanf(completion.fields[9], "%lf", &kh);
}
else
{
kh = 1;
}
if(completion.fields[10]!=NULL)
{
sscanf(completion.fields[10], "%lf", &skin);
}
else
{
skin = 0;
}
r0 = effective_pressure_radius(completion, 100,100,1,10,10,1);
trans = twopi*kh/(logf(r0/r)+skin);
}
return trans;
}
static void get_well_completions(const Record &completion,
std::vector<Record> welspecs,
int dims[3],
std::vector<std::vector<int> > &completions)
{
int k;
int i,j,k1,k2;
int pcell;
Record wnames(welspecs.size());
get_wellnames(welspecs, wnames);
int wnum = get_well_number(wnames, completion.fields[0]);
assert(completion.fields[1]!=NULL);
assert(completion.fields[2]!=NULL);
assert(completion.fields[3]!=NULL);
assert(completion.fields[4]!=NULL);
sscanf(completion.fields[1], "%d", &i);
sscanf(completion.fields[2], "%d", &j);
sscanf(completion.fields[3], "%d", &k1);
sscanf(completion.fields[4], "%d", &k2);
compute_transmissibility(completion);
fprintf(stderr, "%d %d %d %d: ", i,j,k1,k2);
i = i==0 ? 0 : i-1;
j = j==0 ? 0 : j-1;
k1 = k1==0 ? 0 : k1-1;
k2 = k2==0 ? 0 : k2-1;
for (k = k1; k<=k2; ++k)
{
pcell = i + dims[0]*(j + dims[1]*k);
completions[wnum].push_back(pcell);
}
fprintf(stderr, "\n");
}
int main()
{
std::vector<Record> compdat;
read_compdat("compdat.txt", compdat);
display_records(compdat, stderr);
fprintf(stderr, "\n\n");
std::vector<Record> welspecs;
read_welspecs("welspecs.txt", welspecs);
display_records(welspecs, stderr);
fprintf(stderr, "\n\n");
std::vector<Record> wconinje;
read_wconinje("wconinje.txt", wconinje);
display_records(wconinje, stderr);
Record wnames(welspecs.size());
get_wellnames(welspecs, wnames);
wnames.display(stderr);
int dims[3] = {10,10,5};
std::vector<std::vector<int> > completions(2);
for (size_t i=0; i<compdat.size(); ++i)
{
get_well_completions(compdat[i], welspecs, dims, completions);
}
fprintf(stderr, "here:\n");
for (size_t i=0; i<completions.size(); ++i)
{
fprintf(stderr, "%d: ", (int)i);
for (size_t j=0; j<completions[i].size(); ++j)
{
fprintf(stderr, "%d ", completions[i][j]);
}
fprintf(stderr, "\n");
}
return 0;
}

282
common/io/readvector.cpp Normal file
View File

@ -0,0 +1,282 @@
/* Copyright 2010 (c) Jostein R. Natvig <jostein.natvig@gmail.com> */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <vector>
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;
int ret;
int ok;
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], *ptr;
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++)
{
;
}
*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)
{
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 char *fn, std::vector<T>& v)
{
FILE *fp = fopen(fn, "r");
struct ParserState s = {1, 0};
readvector(fp, &s, v);
fclose(fp);
}
#if 1
int main()
{
std::vector<double> v;
read_vector_from_file("example/zcorn.txt", zcorn);
std::vector<int> actnum;
read_vector_from_file("example/actnum.txt", actnum);
for (int i=0; i<v.size(); ++i)
{
fprintf(stderr, "%f\n", zcorn[i]);
}
for (int i=0; i<actnum.size(); ++i)
{
fprintf(stderr, "%d\n", actnum[i]);
}
return 0;
}
#endif