lammps/lib/atc/MeshReader.cpp

226 lines
7.0 KiB
C++

#include "MeshReader.h"
#include "LammpsInterface.h"
#include "Utility.h"
#ifdef HAS_EXODUS
//#include <stdio.h>
//#include "netcdf.h"
#include "exodusII.h"
#endif
using ATC_Utility::to_string;
using std::ifstream;
using std::istringstream;
using std::stringstream;
using std::map;
using std::pair;
using std::set;
using std::string;
namespace ATC {
/** constructor, takes a filename */
MeshReader::MeshReader(string filename,
Array<bool> periodicity,
double /* tol */)
: meshfile_(filename),
periodicity_(periodicity),
nNodes_(0),
nElements_(0)
{
conn_ = new Array2D<int>();
nodeCoords_ = new DENS_MAT;
nodeSets_ = new Array< std::pair< string,set<int> > >();
size_t idx = filename.rfind('.');
if (idx == string::npos) {
throw ATC_Error("Given mesh file is of unknown type.");
}
string ext = filename.substr(idx+1);
if (ext == "mesh"){ read_mesh_file(); }
else { throw ATC_Error("mesh file is of unknown type."); }
}
/** destructor */
MeshReader::~MeshReader()
{
if (conn_) delete conn_;
if (nodeCoords_) delete nodeCoords_;
if (nodeSets_) delete nodeSets_;
}
/** creates handle to new mesh object */
FE_Mesh* MeshReader::create_mesh()
{
return new FE_3DMesh(elementType_,
nNodes_, nElements_,
conn_, nodeCoords_,
periodicity_,
nodeSets_);
}
int MeshReader::number_of_vertices(string str)
{
string temp;
int number=0;
for (unsigned int i=0; i < str.size(); i++) {
if (isdigit(str[i])) {
for (unsigned int a=i; a<str.size(); a++) {
temp += str[a];
}
break;
}
}
istringstream(temp) >> number;
return number;
}
/** reads .mesh format file */
void MeshReader::read_mesh_file() {
ifstream in;
in.open(meshfile_.c_str(), ifstream::in);
string header;
while (getline(in,header)) {
istringstream words(header);
string section;
words >> section;
if (section == "Coordinates") {
words >> nNodes_;
nodeCoords_->reset(3, nNodes_, false);
string line;
for (int i = 0; i < nNodes_; ++i) {
getline(in,line);
istringstream coords(line);
coords >> (*nodeCoords_)(0, i);
coords >> (*nodeCoords_)(1, i);
coords >> (*nodeCoords_)(2, i);
}
stringstream ss;
ss << "read " << nNodes_ << " nodes";
ATC::LammpsInterface::instance()->print_msg_once(ss.str());
}
else if (section == "Elements") {
words >> nElements_;
words >> elementType_;
int nVerts = number_of_vertices(elementType_);
conn_->reset(nVerts, nElements_);
string line;
for (int i = 0; i < nElements_; ++i) {
getline(in,line);
istringstream verts(line);
for (int j = 0; j < nVerts; ++j ) {
int node;
verts >> node;
(*conn_)(j,i) = node-1;
}
}
stringstream ss;
ss << "read " << nElements_ << " " << elementType_ << " elements";
ATC::LammpsInterface::instance()->print_msg_once(ss.str());
}
else if (section == "Nodesets") {
words >> nNodeSets_;
nodeSets_->reset(nNodeSets_);
string infoline;
string setName;
int nNodes;
string line;
for (int i = 0; i < nNodeSets_; ++i) {
getline(in,infoline);
istringstream info(infoline);
info >> setName;
info >> nNodes;
(*nodeSets_)(i).first = setName;
getline(in,line);
istringstream nodes(line);
for (int j = 0; j < nNodes; ++j ) {
int node;
nodes >> node;
(*nodeSets_)(i).second.insert(node-1);
}
}
}
}
in.close();
if (nodeCoords_->size() == 0) {
throw ATC_Error("Could not find mesh file, or mesh file empty.");
}
}
/** reads .exo format file */
void MeshReader::read_exo_file() {
#ifndef HAS_EXODUS
throw ATC_Error("Reading ExodusII .exo files not supported.");
#else
int CPU_word_size=0,IO_word_size=0;
float version;
int exoid = ex_open (meshfile_.c_str(), EX_READ,
&CPU_word_size, &IO_word_size, &version);
if (exoid < 0) { throw ATC_Error("couldn't open "+meshfile_); }
int nsd,nelemblk,nfsets;
char title[MAX_LINE_LENGTH+1];
int error = ex_get_init (exoid, title,
&nsd, &nNodes_, &nElements_, &nelemblk, &nNodeSets_, &nfsets);
if (error > 0) { throw ATC_Error("problem with init "+meshfile_+" "+title); }
// coordinates
float x[nNodes_], y[nNodes_], z[nNodes_];
error = ex_get_coord (exoid, x, y, z);
if (error > 0) { throw ATC_Error("problem with getting coordinates "+meshfile_); }
nodeCoords_->reset(nsd,nNodes_);
DENS_MAT & nodes = *nodeCoords_;
for (int i = 0; i < nNodes_; ++i) {
nodes(0,i) = x[i]; // this is a float to double conversion
nodes(1,i) = y[i]; // this is a float to double conversion
nodes(2,i) = z[i]; // this is a float to double conversion
}
ATC::LammpsInterface::instance()->print_msg_once("read "+to_string(nNodes_)+
" nodes");
// elements
int blkIds[nelemblk],nblkelem[nelemblk],nnpe[nelemblk],na[nelemblk];
error = ex_get_elem_blk_ids(exoid, blkIds);
char etype[MAX_STR_LENGTH+1];
string lastType;
for (int i=0; i<nelemblk; i++){
error = ex_get_elem_block (exoid, blkIds[i], etype,
&(nblkelem[i]), &(nnpe[i]), &(na[i]));
elementType_ = etype;
if (i > 0 && elementType_ != lastType )
{ throw ATC_Error(meshfile_+" is composed of multiple types"); }
lastType = etype;
}
int nVerts = number_of_vertices(elementType_);
conn_->reset(nVerts, nElements_);
int n = 0;
for (int i=0; i<nelemblk; i++) {
int bconn[nnpe[i]*nblkelem[i]];
error = ex_get_elem_conn (exoid, blkIds[i], &bconn);
for (int j=0; j<nblkelem[i]; j++) {
for (int k=0; k<nnpe[i]; k++) {
(*conn_)(k,n) = bconn[k+j*nnpe[i]]-1;
}
n++;
}
ATC::LammpsInterface::instance()->print_msg_once("read "+to_string(n)+" "+elementType_+" elements, block "+to_string(i+1)+"/"+to_string(nelemblk));
}
// nodesets
int nsetIds[nNodeSets_];
error = ex_get_node_set_ids (exoid, nsetIds);
int nnodes,ndist;
//nodeSets_ = new Array< pair< string,set<int> > >();
nodeSets_->reset(nNodeSets_);
for (int i=0; i<nNodeSets_; i++) {
(*nodeSets_)(i).first = to_string(nsetIds[i]);
error = ex_get_node_set_param (exoid, nsetIds[i], &nnodes, &ndist);
int nodes[nnodes];
error = ex_get_node_set (exoid, nsetIds[i], nodes);
for (int j=0; j<nnodes; j++) {
(*nodeSets_)(i).second.insert(nodes[j]-1);
}
}
error = ex_close(exoid);
if (error > 0) { throw ATC_Error("problem with closing "+meshfile_); }
#endif
}
}; // end namespace ATC