/* ---------------------------------------------------------------------- LIGGGHTS - LAMMPS Improved for General Granular and Granular Heat Transfer Simulations LIGGGHTS is part of the CFDEMproject www.liggghts.com | www.cfdem.com Copyright 2015- JKU Linz LIGGGHTS is based on LAMMPS LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov This software is distributed under the GNU General Public License. See the README file in the top-level directory. ------------------------------------------------------------------------- */ #ifdef LAMMPS_VTK #include "mpi.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "ctype.h" #include "input.h" #include "modify.h" #include "update.h" #include "error.h" #include "domain.h" #include "comm.h" #include "memory.h" #include "math.h" #include "vector_liggghts.h" #include "input_mesh_hex.h" #include "region_mesh_hex.h" using namespace LAMMPS_NS; enum{UNSUPPORTED_DATA_TYPE,INT,DOUBLE}; #define MAXLINE 2048 InputMeshHex::InputMeshHex(LAMMPS *lmp, int argc, char **argv) : Input(lmp, argc, argv), verbose_(false), read_cell_data_(false) {} InputMeshHex::~InputMeshHex() {} /* ---------------------------------------------------------------------- process all input from filename ------------------------------------------------------------------------- */ void InputMeshHex::meshhexfile(const char *filename, class RegHexMesh *mesh, bool verbose, bool read_cell_data) { verbose_ = verbose; read_cell_data_ = read_cell_data; if(strlen(filename) < 5) error->all(FLERR,"Illegal command, file name too short for input of tet mesh"); // error if another nested file still open // if single open file is not stdin, close it // open new filename and set stl___file if (me == 0) { nonlammps_file = fopen(filename,"r"); if (nonlammps_file == NULL) { char str[128]; sprintf(str,"Cannot open mesh file %s",filename); error->one(FLERR,str); } } else nonlammps_file = NULL; meshhexfile_vtk(mesh); if(nonlammps_file) fclose(nonlammps_file); } /* ---------------------------------------------------------------------- process VTK file ------------------------------------------------------------------------- */ void InputMeshHex::meshhexfile_vtk(class RegHexMesh *mesh) { int n,m; double phix = (mesh->rot_angle[0])*M_PI/180.; double phiy = (mesh->rot_angle[1])*M_PI/180.; double phiz = (mesh->rot_angle[2])*M_PI/180.; int flag_outside = 0; double **points = NULL; int ipoint = 0, npoints = 0; double vert_before_rot[3], vert_after_rot[3]; int **cells = NULL; int icell = 0, ncells = 0; int nhexs = 0; int iLine = 0; int nLines = 0; int nPointLines = 0; bool parse_scalars = false; bool parse_field = false; bool parse_vectors = false; int dataType = UNSUPPORTED_DATA_TYPE; int nFieldArrays = 0; int ihex = 0; char propertyname[256]={}; const char communication[]="comm_exchange_borders"; int flag_other_than_hex = 0; while (1) { // read a line from input script // n = length of line including str terminator, 0 if end of file // if line ends in continuation char '&', concatenate next line if (me == 0) { m = 0; while (1) { if (maxline-m < 2) reallocate(line,maxline,0); if (fgets(&line[m],maxline-m,nonlammps_file) == NULL) { if (m) n = strlen(line) + 1; else n = 0; break; } m = strlen(line); if (line[m-1] != '\n') continue; m--; while (m >= 0 && isspace(line[m])) m--; if (m < 0 || line[m] != '&') { line[m+1] = '\0'; n = m+2; break; } } } // bcast the line // if n = 0, end-of-file // error if label_active is set, since label wasn't encountered // if original input file, code is done // else go back to previous input file MPI_Bcast(&n,1,MPI_INT,0,world); if (n == 0) { break; } if (n > maxline) reallocate(line,maxline,n); MPI_Bcast(line,n,MPI_CHAR,0,world); // lines start with 1 (not 0) nLines++; //parse one line from the file parse_nonlammps(); // skip empty lines if(narg == 0){ if (me == 0 && screen && verbose_) fprintf(screen,"Note: Skipping empty line in VTK mesh file\n"); continue; } // Note that the first line of an ASCII VTK files start with '#' and will be skipped //increase line counter iLine++; if(iLine < 2) continue; if(iLine == 2) { if(strcmp(arg[0],"ASCII")) error->all(FLERR,"Expecting ASCII VTK mesh file, cannot continue"); continue; } if(iLine == 3) { if(strcmp(arg[0],"DATASET") || strcmp(arg[1],"UNSTRUCTURED_GRID")) error->all(FLERR,"Expecting ASCII VTK unstructured grid mesh file, cannot continue"); continue; } if(iLine == 4) { if(strcmp(arg[0],"POINTS")) error->all(FLERR,"Expecting 'POINTS' section in ASCII VTK mesh file, cannot continue"); npoints = atoi(arg[1]); memory->create(points,npoints,3,"input_mesh:points"); continue; } if(ipoint < npoints) { if(narg % 3) error->all(FLERR,"Expecting multiple of 3 values of point data in 'POINTS' section of ASCII VTK mesh file, cannot continue"); //read the vertex, translate and scale it for(int i = 0; i < narg/3; ++i) { for (int j = 0; j < 3; ++j) { vert_before_rot[j] = (atof(arg[3*i+j])+(mesh->off_fact[j]))*(mesh->scale_fact); } //rotate the vertex vert_after_rot[0] = vert_before_rot[0]*cos(phiy)*cos(phiz)+vert_before_rot[1]*(cos(phiz)*sin(phix)*sin(phiy)-cos(phix)*sin(phiz))+vert_before_rot[2]*(cos(phix)*cos(phiz)*sin(phiy)+sin(phix)*sin(phiz)); vert_after_rot[1] = vert_before_rot[0]*cos(phiy)*sin(phiz)+vert_before_rot[2]*(-cos(phiz)*sin(phix)+cos(phix)*sin(phiy)*sin(phiz))+vert_before_rot[1]*(cos(phix)*cos(phiz)+sin(phix)*sin(phiy)*sin(phiz)); vert_after_rot[2] = vert_before_rot[2]*cos(phix)*cos(phiy)+vert_before_rot[1]*cos(phiy)*sin(phix)-vert_before_rot[0]*sin(phiy); if (!domain->is_in_domain(vert_after_rot)) flag_outside = 1; //store the vertex vectorCopy3D(vert_after_rot,points[ipoint]); ++ipoint; } ++nPointLines; continue; } if(iLine == 5+nPointLines) { if(strcmp(arg[0],"CELLS")) error->all(FLERR,"Expecting 'CELLS' section in ASCII VTK mesh file, cannot continue"); ncells = atoi(arg[1]); memory->create(cells,ncells,8,"input_mesh_hex:cells"); continue; } //copy data of all which have 8 values - can be tet, quad, poly_line or triangle_strip if(iLine <= 5+nPointLines+ncells) { if(narg == 9) for (int j=0;j<8;j++) cells[icell][j] = atoi(arg[1+j]); else cells[icell][0] = -1; icell++; continue; } if(iLine == 6+nPointLines+ncells) { if(strcmp(arg[0],"CELL_TYPES")) error->all(FLERR,"Expecting 'CELL_TYPES' section in ASCII VTK mesh file, cannot continue"); if(ncells != atoi(arg[1])) error->all(FLERR,"Inconsistency in 'CELL_TYPES' section in ASCII VTK mesh file, cannot continue"); icell = 0; continue; } //only take hexahedra (cell type 12 according to VTK standard) - count them if(iLine <= 6+nPointLines+2*ncells) { if(strcmp(arg[0],"12")) { cells[icell][0] = -1; //remove if not a hex flag_other_than_hex = 1; } else nhexs++; icell++; continue; } if(strcmp(arg[0],"POINT_DATA") == 0) { error->warning(FLERR,"Support for 'POINT_DATA' in ASCII VTK mesh file not implemented, skipping data"); break; } // parsing cell data if(read_cell_data_) { if(iLine == 7+nPointLines+2*ncells) { if(strcmp(arg[0],"CELL_DATA")) error->all(FLERR,"Expecting 'CELL_DATA' section in ASCII VTK mesh file, cannot continue"); if(ncells != atoi(arg[1])) error->all(FLERR,"Inconsistency in 'CELL_DATA' section in ASCII VTK mesh file, cannot continue"); continue; } if(strcmp(arg[0],"SCALARS") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'SCALARS' section in ASCII VTK mesh file, cannot continue"); if(narg > 3 && atoi(arg[3]) > 1) error->all(FLERR,"Support for 'SCALARS' with more than 1 component in ASCII VTK mesh file not implemented, cannot continue"); strcpy(propertyname, arg[1]); if(strcmp(arg[2],"int") == 0 || strcmp(arg[2],"long") == 0 || strcmp(arg[2],"vtkIdType") == 0) { mesh->prop().addElementProperty< ScalarContainer >(propertyname,communication,"frame_invariant","restart_yes",1,nhexs); dataType = INT; } else if(strcmp(arg[2],"float") == 0 || strcmp(arg[2],"double") == 0) { mesh->prop().addElementProperty< ScalarContainer >(propertyname,communication,"frame_invariant","restart_yes",1,nhexs); dataType = DOUBLE; } else { dataType = UNSUPPORTED_DATA_TYPE; error->warning(FLERR,"Data type for 'SCALARS' in ASCII VTK mesh file not implemented, skipping data"); } parse_scalars = true; icell = 0; ihex = 0; continue; } if(strcmp(arg[0],"LOOKUP_TABLE") == 0) { if(!parse_scalars) error->all(FLERR,"Unexpected 'LOOKUP_TABLE' section in ASCII VTK mesh file, cannot continue"); if(strcmp(arg[1],"default")) error->all(FLERR,"Parsing of custom lookup table in ASCII VTK mesh file not implemented, cannot continue"); continue; } if(strcmp(arg[0],"FIELD") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'FIELD' section in ASCII VTK mesh file, cannot continue"); nFieldArrays = atoi(arg[2]); parse_field = true; icell = -1; continue; } if(strcmp(arg[0],"COLOR_SCALARS") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'COLOR_SCALARS' section in ASCII VTK mesh file, cannot continue"); error->warning(FLERR,"Support for 'COLOR_SCALARS' section in ASCII VTK mesh file not implemented, skipping data"); continue; } if(strcmp(arg[0],"VECTORS") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'VECTORS' section in ASCII VTK mesh file, cannot continue"); strcpy(propertyname, arg[1]); if(strcmp(arg[2],"int") == 0 || strcmp(arg[2],"long") == 0 || strcmp(arg[2],"vtkIdType") == 0) { mesh->prop().addElementProperty< VectorContainer >(propertyname,communication,"frame_invariant","restart_yes",1,nhexs); dataType = INT; } else if(strcmp(arg[2],"float") == 0 || strcmp(arg[2],"double") == 0) { mesh->prop().addElementProperty< VectorContainer >(propertyname,communication,"frame_invariant","restart_yes",1,nhexs); dataType = DOUBLE; } else { dataType = UNSUPPORTED_DATA_TYPE; error->warning(FLERR,"Data type for 'VECTORS' in ASCII VTK mesh file not implemented, skipping data"); } parse_vectors = true; icell = 0; ihex = 0; continue; } if(strcmp(arg[0],"NORMALS") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'NORMALS' section in ASCII VTK mesh file, cannot continue"); error->warning(FLERR,"Support for 'NORMALS' section in ASCII VTK mesh file not implemented, skipping data"); continue; } if(strcmp(arg[0],"TEXTURE_COORDINATES") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'TEXTURE_COORDINATES' section in ASCII VTK mesh file, cannot continue"); error->warning(FLERR,"Support for 'TEXTURE_COORDINATES' section in ASCII VTK mesh file not implemented, skipping data"); continue; } if(strcmp(arg[0],"TENSORS") == 0) { if(parse_scalars || parse_field || parse_vectors) error->all(FLERR,"Unexpected 'TENSORS' section in ASCII VTK mesh file, cannot continue"); error->warning(FLERR,"Support for 'TENSORS' section in ASCII VTK mesh file not implemented, skipping data"); continue; } if(parse_scalars) { switch(dataType) { case INT: { ScalarContainer *ep = mesh->prop().getElementProperty >(propertyname); for(int i = 0; i < narg; ++i) { if(cells[icell][0] != -1) { ep->set(ihex, atoi(arg[i])); ++ihex; } ++icell; } break; } case DOUBLE: { ScalarContainer *ep = mesh->prop().getElementProperty >(propertyname); for(int i = 0; i < narg; ++i) { if(cells[icell][0] != -1) { ep->set(ihex, atof(arg[i])); ++ihex; } ++icell; } break; } case UNSUPPORTED_DATA_TYPE: icell += narg; break; } if(icell == ncells) parse_scalars = false; continue; } if(parse_field) { if(icell < 0) { strcpy(propertyname, arg[0]); if(atoi(arg[1]) > 1) error->all(FLERR,"Support for field arrays with more than 1 component in ASCII VTK mesh file not implemented, cannot continue"); if(ncells != atoi(arg[2])) error->all(FLERR,"Inconsistency in 'FIELD' section in ASCII VTK mesh file, cannot continue"); if(strcmp(arg[3],"int") == 0 || strcmp(arg[3],"long") == 0 || strcmp(arg[3],"vtkIdType") == 0) { mesh->prop().addElementProperty< ScalarContainer >(propertyname,communication,"frame_invariant","restart_yes",1,nhexs); dataType = INT; } else if(strcmp(arg[3],"float") == 0 || strcmp(arg[3],"double") == 0) { mesh->prop().addElementProperty< ScalarContainer >(propertyname,communication,"frame_invariant","restart_yes",1,nhexs); dataType = DOUBLE; } else { dataType = UNSUPPORTED_DATA_TYPE; error->warning(FLERR,"Data type for 'FIELD' in ASCII VTK mesh file not implemented, skipping data"); } icell = 0; ihex = 0; continue; } switch(dataType) { case INT: { ScalarContainer *ep = mesh->prop().getElementProperty >(propertyname); for(int i = 0; i < narg; ++i) { if(cells[icell][0] != -1) { ep->set(ihex, atoi(arg[i])); ++ihex; } ++icell; } break; } case DOUBLE: { ScalarContainer *ep = mesh->prop().getElementProperty >(propertyname); for(int i = 0; i < narg; ++i) { if(cells[icell][0] != -1) { ep->set(ihex, atof(arg[i])); ++ihex; } ++icell; } break; } case UNSUPPORTED_DATA_TYPE: icell += narg; break; } if(icell == ncells) { --nFieldArrays; if(nFieldArrays > 0) icell = -1; else parse_field = false; } continue; } if(parse_vectors) { if(narg % 3) error->all(FLERR,"Expecting multiple of 3 values of cell data in 'VECTORS' section of ASCII VTK mesh file, cannot continue"); switch(dataType) { case INT: { VectorContainer *ep = mesh->prop().getElementProperty >(propertyname); for(int i = 0; i < narg/3; ++i) { if(cells[icell][0] != -1) { int vector[3]; vector[0] = atoi(arg[3*i + 0]); vector[1] = atoi(arg[3*i + 1]); vector[2] = atoi(arg[3*i + 2]); ep->set(ihex, vector); ++ihex; } ++icell; } break; } case DOUBLE: { VectorContainer *ep = mesh->prop().getElementProperty >(propertyname); for(int i = 0; i < narg/3; ++i) { if(cells[icell][0] != -1) { double vector[3]; vector[0] = atof(arg[3*i + 0]); vector[1] = atof(arg[3*i + 1]); vector[2] = atof(arg[3*i + 2]); ep->set(ihex, vector); ++ihex; } ++icell; } break; } case UNSUPPORTED_DATA_TYPE: icell += narg/3; break; } if(icell == ncells) parse_vectors = false; continue; } } } //must throw an error here since regions may not extend outside box if(flag_outside) error->all(FLERR,"VTK mesh file is incompatible with simulation box: One or more vertices outside simulation box"); //now that everything is parsed, write the data into the mesh while(mesh->nHexMax < nhexs) mesh->grow_arrays(); double **hexnodes; memory->create(hexnodes,8,3,"input_mesh_hex:hexnodes"); for(int i = 0; i < ncells; i++) { if(cells[i][0] == -1) continue; for (int j = 0; j < 8; j++) vectorCopy3D(points[cells[i][j]],hexnodes[j]); mesh->add_hex(hexnodes); } if(flag_other_than_hex && comm->me == 0) error->warning(FLERR,"VTK file contains other types than hexahedra - only hexs are currently supported in LIGGGHTS, other cells are discarded"); if(ncells == 0) error->all(FLERR,"VTK mesh file containing no hex cell - cannnot continue"); memory->destroy(hexnodes); memory->destroy(points); memory->destroy(cells); } #endif