[MOAB-dev] r3122 - MOAB/trunk
bmsmith6 at wisc.edu
bmsmith6 at wisc.edu
Thu Aug 27 12:28:21 CDT 2009
Author: bmsmith
Date: 2009-08-27 12:28:21 -0500 (Thu, 27 Aug 2009)
New Revision: 3122
Added:
MOAB/trunk/ReadNASTRAN.cpp
MOAB/trunk/ReadNASTRAN.hpp
Modified:
MOAB/trunk/MBReaderWriterSet.cpp
MOAB/trunk/Makefile.am
Log:
Initial commit of NASTRAN reader
Modified: MOAB/trunk/MBReaderWriterSet.cpp
===================================================================
--- MOAB/trunk/MBReaderWriterSet.cpp 2009-08-27 17:18:02 UTC (rev 3121)
+++ MOAB/trunk/MBReaderWriterSet.cpp 2009-08-27 17:28:21 UTC (rev 3122)
@@ -25,6 +25,7 @@
#include "ReadGmsh.hpp"
#include "ReadIDEAS.hpp"
#include "ReadMCNP5.hpp"
+#include "ReadNASTRAN.hpp"
#include "ReadABAQUS.hpp"
#include "ReadSms.hpp"
#include "Tqdcfr.hpp"
@@ -79,6 +80,8 @@
register_factory( ReadMCNP5::factory, NULL, "MCNP5 format", "meshtal", "MESHTAL" );
+ register_factory( ReadNASTRAN::factory, NULL, "NASTRAN format", "nas", "NAS" );
+
register_factory( ReadABAQUS::factory, NULL, "ABAQUS INP mesh format", "abq", "Abaqus mesh" );
register_factory( ReadVtk::factory, WriteVtk::factory, "Kitware VTK", "vtk", "VTK" );
Modified: MOAB/trunk/Makefile.am
===================================================================
--- MOAB/trunk/Makefile.am 2009-08-27 17:18:02 UTC (rev 3121)
+++ MOAB/trunk/Makefile.am 2009-08-27 17:28:21 UTC (rev 3122)
@@ -177,6 +177,8 @@
ReadIDEAS.hpp \
ReadMCNP5.cpp \
ReadMCNP5.hpp \
+ ReadNASTRAN.cpp \
+ ReadNASTRAN.hpp \
ReadABAQUS.cpp \
ReadABAQUS.hpp \
ReadTetGen.cpp \
Added: MOAB/trunk/ReadNASTRAN.cpp
===================================================================
--- MOAB/trunk/ReadNASTRAN.cpp (rev 0)
+++ MOAB/trunk/ReadNASTRAN.cpp 2009-08-27 17:28:21 UTC (rev 3122)
@@ -0,0 +1,360 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation. Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#include "ReadNASTRAN.hpp"
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <vector>
+#include <cstdlib>
+#include <assert.h>
+#include <cmath>
+
+#include "MBInterface.hpp"
+#include "MBReadUtilIface.hpp"
+#include "MBInternals.hpp" // for MB_START_ID
+#include "MBRange.hpp"
+#include "FileOptions.hpp"
+#include "FileTokenizer.hpp"
+#include "MBTagConventions.hpp"
+#include "MBCN.hpp"
+
+MBReaderIface* ReadNASTRAN::factory( MBInterface* iface ) {
+ return new ReadNASTRAN( iface );
+}
+
+// constructor
+ReadNASTRAN::ReadNASTRAN(MBInterface* impl)
+ : MBI(impl), fileIDTag(0) {
+ assert(NULL != impl);
+ void *ptr = 0;
+ MBI->query_interface("MBReadUtilIface", &ptr);
+ assert(NULL != ptr);
+ readMeshIface = reinterpret_cast<MBReadUtilIface*>(ptr);
+}
+
+// destructor
+ReadNASTRAN::~ReadNASTRAN() {
+ if (readMeshIface) {
+ MBI->release_interface("MBReadUtilIface", readMeshIface);
+ readMeshIface = 0;
+ }
+}
+
+MBErrorCode ReadNASTRAN::read_tag_values( const char* file_name,
+ const char* tag_name,
+ const FileOptions& opts,
+ std::vector<int>& tag_values_out,
+ const IDTag* subset_list,
+ int subset_list_length )
+{
+ return MB_NOT_IMPLEMENTED;
+}
+
+// load the file as called by the MBInterface function
+MBErrorCode ReadNASTRAN::load_file(const char *filename,
+ MBEntityHandle &file_set,
+ const FileOptions &options,
+ const MBReaderIface::IDTag *subset_list,
+ int subset_list_length,
+ const MBTag* file_id_tag) {
+ // at this time there is no support for reading a subset of the file
+ if (subset_list && subset_list_length) {
+ readMeshIface->report_error( "Reading subset of files not supported for NASTRAN." );
+ return MB_UNSUPPORTED_OPERATION;
+ }
+
+ nodeId = elemId = 0;
+ fileIDTag = file_id_tag;
+
+ bool debug = false;
+ if (debug) std::cout << "begin ReadNASTRAN::load_file" << std::endl;
+ MBErrorCode result;
+ FILE* file = fopen( filename, "r" );
+
+ // create the file set
+ result = MBI->create_meshset(MESHSET_SET, file_set);
+ if(MB_SUCCESS != result) return result;
+
+ // create tags
+ MBTag id_tag, material_tag;
+ result = MBI->tag_create(GLOBAL_ID_TAG_NAME, sizeof(int), MB_TAG_DENSE,
+ MB_TYPE_INTEGER, id_tag, 0);
+ if(MB_SUCCESS!=result && MB_ALREADY_ALLOCATED!=result) return result;
+ result = MBI->tag_create(MATERIAL_SET_TAG_NAME, sizeof(int), MB_TAG_DENSE,
+ MB_TYPE_INTEGER, material_tag, 0);
+ if(MB_SUCCESS!=result && MB_ALREADY_ALLOCATED!=result) return result;
+
+ // IMPORTANT: these are the same as the MOAB enums. Currently only vertices,
+ // tets, and prisms are supported. Implement more as needed.
+ const char* const data_type_names[] = { "GRID", // MBVERTEX
+ "MBEDGE",
+ "MBTRI",
+ "MBQUAD",
+ "MBPOLYGON",
+ "CTETRA", // MBTET
+ "MBPYRAMID",
+ "CPENTA", // MBPRISM
+ "MBKNIFE",
+ "MBHEX",
+ "MBPOLYHEDRON",
+ "MBENTITYSET",
+ "MBMAXTYPE" };
+
+ /* Count the entities of each type in the file. If the token is not
+ matched assume that it is something else in the file (not an error).
+ During the next read we will check for errors.
+ This is used to allocate the node array. Let the tokenizer run out of
+ scope (and thus call fclose). There is no other way to rewind the
+ tokenizer. */
+ int entity_count[MBMAXTYPE];
+ for(int i=0; i<MBMAXTYPE; i++) entity_count[i] = 0;
+ { FileTokenizer tokens( file, readMeshIface );
+ while( !tokens.eof() ) {
+ int data = tokens.match_token( data_type_names ) -1;
+ if(-1 != data) entity_count[data]++;
+ }
+ }
+ if(debug) {
+ for(int i=0; i<MBMAXTYPE; i++) {
+ std::cout << "entity_count[" << i << "]=" << entity_count[i] << std::endl;
+ }
+ }
+
+ /* If we assume that the node ids are continuous, then the node ids can be
+ easily mapped to vertex handles. If they are not continuous then the node
+ ids themselves will need to be used to create connectivity. It is very
+ slow to find each node by its id because this is a tag call. */
+ bool node_ids_are_continuous = true;
+
+ // Now that the number of vertices is known, create the vertices.
+ MBEntityHandle start_vert = NULL;
+ std::vector<double*> coord_arrays(3);
+ result = readMeshIface->get_node_arrays( 3, entity_count[0], MB_START_ID,
+ start_vert, coord_arrays );
+ if(MB_SUCCESS != result) return result;
+ if(0 == start_vert) return MB_FAILURE; // check for NULL
+ int vert_index = 0;
+ if(debug) std::cout << "allocated coord arrays" << std::endl;
+
+ // Read the file again and build the entities. Each line in the file
+ // represents one entity.
+ file = fopen( filename, "r" );
+ FileTokenizer tokens( file, readMeshIface );
+ while( !tokens.eof() ) {
+ // these have been enumerated to match MBEntityTypes
+ int data = tokens.match_token( data_type_names ) -1;
+ MBEntityType datatype = (MBEntityType)data;
+ if(debug) {
+ std::cout << "MBVERTEX=" << MBVERTEX << " datatype=" << datatype << std::endl;
+ }
+
+ // the eof was found
+ if( tokens.eof() ) {
+ break;
+
+ // no matching entity was found
+ } else if(-1 == datatype ) {
+ return MB_NOT_IMPLEMENTED;
+
+ // a vertex line was found
+ } else if(MBVERTEX == datatype) {
+ result = read_node(tokens, id_tag, file_set, debug, coord_arrays,
+ vert_index, start_vert, node_ids_are_continuous );
+ if(MB_SUCCESS != result) return result;
+
+ // an element line was found
+ } else {
+ result = read_element(tokens, id_tag, material_tag, datatype, file_set,
+ debug, start_vert, node_ids_are_continuous );
+ if(MB_SUCCESS != result) return result;
+ }
+ }
+ return MB_SUCCESS;
+}
+
+/* It has been determined that this line is a vertex. Read the rest of
+ the line and create the vertex. */
+MBErrorCode ReadNASTRAN::read_node( FileTokenizer &tokens,
+ MBTag id_tag,
+ const MBEntityHandle file_set,
+ const bool debug,
+ std::vector<double*> coord_arrays,
+ int &vert_index,
+ const MBEntityHandle start_vert,
+ bool &node_ids_are_continuous ) {
+ // read the node's id (unique)
+ MBErrorCode result;
+ int id;
+ if( !tokens.get_integers(1, &id) ) return MB_FAILURE;;
+
+ // read the coordinates
+ const char* coords_string = tokens.get_string();
+ if (!coords_string) return MB_FAILURE;
+ if(debug) std::cout << "coords_string=" << coords_string << std::endl;
+ double coords[3];
+ result = parse_coords( coords_string, coords, debug );
+ if(MB_SUCCESS != result) return result;
+
+ // create the node
+ MBEntityHandle vert = start_vert+vert_index;
+ for(int i=0; i<3; i++) coord_arrays[i][vert_index] = coords[i];
+ vert_index++;
+
+ // check to see if the node ids are still continuous
+ if(id != vert_index) {
+ node_ids_are_continuous = false;
+ std::cout << "node ids are not continuous" << std::endl;
+ }
+
+ // tag with the global id from the NASTRAN file
+ result = MBI->tag_set_data( id_tag, &vert, 1, &id );
+ if(MB_SUCCESS != result) return result;
+
+ // add to the file set
+ result = MBI->add_entities( file_set, &vert, 1 );
+ if(MB_SUCCESS != result) return result;
+
+ return MB_SUCCESS;
+}
+
+/* The coordinates are difficult to parse. Below are some samples. */
+MBErrorCode ReadNASTRAN::parse_coords( const char *coords_string,
+ double coords[],
+ const bool debug ) {
+ /* GRID 1 03.9804546.9052-15.6008-1
+ has the coordinates: ( 3.980454, 6.9052e-1, 5.6008e-1 )
+ GRID 200005 04.004752-3.985-15.4955-1
+ has the coordinates: ( 4.004752, -3.985e-1, 5.4955e-1 ) */
+ char x[9], y[8], z[8];
+ strncpy(x, coords_string, 9); //will copy first 4 characters
+ strncpy(y, coords_string+sizeof(x), 8);
+ strncpy(z, coords_string+sizeof(x)+sizeof(y), 8);
+ if(debug) std::cout << "x=" << x << " y=" << y << " z=" << z << std::endl;
+
+ // returns memory location of last match if found. returns null if not found.
+ char *x_loc, *y_loc, *z_loc;
+ x_loc = strrchr(x,'-'); // - x + 1;
+ y_loc = strrchr(y,'-'); // - y + 1;
+ z_loc = strrchr(z,'-'); // - z + 1;
+ if(debug) std::cout << "loc=" << x_loc << " " << y_loc << " " << z_loc << std::endl;
+
+ // copies( destination memory address, source memory address, size to copy)
+ // copy only the exponent, if it exists.
+ char exp_x[9], exp_y[8], exp_z[8];
+ if(0 != x_loc) {
+ memcpy(exp_x, x_loc, 9);
+ coords[0] = atof(x) * pow(10, atof(exp_x));
+ } else {
+ coords[0] = atof(x);
+ }
+ if(0 != y_loc) {
+ memcpy(exp_y, y_loc, 8 );
+ coords[1] = atof(y) * pow(10, atof(exp_y));
+ } else {
+ coords[1] = atof(y);
+ }
+ if(0 != z_loc) {
+ memcpy(exp_z, z_loc, 8-(int)(z_loc-z) );
+ coords[2] = atof(z)*pow(10, atof(exp_z));;
+ } else {
+ coords[2] = atof(z);
+ }
+ //std::cout << "exp=" << exp_x << " " << exp_y << " " << exp_z << std::endl;
+ if(debug) std::cout << "coords[]=" << coords[0] << " " << coords[1]
+ << " " << coords[2] << std::endl;
+
+ return MB_SUCCESS;
+}
+
+/* The type of element has already been identified. Read the rest of the
+ line and create the element. Assume that all of the nodes have already
+ been created. */
+MBErrorCode ReadNASTRAN::read_element( FileTokenizer &tokens,
+ MBTag id_tag,
+ MBTag material_tag,
+ const MBEntityType element_type,
+ const MBEntityHandle file_set,
+ const bool debug,
+ const MBEntityHandle start_vert,
+ const bool node_ids_are_continuous ) {
+
+ // read the element's id (unique) and material set
+ MBErrorCode result;
+ int id;
+ bool res = tokens.get_integers(1, &id);
+ if(false == res) return MB_FAILURE;
+ int material;
+ res = tokens.get_integers(1, &material);
+ if(false == res) return MB_FAILURE;
+
+ // the size of the connectivity array depends on the element type
+ int n_conn = MBCN::VerticesPerEntity(element_type);
+
+ // read the connected node ids from the file
+ int conn[n_conn];
+ res = tokens.get_integers(n_conn, conn);
+ if(false == res) return MB_FAILURE;
+
+ /* Get the vertex handles with those node ids. If the nodes do not have
+ continuous ids we need to do a very slow tag search for global ids.
+ The cannonical numbering between NASTRAN and MOAB is the same for
+ tets and prisms. */
+ MBEntityHandle conn_verts[n_conn];
+ for(int i=0; i<n_conn; i++) {
+ if(node_ids_are_continuous) {
+ conn_verts[i] = start_vert + conn[i] -1;
+ } else {
+ void *vert_id_val[] = {&conn[i]};
+ MBRange vert;
+ result = MBI->get_entities_by_type_and_tag( file_set, MBVERTEX, &id_tag,
+ vert_id_val, 1, vert );
+ if(MB_SUCCESS != result) return result;
+ if(1 != vert.size()) return MB_FAILURE; // only one vertex should have this global id
+ conn_verts[i] = vert.front();
+ }
+ if(debug) std::cout << "conn[" << i << "]=" << conn[i] << std::endl;
+ }
+
+ // Create the element and set the global id from the NASTRAN file
+ MBEntityHandle element;
+ result = MBI->create_element( element_type, conn_verts, n_conn, element );
+ if(MB_SUCCESS != result) return result;
+ result = MBI->tag_set_data( id_tag, &element, 1, &id );
+ if(MB_SUCCESS != result) return result;
+
+ // Create the material set for the element if it does not already exist.
+ void *mat_val[] = {&material};
+ MBRange material_set;
+ result = MBI->get_entities_by_type_and_tag( file_set, MBENTITYSET, &material_tag,
+ mat_val, 1, material_set );
+ if(MB_SUCCESS != result) return result;
+ if(0 == material_set.size()) {
+ MBEntityHandle new_material_set;
+ result = MBI->create_meshset( 0, new_material_set );
+ if(MB_SUCCESS != result) return result;
+ result = MBI->add_entities( file_set, &new_material_set, 1 );
+ result = MBI->tag_set_data( material_tag, &new_material_set, 1, &material );
+ if(MB_SUCCESS != result) return result;
+ material_set.insert( new_material_set );
+ } else if(1 < material_set.size()) {
+ return MB_MULTIPLE_ENTITIES_FOUND;
+ }
+ result = MBI->add_entities( material_set.front(), &element, 1 );
+ if(MB_SUCCESS != result) return result;
+
+ return MB_SUCCESS;
+}
Added: MOAB/trunk/ReadNASTRAN.hpp
===================================================================
--- MOAB/trunk/ReadNASTRAN.hpp (rev 0)
+++ MOAB/trunk/ReadNASTRAN.hpp 2009-08-27 17:28:21 UTC (rev 3122)
@@ -0,0 +1,105 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ *
+ * Copyright 2004 Sandia Corporation. Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
+ * retains certain rights in this software.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+//-------------------------------------------------------------------------
+// Filename : ReadNASTRAN.hpp
+//
+// Purpose : NASTRAN file reader
+//
+// Creator : Brandon Smith
+//
+// Date : 08/2009
+//
+//-------------------------------------------------------------------------
+
+#ifndef READNASTRAN_HPP
+#define READNASTRAN_HPP
+
+#ifndef IS_BUILDING_MB
+ #error "ReadNASTRAN.hpp isn't supposed to be included into an application"
+#endif
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <vector>
+
+#include "MBInterface.hpp"
+#include "MBReaderIface.hpp"
+#include "FileTokenizer.hpp"
+
+class MBReadUtilIface;
+
+class ReadNASTRAN : public MBReaderIface
+{
+
+public:
+ // factory method
+ static MBReaderIface* factory( MBInterface* );
+
+ MBErrorCode load_file( const char *filename,
+ MBEntityHandle &file_set,
+ const FileOptions &options,
+ const MBReaderIface::IDTag *subset_list = 0,
+ int subset_list_length = 0,
+ const MBTag *file_id_tag = 0 );
+ // constructor
+ ReadNASTRAN(MBInterface* impl = NULL);
+
+ // destructor
+ virtual ~ReadNASTRAN();
+
+ MBErrorCode read_tag_values( const char *file_name,
+ const char *tag_name,
+ const FileOptions &opts,
+ std::vector<int> &tag_values_out,
+ const IDTag *subset_list,
+ int subset_list_length );
+
+protected:
+
+private:
+ // read mesh interface
+ MBReadUtilIface* readMeshIface;
+
+ // MOAB Interface
+ MBInterface* MBI;
+
+ const MBTag* fileIDTag;
+ int nodeId, elemId;
+
+ MBErrorCode read_node(FileTokenizer &tokens,
+ MBTag id_tag,
+ const MBEntityHandle file_set,
+ const bool debug,
+ std::vector<double*> coord_arrays,
+ int &vert_index,
+ const MBEntityHandle start_vert,
+ bool &node_ids_are_continuous );
+
+ MBErrorCode parse_coords( const char *coords_string,
+ double coords[],
+ const bool debug );
+
+ MBErrorCode read_element(FileTokenizer &tokens,
+ MBTag id_tag,
+ MBTag material_tag,
+ const MBEntityType element_type,
+ const MBEntityHandle file_set,
+ const bool debug,
+ const MBEntityHandle start_vert,
+ const bool node_ids_are_continuous );
+};
+#endif
More information about the moab-dev
mailing list