Convert ADCIRC ascii grid files and accompanying simulation output into F5. The levee information contained in the grid file is put into a specific triangular mesh for visualization purposes.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <hdf5.h>
#include <F5/F5X.h>
#include <F5/F5F.h>
#include <F5/F5B.h>
#include <F5/F5R.h>
#include <F5/F5coordinates.h>
#include <F5/F5surface.h>
#include <F5/F5defs.h>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
void AppendSurfaceData( hid_t fileID, const string&gridname,
const vector<F5_vec3_point_t>&Coords,
const vector<F5_triangle_t>&Triangles,
int time_steps_to_load)
{
char buf[2048];
double time = 0;
FILE*kat63 = fopen("fort.63", "rt"),
*kat64 = fopen("fort.64", "rt"),
*kat74 = fopen("fort.74", "rt");
FILE*elev = 0;
#ifdef R_OK
if (access("fort.63.gz", R_OK) == 0)
{
elev = popen("zcat fort.63.gz", "r");
if (elev==0)
perror("Error in reading fort.63");
else
fputs("Fine, could open fort63 file.\n", stderr);
}
#endif
if (!(kat63 || kat74 || kat64|| elev))
{
fputs("No additional field information available.\n", stderr);
return;
}
unsigned int Timesteps = 0, Nodes = 0;
if (kat63)
{
fgets(buf, sizeof(buf), kat63);
fprintf(stderr, buf );
fgets(buf, sizeof(buf), kat63);
sscanf(buf, "%d %d", &Timesteps, &Nodes);
fgets(buf, sizeof(buf), kat63);
fprintf(stderr, buf );
}
if (kat64)
{
fgets(buf, sizeof(buf), kat64);
fprintf(stderr, buf );
fgets(buf, sizeof(buf), kat64);
sscanf(buf, "%d %d", &Timesteps, &Nodes);
fgets(buf, sizeof(buf), kat64);
fprintf(stderr, buf );
}
if (kat74)
{
fgets(buf, sizeof(buf), kat74);
fprintf(stderr, buf );
fgets(buf, sizeof(buf), kat74);
sscanf(buf, "%d %d", &Timesteps, &Nodes);
fgets(buf, sizeof(buf), kat74);
fprintf(stderr, buf );
}
if (elev)
{
fgets(buf, sizeof(buf), elev);
fprintf(stderr, buf );
fgets(buf, sizeof(buf), elev);
sscanf(buf, " %d %d", &Timesteps, &Nodes);
fgets(buf, sizeof(buf), elev);
fprintf(stderr, buf );
}
fprintf(stderr,"ADCIRC Surface Data: %d time steps, %d vertices\n", Timesteps, Nodes);
if (Nodes != Coords.size() )
{
fputs("Vertices and Coordinates mismatch.", stderr);
return;
}
if(time_steps_to_load > 0 && (unsigned)time_steps_to_load < Timesteps )
Timesteps = time_steps_to_load;
vector<float> Elevation;
vector<F5_vec3f_t> Wind;
vector<F5_vec3f_t> DepthAverageVelocity;
if (kat63 || elev) Elevation.resize( Coords.size() );
if (kat74) Wind.resize( Coords.size() );
if (kat64) DepthAverageVelocity.resize( Coords.size() );
for(unsigned tstep=0; tstep < Timesteps; tstep++)
{
double Time = time + 30*tstep;
fprintf(stderr, "Timestep %d -> t=%lg\n", tstep, Time);
if (!FirstSurface)
{
gridname.c_str(),
&Coords[0], Coords.size(),
&Triangles[0], Triangles.size() );
myGrid = FirstSurface;
}
else
gridname.c_str(),
0, Coords.size(),
0, Triangles.size()
);
if (kat63)
{
for(unsigned int i=0; i<Coords.size(); i++)
{
int num;
fgets(buf, sizeof(buf), kat63);
if ( sscanf(buf, "%d %g\n", &num, &Elevation[i] ) != 2 )
{
fprintf(stderr, "Error can't find scalar value for vertex %d\n", i );
return;
}
if ( Elevation[i] < -3333 ) Elevation[i] = 0.0;
}
fgets(buf, sizeof(buf), kat63);
F5Fwrite_1D(myGrid, "height", Coords.size(),
H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT,
&Elevation[0], F5P_DEFAULT);
}
if (elev)
{
for(unsigned i=0; i<Coords.size(); i++)
{unsigned
int num;
fgets(buf, sizeof(buf), elev);
if ( sscanf(buf, "%d %g\n", &num, &Elevation[i] ) != 2 )
{
fprintf(stderr, "Error can't find scalar value for vertex %d\n", i );
return;
}
if (num != i+1)
fprintf(stderr, "Index mismatch: %s\n", buf);
}
fgets(buf, sizeof(buf), elev);
F5Fwrite_1D(myGrid, "elevation", Coords.size(),
H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT,
&Elevation[0], F5P_DEFAULT);
}
if (kat74)
{
for(unsigned int i=0; i<Coords.size(); i++)
{
int num;
fgets(buf, sizeof(buf), kat74);
if ( sscanf(buf, "%d %g %g\n", &num, &Wind[i].x, &Wind[i].y ) != 3 )
{
fprintf(stderr, "Error can't find vector value for vertex %d\n", i );
return;
}
Wind[i].z = 0.0;
}
fgets(buf, sizeof(buf), kat74);
F5Fwrite_1D(myGrid, "wind", Coords.size(),
F5T_VEC3_FLOAT, F5T_VEC3_FLOAT,
&Wind[0], F5P_DEFAULT);
}
if (kat64)
{
for(unsigned int i=0; i<Coords.size(); i++)
{
int num;
fgets(buf, sizeof(buf), kat64);
if ( sscanf(buf, "%d %g %g\n", &num,
&DepthAverageVelocity[i].x,
&DepthAverageVelocity[i].y ) != 3 )
{
fprintf(stderr, "Error can't find vector value for vertex %d\n", i );
return;
}
DepthAverageVelocity[i].z = 0.0;
}
fgets(buf, sizeof(buf), kat64);
F5Fwrite_1D(myGrid, "depth average velocity", Coords.size(),
F5T_VEC3_FLOAT, F5T_VEC3_FLOAT,
&DepthAverageVelocity[0], F5P_DEFAULT);
}
if (myGrid != FirstSurface)
}
if (kat63) fclose(kat63);
if (kat74) fclose(kat74);
if (kat64) fclose(kat64);
if (elev) pclose(elev);
}
void flip(
const vector<F5_vec3_point_t>&Coords,
F5_triangle_t &T)
{
BA = { B.
x - A.x, B.y - A.
y, B.z - A.
z },
CA = { C.x - A.x, C.y - A.y, C.z - A.z };
double zDir = BA.x*CA.y - CA.x*BA.y;
if (zDir < 0)
{
int tmp = T.j;
T.j = T.k;
T.k = tmp;
}
}
double zDir(
const vector<F5_vec3_point_t>&Coords,
F5_triangle_t &T)
{
A = Coords[T.i],
B = Coords[T.j],
C = Coords[T.k],
BA = { B.x - A.x, B.y - A.y, B.z - A.z },
CA = { C.x - A.x, C.y - A.y, C.z - A.z };
double zDir = BA.x*CA.y - CA.x*BA.y;
return zDir;
}
{
int tmp = T.j;
T.j = T.k;
T.k = tmp;
}
int main(int argc, char*argv[])
{
double time = 0.0;
hid_t fileID;
string gridname;
char buf[1024];
int nCoords = 0,
nTriangles = 0;
FILE*what;
int time_steps_to_load = -1;
if (argc<2)
{
puts("Usage: ADCIRCtoF5 <inputfile.grd> <number of time steps>");
puts("Time step argument may be ommitted to convert all time steps");
return 1;
}
if (argc > 2)
{
time_steps_to_load = atoi(argv[2]);
}
strcpy(buf, argv[1]);
{
char*c = strrchr(buf, '.');
if (c)
{
*c = 0;
strcat(c, ".f5");
fileID = H5Fcreate(buf,
H5F_ACC_TRUNC,
H5P_DEFAULT,
H5P_DEFAULT);
}
else
{
puts("invalid filename.");
return 3;
}
*c = 0;
gridname = buf;
}
what = fopen(argv[1], "rt");
if (!what)
{
printf("Cannot open '%s'. That's not good.\n", argv[1] );
return 2;
}
fgets(buf, sizeof(buf), what);
if (fscanf(what, "%d %d\n",&nTriangles, &nCoords) !=2)
{
fprintf(stderr,"Error cant find no of points and triangles in header\n");
return 5;
}
fprintf(stderr,"Read no of coords %d and triangles %d\n",nCoords, nTriangles);
fflush(stderr);
vector<F5_vec3_point_t> Coords;
Coords.resize( nCoords );
{for (int i=0; i<nCoords; i++)
{
int index;
double x,y,z;
if (fscanf(what, "%d %lg %lg %lg\n",&index, &x, &y, &z) !=4) {
fprintf(stderr,"Error cant find 3 coords for index %d\n",i);
return 5;
}
assert(index == i+ 1);
Coords[i].x = x;
Coords[i].y = y;
Coords[i].z = z;
}}
vector<F5_triangle_t> Triangles;
Triangles.resize( nTriangles );
vector<F5_triangle_t> Levees;
vector<vector<int> > LeveeComplex;
{for (int i=0; i<nTriangles; i++)
{
int index;
int nodes_nr;
int idx[3];
if (fscanf(what, "%d %d %d %d %d\n",&index, &nodes_nr, &idx[0], &idx[1], &idx[2]) !=5)
{
fprintf(stderr,"Error cant find 3 vertices for index %d\n",i);
return 5;
}
assert(index == i + 1);
assert(nodes_nr == 3);
Triangles[i].i = idx[0]-1;
Triangles[i].j = idx[1]-1;
Triangles[i].k = idx[2]-1;
}}
vector<vector<int> > WeirComplex;
int DoID = -1;
char *ADCIRC_ID = getenv("ADCIRC_ID");
if (ADCIRC_ID)
DoID = atoi( ADCIRC_ID );
for(int N=0; N<2; N++)
{
int Number;
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d", &Number) < 1)
{
puts("ERROR in decoding object number");
break;
}
printf("Got Object number line: %s", buf);
int TotalNodeNumber;
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d", &TotalNodeNumber) < 1)
{
puts("ERROR in getting the total number of nodes");
break;
}
printf("Got Object total node number: %s", buf);
for(int ID=0; ID<Number; ID++)
{
int nodes, type;
fgets(buf, sizeof(buf), what);
int got = sscanf(buf, "%d %d", &nodes, &type);
if (got < 2)
{
if (got<1)
{
puts("ERROR in decoding boundary type");
printf("LINE: %s\n", buf);
return 1;
}
for(int i=0; i<nodes; i++)
{
int I;
fgets(buf, sizeof(buf), what);
sscanf(buf, "%d\n", &I);
}
puts("open boundary done.");
}
else if ( type==0 || type==1 || type==2 || type==10 || type==11 ||type==11 ||
type==12 || type==20 || type==21 || type==22
|| type == 52
)
{
int I;
for(int i=0; i<nodes; i++)
{
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d\n", &I)<1)
{
puts("ERROR: cannot decode boundary");
break;
}
}
printf("Boundary No. %d done\n", ID); fflush(stdout);
}
else if ( type==3 || type==13 || type==23 )
{
int I;
double height, CoeffA;
WeirComplex.push_back( vector<int>() );
LeveeComplex.push_back( vector<int>() );
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d %lg %lg\n", &I, &height, &CoeffA )<3)
{
puts("ERROR: cannot decode weirs");
break;
}
I--;
double HeightScale = 0.001;
height *= HeightScale;
int VI;
VI = Coords.size();
VIc.z = height;
Coords.push_back( VIc );
std::cerr << "Weir " << ID << "found - adding "
<< 2*nodes << "triangles (now at "
<< Triangles.size() << ")" << std::endl;
fflush(stderr);
for(int i=0; i<nodes-1; i++)
{
int Inew;
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d %lg %lg\n", &Inew, &height, &CoeffA)<3)
{
puts("ERROR: cannot decode weirs");
break;
}
Inew--;
I = Inew;
}
}
else if (type==24 || type== 4)
{
int I, J;
double height, CoeffA, CoeffB;
WeirComplex.push_back( vector<int>() );
LeveeComplex.push_back( vector<int>() );
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d %d %lg %lg %lg\n", &I, &J, &height, &CoeffA, &CoeffB)<5)
{
puts("ERROR: cannot decode weirs");
break;
}
I--; J--;
double HeightScale = 0.001;
height *= HeightScale;
int VI;
VI = Coords.size();
VIc.z = height;
Coords.push_back( VIc );
int VJ;
VJ = Coords.size();
VJc.z = height;
Coords.push_back( VJc );
std::cerr << "Weir " << ID << " found - adding "
<< 2*nodes << " triangles (now at "
<< Triangles.size() << ")" << std::endl;
fflush(stderr);
bool flipit = false;
for(int i=0; i<nodes-1; i++)
{
int Inew, Jnew;
fgets(buf, sizeof(buf), what);
if (sscanf(buf, "%d %d %lg %lg %lg\n", &Inew, &Jnew, &height, &CoeffA, &CoeffB)<5)
{
puts("ERROR: cannot decode weirs");
break;
}
Inew--; Jnew--;
if (DoID>0 && ID != DoID) continue;
{
left.i = I; left.j = J; left.k = Inew;
right.i=Inew; right.j = J; right.k = Jnew;
if (i==0)
{
flipit = (zDir( Coords, left) <= 0.0)
;
}
WeirComplex.back().push_back( Triangles.size() );
if (flipit) flip(left);
Triangles.push_back( left );
WeirComplex.back().push_back( Triangles.size() );
if (flipit) flip(right);
Triangles.push_back( right );
}
{
height *= HeightScale;
int VInew;
VInew = Coords.size();
VIc.z = height;
Coords.push_back( VIc );
int VJnew;
VJnew = Coords.size();
VJc.z = height;
Coords.push_back( VJc );
Trngl.i = I; Trngl.j = VI; Trngl.k = Inew;
if (flipit) flip(Trngl);
LeveeComplex.back().push_back( Levees.size() ); Levees.push_back( Trngl );
Trngl.i = Inew; Trngl.j = VI; Trngl.k = VInew;
if (flipit) flip(Trngl);
LeveeComplex.back().push_back( Levees.size() ); Levees.push_back( Trngl );
Trngl.i = VI; Trngl.j = VJ; Trngl.k = VInew;
if (flipit) flip(Trngl);
LeveeComplex.back().push_back( Levees.size() ); Levees.push_back( Trngl );
Trngl.i = VJ; Trngl.j = VJnew; Trngl.k = VInew;
if (flipit) flip(Trngl);
LeveeComplex.back().push_back( Levees.size() ); Levees.push_back( Trngl );
Trngl.i = VJnew; Trngl.j = J; Trngl.k = Jnew;
if (flipit) flip(Trngl);
LeveeComplex.back().push_back( Levees.size() ); Levees.push_back( Trngl );
Trngl.i = VJnew; Trngl.j = VJ; Trngl.k = J;
if (flipit) flip(Trngl);
LeveeComplex.back().push_back( Levees.size() ); Levees.push_back( Trngl );
VI = VInew;
VJ = VJnew;
}
I = Inew;
J = Jnew;
}
}
else
{
puts("ERROR in decoding ADCIRC file");
printf("ERROR LINE: %s\n", buf);
printf("Unsupported type = %d", type);
return 1;
break;
}
}
printf("Boundary Complex %d done.\n", N);
}
std::cerr << "Triangular surface: " << nCoords << " vertices, "
<< Triangles.size() << " triangles - "
<< Triangles.size() - nTriangles << " for weirs" << std::endl;
fflush(stderr);
&Coords[0], nCoords,
&Triangles[0], Triangles.size() );
if (!MainGrid)
puts("ERROR in writing grid...");
std::cerr << "Levee Triangular surface: " << Coords.size() << " vertices, "
<< Levees.size() << " triangles" << std::endl;
fflush(stderr);
if( Levees.size()>0 )
{
&Coords[0], Coords.size(),
&Levees[0], Levees.size() );
if (!LeveeGrid)
puts("ERROR in writing grid...");
}
Coords.resize( nCoords );
AppendSurfaceData( fileID, gridname, Coords, Triangles, time_steps_to_load );
H5Fclose(fileID);
return 0;
}
void F5Fclose(F5Path *f)
Definition: F5F.c:92
F5Path * F5Flink_triangular_surface(F5Path *target, double time, const char *gridname, const F5_vec3_point_t *Coords, int nCoords, const F5_triangle_t *Triangles, int nTriangles, const char *coordinate_system)
Definition: F5surface.c:51
F5Path * F5write_triangular_surface(hid_t file_id, double time, const char *name, const F5_vec3_point_t *Coords, int nCoords, const F5_triangle_t *Triangles, int nTriangles)
Definition: F5surface.c:9
Definition: F5coordinates.h:58
Definition: F5coordinates.h:246