KTH framework for Nek5000 toolboxes; testing version  0.0.1
crs_amg_io.h
Go to the documentation of this file.
1 /*==========================================================================
2 
3  File I/O for AMG
4  small wrappers to read/write files consisting of doubles
5 
6  ==========================================================================*/
7 
8 #ifndef MPI
9 #undef USEMPIIO
10 #endif
11 
12 #ifdef NOMPIIO
13 #undef USEMPIIO
14 #endif
15 
16 /* reverse the byte order of the given double
17  portable up to 129-byte doubles, standards conforming */
18 #define N sizeof(double)
19 static double byteswap(double x)
20 {
21  char t, buf[N];
22  memcpy(buf,&x,N);
23 #define SWAP1(i) if(N>2*(i)+1) t=buf[i],buf[i]=buf[N-1-(i)],buf[N-1-(i)]=t
24 #define SWAP2(i) SWAP1(i); SWAP1((i)+0x01); SWAP1((i)+0x02); SWAP1((i)+0x03)
25 #define SWAP3(i) SWAP2(i); SWAP2((i)+0x04); SWAP2((i)+0x08); SWAP2((i)+0x0c)
26 #define SWAP4(i) SWAP3(i); SWAP3((i)+0x10); SWAP3((i)+0x20); SWAP3((i)+0x30)
27  SWAP4(0);
28 #undef SWAP1
29 #undef SWAP2
30 #undef SWAP3
31 #undef SWAP4
32  memcpy(&x,buf,N);
33  return x;
34 }
35 #undef N
36 
37 struct file {
38  FILE *fptr;
39  int swap;
40 };
41 
42 #ifdef USEMPIIO
43 struct sfile {
44  MPI_File fh;
45  int swap;
46 };
47 #endif
48 
49 static int rfread(void *ptr, size_t n, FILE *const fptr)
50 {
51  size_t na; char *p=ptr;
52  while(n && (na=fread (p,1,n,fptr))) n-=na, p+=na;
53  return n!=0;
54 }
55 
56 static int rfwrite(FILE *const fptr, const void *ptr, size_t n)
57 {
58  size_t na; const char *p=ptr;
59  while(n && (na=fwrite(p,1,n,fptr))) n-=na, p+=na;
60  return n!=0;
61 }
62 
63 
64 static struct file dopen(const char *filename, const char mode,int *code)
65 {
66  const double magic = 3.14159;
67  double t;
68  struct file f;
69  f.fptr = fopen(filename,mode=='r'?"r":"w");
70  f.swap = 0;
71  if(f.fptr==0) {
72  diagnostic("ERROR ",__FILE__,__LINE__,
73  "AMG: could not open %s for %s",
74  filename,mode=='r'?"reading":"writing");
75  *code=1;
76  return f;
77  }
78  if(mode=='r') {
79  if(rfread(&t,sizeof(double), f.fptr)){
80  diagnostic("ERROR ",__FILE__,__LINE__,
81  "AMG: could not read from %s",filename);
82  *code=1;
83  return f;
84  }
85  if(fabs(t-magic)>0.000001) {
86  t=byteswap(t);
87  if(fabs(t-magic)>0.000001) {
88  diagnostic("ERROR ",__FILE__,__LINE__,
89  "AMG: magic number for endian test not found in %s",
90  filename);
91  *code=1;
92  return f;
93  }
94  f.swap = 1;
95  }
96  } else {
97  if(rfwrite(f.fptr, &magic,sizeof(double))){
98  diagnostic("ERROR ",__FILE__,__LINE__,
99  "AMG: could not write to %s",filename);
100  *code=1;
101  return f;
102  }
103  }
104  return f;
105 }
106 
107 static void dread(double *p, size_t n, const struct file f,int *code)
108 {
109  if(rfread(p,n*sizeof(double),f.fptr)) {
110  diagnostic("ERROR ",__FILE__,__LINE__,
111  "AMG: failed reading %u doubles from disk",(unsigned)n);
112  *code=1;
113  return;
114  }
115  if(f.swap) while(n) *p=byteswap(*p), ++p, --n;
116 }
117 
118 static void dwrite(const struct file f, const double *p, size_t n,int *code)
119 {
120  if(rfwrite(f.fptr, p,n*sizeof(double))) {
121  diagnostic("ERROR ",__FILE__,__LINE__,
122  "AMG: failed writing %u doubles to disk",(unsigned)n);
123  *code=1;
124  }
125 }
126 
127 static void dclose(const struct file f)
128 {
129  fclose(f.fptr);
130 }
131 
132 #ifdef USEMPIIO
133 static void dread_mpi(double *buf, uint n, const struct sfile f,int *code)
134 {
135  MPI_File fh=f.fh;
136  MPI_Status status;
137  int count=n;
138 
139  if(MPI_File_read_all(fh,buf,count,MPI_DOUBLE,&status)) {
140  diagnostic("ERROR ",__FILE__,__LINE__,
141  "AMG: failed reading %u doubles from disk",(unsigned)count);
142  *code=1;
143  return;
144  }
145  if(f.swap) while(count) *buf=byteswap(*buf), ++buf, --count;
146 }
147 
148 static struct sfile dopen_mpi(const char *filename, const char mode,
149  const struct comm *c,int *code)
150 {
151  const double magic = 3.14159;
152  double t;
153  struct sfile f={0,0};
154  MPI_File fh;
155 
156  int amode = mode=='r' ? MPI_MODE_RDONLY : MPI_MODE_CREATE|MPI_MODE_WRONLY;
157  MPI_File_open(c->c,filename,amode,MPI_INFO_NULL,&fh);
158 
159  f.fh = fh;
160 
161  if(f.fh==0) {
162  diagnostic("ERROR ",__FILE__,__LINE__,
163  "AMG: could not open %s for %s",
164  filename,mode=='r'?"reading":"writing");
165  *code=1;
166  return f;
167  }
168 
169  if(mode=='r') {
170  dread_mpi(&t, 1, f, code);
171  if(*code!=0) {
172  diagnostic("ERROR ",__FILE__,__LINE__,
173  "AMG: could not read from %s",filename);
174  return f;
175  }
176  if(fabs(t-magic)>0.000001) {
177  t=byteswap(t);
178  if(fabs(t-magic)>0.000001) {
179  diagnostic("ERROR ",__FILE__,__LINE__,
180  "AMG: magic number for endian test not found in %s",
181  filename);
182  *code=1;
183  return f;
184  }
185  f.swap = 1;
186  }
187  } else {
188  /* dwrite_mpi(&t, 1, f.fh, code); */
189  if(*code!=0) {
190  diagnostic("ERROR ",__FILE__,__LINE__,
191  "AMG: could not write to %s",filename);
192  return f;
193  }
194  }
195  return f;
196 }
197 
198 static void dview_mpi(ulong n, const struct sfile f, int *code)
199 {
200  MPI_File fh=f.fh;
201  MPI_Info info;
202  MPI_Offset disp=n*sizeof(double);
203 
204  if(MPI_File_set_view(fh,disp,MPI_DOUBLE,MPI_DOUBLE,"native",MPI_INFO_NULL)) {
205  diagnostic("ERROR ",__FILE__,__LINE__,
206  "AMG: failed chaning view to %u doubles",(unsigned)n);
207  *code=1;
208  return;
209  }
210 }
211 
212 static void dclose_mpi(const struct sfile f)
213 {
214  MPI_File fh=f.fh;
215  MPI_File_close(&fh);
216 }
217 #endif
218 
#define N
Definition: crs_amg_io.h:18
#define SWAP4(i)
subroutine swap(b, ind, n, temp)
Definition: navier7.f:504
int swap
Definition: crs_amg_io.h:39
FILE * fptr
Definition: crs_amg_io.h:38