From e2f16032cc61fb59687556d4cd2155b3dab1af76 Mon Sep 17 00:00:00 2001 From: Philippose Rajan Date: Tue, 27 Oct 2009 23:11:15 +0000 Subject: [PATCH] * OpenFOAM 1.5+ Export capability added * Relevant changes to Makefile.am and MSVC project files * Pressing the "Quit" toolbar button now pops up a dialog box --- libsrc/interface/Makefile.am | 2 +- libsrc/interface/writeOpenFOAM15x.cpp | 713 ++++++++++++++++++++++++++ libsrc/interface/writegmsh2.cpp | 522 +++++++++---------- libsrc/interface/writeuser.cpp | 8 +- libsrc/interface/writeuser.hpp | 86 ++-- ng/menustat.tcl | 14 +- windows/netgen.vcproj | 28 +- 7 files changed, 1053 insertions(+), 320 deletions(-) create mode 100644 libsrc/interface/writeOpenFOAM15x.cpp diff --git a/libsrc/interface/Makefile.am b/libsrc/interface/Makefile.am index f1675e70..b65ec94c 100644 --- a/libsrc/interface/Makefile.am +++ b/libsrc/interface/Makefile.am @@ -6,6 +6,6 @@ noinst_LTLIBRARIES = libinterface.la libinterface_la_SOURCES = read_fnf_mesh.cpp readtetmesh.cpp readuser.cpp writeabaqus.cpp writediffpack.cpp \ writedolfin.cpp writeelmer.cpp writefeap.cpp writefluent.cpp writegmsh.cpp writejcm.cpp \ writepermas.cpp writetecplot.cpp writetet.cpp writetochnog.cpp writeuser.cpp \ - wuchemnitz.cpp writegmsh2.cpp + wuchemnitz.cpp writegmsh2.cpp writeOpenFOAM15x.cpp diff --git a/libsrc/interface/writeOpenFOAM15x.cpp b/libsrc/interface/writeOpenFOAM15x.cpp new file mode 100644 index 00000000..2dbedfbc --- /dev/null +++ b/libsrc/interface/writeOpenFOAM15x.cpp @@ -0,0 +1,713 @@ +/*! \file writeOpenFOAM15x.cpp +* \brief Export Netgen Mesh in the OpenFOAM 1.5+ File format +* \author Philippose Rajan +* \date 25 October 2009 +* +* This function extends the export capabilities of +* Netgen to include the OpenFOAM 1.5+ File Format. +* +* The OpenFOAM 1.5+ mesh format consists of a set of 5 files +* which together define the mesh points, faces, cells and +* boundary conditions. +* +* The files are: +* 1. points -> A list of the point co-ordinates +* 2. faces -> A list of the faces with format (pnt_ind1 pnt_ind2 .... pnt_ind) +* 3. owner -> The owner cell of each face +* 4. neighbour -> The neighbour cell of each face +* 5. boundary -> The set of boundaries with name, start face, and num. of faces +* +* For a detailed description of the format, refer to the following link: +* http://openfoamwiki.net/index.php/Write_OpenFOAM_meshes +* +*/ + +#include + +#include +#include +#include +#include +#include + + +namespace netgen +{ +#include "writeuser.hpp" + + // Global Va + Array OF15x_owner_facelist; + Array OF15x_owner_celllist; + Array OF15x_neighbour_facelist; + Array OF15x_neighbour_celllist; + Array OF15x_surfelem_bclist; + Array OF15x_surfelem_facelist; + Array OF15x_surfelem_celllist; + + + void WriteOpenFOAM15xBanner(ofstream & outfile) + { + static char FOAMversion[4] = "1.5"; + static char spaces[40]; + + memset(spaces, ' ', 40); + spaces[38 - strlen(FOAMversion)] = '\0'; + + outfile << + "/*--------------------------------*- C++ -*----------------------------------*\\\n"; + + outfile << + "| ========= | |\n" + "| \\\\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n" + "| \\\\ / O peration | Version: " << FOAMversion << spaces << "|\n" + "| \\\\ / A nd | Web: http://www.OpenFOAM.org |\n" + "| \\\\/ M anipulation | |\n" + "\\*---------------------------------------------------------------------------*/\n"; + + } + + + + void WriteOpenFOAM15xDividerStart(ofstream & outfile) + { + outfile << + "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n"; + } + + + + void WriteOpenFOAM15xDividerEnd(ofstream & outfile) + { + outfile << + "// ************************************************************************* //\n"; + } + + + + void BuildOpenFOAM15xLists (const Mesh & mesh) + { + ResetTime(); + cout << endl << "Building Lists.... "; + + // Clear all the arrays + OF15x_owner_facelist.DeleteAll(); + OF15x_owner_celllist.DeleteAll(); + OF15x_neighbour_facelist.DeleteAll(); + OF15x_neighbour_celllist.DeleteAll(); + OF15x_surfelem_bclist.DeleteAll(); + OF15x_surfelem_facelist.DeleteAll(); + OF15x_surfelem_celllist.DeleteAll(); + + + int ne = mesh.GetNE(); + + const_cast (mesh).BuildElementSearchTree(); + const MeshTopology& meshtopo = mesh.GetTopology(); + + // Update the mesh topology structures + const_cast (mesh).UpdateTopology(); + + // Loop through all the volume elements + for(int elind = 1; elind <= ne; elind++) + { + Array locfaces; + + Element el = mesh.VolumeElement(elind); + locfaces.SetSize(el.GetNFaces()); + + // Get the face numbers of the faces of the current volume element + meshtopo.GetElementFaces(elind,locfaces,false); + + // Loop through the faces + for(int i = 1; i <= locfaces.Size(); i++) + { + // Check if the face is a surface element (boundary face) + // if not, add the current volume element and the corresponding face into + // the owner list + if(!(meshtopo.GetFace2SurfaceElement(locfaces.Elem(i)))) + { + // If the face is already present in the owner list, append the + // current cell and face to the neighbour list else append it + // as usual into the owner list + if(OF15x_owner_facelist.Contains(locfaces.Elem(i))) + { + OF15x_neighbour_celllist.Append(elind); + OF15x_neighbour_facelist.Append(locfaces.Elem(i)); + } + else + { + OF15x_owner_celllist.Append(elind); + OF15x_owner_facelist.Append(locfaces.Elem(i)); + } + } + // If the face is a boundary face, extract the boundary condition number of the + // face, and append that along with the face number and the current cell + // into the various surface elements lists + else + { + Element2d sel = mesh.SurfaceElement(meshtopo.GetFace2SurfaceElement(locfaces.Elem(i))); + OF15x_surfelem_bclist.Append(mesh.GetFaceDescriptor(sel.GetIndex()).BCProperty()); + OF15x_surfelem_facelist.Append(locfaces.Elem(i)); + OF15x_surfelem_celllist.Append(elind); + } + } + } + + // Sort the list of surface elements in ascending order of boundary condition number + // also sort the cell list in the same manner (using a temporary array...!) + Array OF15x_surfelem_tmplist(OF15x_surfelem_bclist); + BubbleSort(OF15x_surfelem_bclist,OF15x_surfelem_facelist); + BubbleSort(OF15x_surfelem_tmplist,OF15x_surfelem_celllist); + OF15x_surfelem_tmplist.DeleteAll(); + + for(int i = 1; i <= OF15x_owner_celllist.Size(); i++) + { + // Order the list of neighbours according to the order of the faces + // in the owners list by searching and swapping the neighbour cell + // and face array + // NOTE: As of now, function "Pos" is zero-based and NOT 1-based!! + int ind = OF15x_neighbour_facelist.Pos(OF15x_owner_facelist.Elem(i)); + if(ind > -1) + { + int facetmp = OF15x_neighbour_facelist.Elem(i); + int celltmp = OF15x_neighbour_celllist.Elem(i); + + // Swap elements in the face and cell lists + OF15x_neighbour_facelist.Elem(i) = OF15x_neighbour_facelist.Elem(ind+1); + OF15x_neighbour_facelist.Elem(ind+1) = facetmp; + OF15x_neighbour_celllist.Elem(i) = OF15x_neighbour_celllist.Elem(ind+1); + OF15x_neighbour_celllist.Elem(ind+1) = celltmp; + } + } + + int rng_start = 1; + int rng_end = 1; + + for(int i = 1; i <= OF15x_owner_celllist.Size(); i++) + { + // Order the face list of each owner cell in accordance to the cell list + // of the neighbours of that owner sorted in ascending order + // This operation is performed by selecting the right range within the + // array (basically... all the neighbours of each owner cell set are + // extracted and sorted one set at a time) + if((OF15x_owner_celllist.Elem(i) == OF15x_owner_celllist.Elem(rng_start)) && (i != OF15x_owner_celllist.Size())) + { + rng_end = i; + } + else + { + if(i == OF15x_owner_celllist.Size()) rng_end = i; + + FlatArray neisort_celllist = OF15x_neighbour_celllist.Range(rng_start-1,rng_end); + FlatArray neisort_facelist = OF15x_neighbour_facelist.Range(rng_start-1,rng_end); + + BubbleSort(neisort_celllist,neisort_facelist); + + // After sorting out the cell and face lists, replace the old list with the + // newly ordered lists + for(int j = 1; j <= neisort_celllist.Size(); j++) + { + OF15x_neighbour_celllist.Elem(rng_start-1+j) = neisort_celllist.Elem(j); + OF15x_neighbour_facelist.Elem(rng_start-1+j) = neisort_facelist.Elem(j); + + OF15x_owner_facelist.Elem(rng_start-1+j) = neisort_facelist.Elem(j); + } + + // initialise the range variables to the next set of owner cells + rng_start = i; + rng_end = i; + } + } + + cout << "Done (Time elapsed = " << GetTime() << " sec)" << endl; + +/* + ofstream dbg("OpenFOAMDebug.log"); + + dbg << " ------- Boundary List -------- " << endl; + + for(int i = 1; i <= OF15x_surfelem_bclist.Size(); i++) + { + dbg << "bc = " << OF15x_surfelem_bclist.Elem(i) + << " : face = " << OF15x_surfelem_facelist.Elem(i) + << " : cell = " << OF15x_surfelem_celllist.Elem(i) << endl; + } + + dbg << endl << " ------- Owner List ------- " << endl; + + for(int i = 1; i <= OF15x_owner_celllist.Size(); i++) + { + dbg << "Ind:" << i << " :: (" + << OF15x_owner_celllist.Elem(i) << " " + << OF15x_owner_facelist.Elem(i) << ")" << endl; + } + + dbg << endl << " ----- Neighbour List ----- " << endl; + + for(int i = 1; i <= OF15x_neighbour_celllist.Size(); i++) + { + dbg << "Ind:" << i << " :: (" + << OF15x_neighbour_celllist.Elem(i) << " " + << OF15x_neighbour_facelist.Elem(i) << ")" << endl; + } + + dbg.close(); +*/ + } + + + + void WriteOpenFOAM15xNeighbour (ofstream & outfile) + { + // Write the OpenFOAM standard banner and dividers, etc... + WriteOpenFOAM15xBanner(outfile); + outfile << "FoamFile \n" + << "{ \n" + << " version 2.0; \n" + << " format ascii; \n" + << " class labelList; \n" + << " location \"constant\\polyMesh\"; \n" + << " object neighbour; \n" + << "} \n"; + WriteOpenFOAM15xDividerStart(outfile); + + outfile << endl << endl; + + int nneighbours = OF15x_neighbour_celllist.Size(); + + outfile << nneighbours << endl; + + outfile << "(" << endl; + + // Write the neighbour cells to file + for(int i = 1; i <= OF15x_neighbour_celllist.Size(); i++) + { + outfile << OF15x_neighbour_celllist.Elem(i) - 1 << endl; + } + outfile << ")" << endl << endl; + WriteOpenFOAM15xDividerEnd(outfile); + } + + + + void WriteOpenFOAM15xOwner (ofstream & outfile) + { + // Write the OpenFOAM standard banner and dividers, etc... + WriteOpenFOAM15xBanner(outfile); + outfile << "FoamFile \n" + << "{ \n" + << " version 2.0; \n" + << " format ascii; \n" + << " class labelList; \n" + << " location \"constant\\polyMesh\"; \n" + << " object owner; \n" + << "} \n"; + WriteOpenFOAM15xDividerStart(outfile); + + outfile << endl << endl; + + int nowners = OF15x_owner_celllist.Size() + OF15x_surfelem_celllist.Size(); + + outfile << nowners << endl; + + outfile << "(" << endl; + + // Write the owners of the internal cells to file + for(int i = 1; i <= OF15x_owner_celllist.Size(); i++) + { + outfile << OF15x_owner_celllist.Elem(i) - 1 << endl; + } + + // Write the owners of the boundary cells to file + // (Written in order of ascending boundary condition numbers) + for(int i = 1; i <= OF15x_surfelem_celllist.Size(); i++) + { + outfile << OF15x_surfelem_celllist.Elem(i) - 1 << endl; + } + outfile << ")" << endl << endl; + WriteOpenFOAM15xDividerEnd(outfile); + } + + + + void WriteOpenFOAM15xFaces (ofstream & outfile, const Mesh & mesh) + { + const_cast (mesh).BuildElementSearchTree(); + const MeshTopology& meshtopo = mesh.GetTopology(); + + // Update the mesh topology structures + const_cast (mesh).UpdateTopology(); + + + // Write the OpenFOAM standard banner and dividers, etc... + WriteOpenFOAM15xBanner(outfile); + outfile << "FoamFile \n" + << "{ \n" + << " version 2.0; \n" + << " format ascii; \n" + << " class faceList; \n" + << " location \"constant\\polyMesh\"; \n" + << " object faces; \n" + << "} \n"; + WriteOpenFOAM15xDividerStart(outfile); + + outfile << endl << endl; + + int nfaces = OF15x_owner_facelist.Size() + OF15x_surfelem_facelist.Size(); + + outfile << nfaces << endl; + + outfile << "(" << endl; + + // Write the faces in the order specified in the owners lists of the + // internal cells and the boundary cells + for(int i = 1; i <= OF15x_owner_facelist.Size(); i++) + { + int faceind = OF15x_owner_facelist.Elem(i); + + Array facepnts; + Array faces; + Array faceorient; + + meshtopo.GetElementFaces(OF15x_owner_celllist.Elem(i),faces,false); + meshtopo.GetElementFaceOrientations(OF15x_owner_celllist.Elem(i),faceorient); + + meshtopo.GetFaceVertices(faceind,facepnts); + + // Get the orientation of the face, and invert it if required + // for a quad, inversion => swap 1 <=> 2 and 3 <=> 4 + // for a trig, inversion => swap 1 <=> 3 + int orient = faceorient.Elem(faces.Pos(faceind)+1); + if(orient == 0 || orient == 3 || orient == 5 || orient == 6) + { + if(facepnts.Size() == 4) + { + int pnttmp = facepnts.Elem(1); + facepnts.Elem(1) = facepnts.Elem(2); + facepnts.Elem(2) = pnttmp; + + pnttmp = facepnts.Elem(3); + facepnts.Elem(3) = facepnts.Elem(4); + facepnts.Elem(4) = pnttmp; + } + else if(facepnts.Size() == 3) + { + int pnttmp = facepnts.Elem(1); + facepnts.Elem(1) = facepnts.Elem(3); + facepnts.Elem(3) = pnttmp; + } + } + + outfile << facepnts.Size(); + outfile << "("; + for(int j = 1; j <= facepnts.Size(); j++) + { + outfile << facepnts.Elem(j)-1; + if(j != facepnts.Size()) outfile << " "; + } + outfile << ")" << endl; + } + + for(int i = 1; i <= OF15x_surfelem_facelist.Size(); i++) + { + int faceind = OF15x_surfelem_facelist.Elem(i); + + Array facepnts; + Array faces; + Array faceorient; + + meshtopo.GetElementFaces(OF15x_surfelem_celllist.Elem(i),faces,false); + meshtopo.GetElementFaceOrientations(OF15x_surfelem_celllist.Elem(i),faceorient); + + meshtopo.GetFaceVertices(faceind,facepnts); + + // Get the orientation of the face, and invert it if required + // for a quad, inversion => swap 1 <=> 2 and 3 <=> 4 + // for a trig, inversion => swap 1 <=> 3 + int orient = faceorient.Elem(faces.Pos(faceind)+1); + if(orient == 0 || orient == 3 || orient == 5 || orient == 6) + { + if(facepnts.Size() == 4) + { + int pnttmp = facepnts.Elem(1); + facepnts.Elem(1) = facepnts.Elem(2); + facepnts.Elem(2) = pnttmp; + + pnttmp = facepnts.Elem(3); + facepnts.Elem(3) = facepnts.Elem(4); + facepnts.Elem(4) = pnttmp; + } + else if(facepnts.Size() == 3) + { + int pnttmp = facepnts.Elem(1); + facepnts.Elem(1) = facepnts.Elem(3); + facepnts.Elem(3) = pnttmp; + } + } + + outfile << facepnts.Size(); + outfile << "("; + for(int j = 1; j <= facepnts.Size(); j++) + { + outfile << facepnts.Elem(j)-1; + if(j != facepnts.Size()) outfile << " "; + } + outfile << ")" << endl; + } + + outfile << ")" << endl << endl; + WriteOpenFOAM15xDividerEnd(outfile); + } + + + + void WriteOpenFOAM15xPoints (ofstream & outfile, const Mesh & mesh) + { + int np = mesh.GetNP(); + + // Write the OpenFOAM standard banner and dividers, etc... + WriteOpenFOAM15xBanner(outfile); + outfile << "FoamFile \n" + << "{ \n" + << " version 2.0; \n" + << " format ascii; \n" + << " class vectorField; \n" + << " location \"constant\\polyMesh\"; \n" + << " object points; \n" + << "} \n"; + WriteOpenFOAM15xDividerStart(outfile); + + outfile << endl << endl; + + // Number of points in the following list + outfile << np << endl; + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + // Coordinate list starts here + outfile << "(" << endl; + + for(int i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + // Write coordinates to file + outfile << "("; + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z(); + outfile << ")" << endl; + } + outfile << ")" << endl << endl; + WriteOpenFOAM15xDividerEnd(outfile); + } + + + + void WriteOpenFOAM15xBoundary (ofstream & outfile) + { + // Write the OpenFOAM standard banner and dividers, etc... + WriteOpenFOAM15xBanner(outfile); + outfile << "FoamFile \n" + << "{ \n" + << " version 2.0; \n" + << " format ascii; \n" + << " class polyBoundaryMesh; \n" + << " location \"constant\\polyMesh\"; \n" + << " object boundary; \n" + << "} \n"; + WriteOpenFOAM15xDividerStart(outfile); + + outfile << endl; + + + Array bcarray; + int ind = 1; + + bcarray.Append(INDEX_3(OF15x_surfelem_bclist.Elem(1),1,0)); + + for(int i = 2; i <= OF15x_surfelem_bclist.Size(); i++) + { + if(OF15x_surfelem_bclist.Elem(i) == bcarray.Elem(ind).I1()) + { + bcarray.Elem(ind).I2() = bcarray.Elem(ind).I2()+1; + } + else + { + ind++; + bcarray.Append(INDEX_3(OF15x_surfelem_bclist.Elem(i),1,i-1)); + } + } + + outfile << bcarray.Size() << endl; + outfile << "(" << endl; + + int startface = 0; + + for(int i = 1; i <= bcarray.Size(); i++) + { + startface = OF15x_owner_celllist.Size() + bcarray.Elem(i).I3(); + + outfile << " patch" << bcarray.Elem(i).I1() << endl + << " {" << endl + << " type patch;" << endl + << " physicalType patch;" << endl + << " nFaces " << bcarray.Elem(i).I2() << ";" << endl + << " startFace " << startface << ";" << endl + << " }" << endl; + } + + outfile << ")" << endl << endl; + WriteOpenFOAM15xDividerEnd(outfile); + } + + + + void WriteOpenFOAM15xFormat (const Mesh & mesh, const string & casename) + { + int i,j; + bool error = false; + char casefiles[256]; + + int np = mesh.GetNP(); + int nse = mesh.GetNSE(); + int ne = mesh.GetNE(); + + cout << "Write OpenFOAM 1.5+ Mesh Files...." << endl; + + // Abort if there are no points, surface elements or volume elements + if((np <= 0) || (ne <= 0) || (nse <= 0)) + { + cout << "Export Error: Invalid mesh.... Aborting!" << endl; + return; + } + + // OpenFOAM only supports linear meshes! + if(mparam.secondorder) + { + cout << "Export Error: OpenFOAM 1.5+ does not support non-linear elements.... Aborting!" << endl; + return; + } + + cout << "Writing OpenFOAM 1.5+ Mesh files to case: " << casename << endl; + + // Create the Case directory if it does not already exist + #ifdef WIN32 + char casedir[256]; + sprintf(casedir, "mkdir %s\\constant\\polyMesh", casename.c_str()); + system(casedir); + #else + char casedir[256]; + sprintf(casedir, "mkdir -p %s/constant/polyMesh", casename.c_str()); + mkdir(casedir, S_IRWXU|S_IRWXG); + #endif + + // Open handles to the five required mesh files + // points + // faces + // owner + // neighbour + // boundary + sprintf(casefiles, "%s/constant/polyMesh/points", casename.c_str()); + ofstream outfile_pnts(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/faces", casename.c_str()); + ofstream outfile_faces(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/owner", casename.c_str()); + ofstream outfile_own(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/neighbour", casename.c_str()); + ofstream outfile_nei(casefiles); + sprintf(casefiles, "%s/constant/polyMesh/boundary", casename.c_str()); + ofstream outfile_bnd(casefiles); + + // Build the owner, neighbour, faces and boundary lists + // from the Netgen mesh + BuildOpenFOAM15xLists(mesh); + + + // Write the "points" file + if(outfile_pnts.good() && !error) + { + cout << "Writing the points file: "; + WriteOpenFOAM15xPoints(outfile_pnts,mesh); + outfile_pnts.close(); + cout << "Done!" << endl; + } + else + { + cout << "Export Error: Error creating file: points.... Aborting" << endl; + error = true; + } + + + // Write the "owner" file + if(outfile_own.good() && !error) + { + cout << "Writing the owner file: "; + WriteOpenFOAM15xOwner(outfile_own); + outfile_own.close(); + cout << "Done!" << endl; + } + else + { + cout << "Export Error: Error creating file: owner.... Aborting" << endl; + error = true; + } + + + // Write the "neighbour" file + if(outfile_nei.good() && !error) + { + cout << "Writing the neighbour file: "; + WriteOpenFOAM15xNeighbour(outfile_nei); + outfile_nei.close(); + cout << "Done!" << endl; + } + else + { + cout << "Export Error: Error creating file: neighbour.... Aborting" << endl; + error = true; + } + + + // Write the "faces" file + if(outfile_faces.good() && !error) + { + cout << "Writing the faces file: "; + WriteOpenFOAM15xFaces(outfile_faces, mesh); + outfile_faces.close(); + cout << "Done!" << endl; + } + else + { + cout << "Export Error: Error creating file: faces.... Aborting" << endl; + error = true; + } + + + // Write the "boundary" file + if(outfile_bnd.good() && !error) + { + cout << "Writing the boundary file: "; + WriteOpenFOAM15xBoundary(outfile_bnd); + outfile_bnd.close(); + cout << "Done!" << endl; + } + else + { + cout << "Export Error: Error creating file: boundary.... Aborting" << endl; + error = true; + } + + if(!error) + { + cout << "OpenFOAM 1.5+ Export successfully completed!" << endl; + } + else + { + cout << "Error in OpenFOAM 1.5+ Export.... Aborted!" << endl; + } + } +} + diff --git a/libsrc/interface/writegmsh2.cpp b/libsrc/interface/writegmsh2.cpp index 31452ddd..5ec3dc8f 100644 --- a/libsrc/interface/writegmsh2.cpp +++ b/libsrc/interface/writegmsh2.cpp @@ -1,261 +1,261 @@ -/*! \file writegmsh2.cpp - * \brief Export Netgen Mesh in the GMSH v2.xx File format - * \author Philippose Rajan - * \date 02 November 2008 - * - * This function extends the export capabilities of - * Netgen to include the GMSH v2.xx File Format. - * - * Current features of this function include: - * - * 1. Exports Triangles, Quadrangles and Tetrahedra \n - * 2. Supports upto second order elements of each type - * - */ - - -#include - -#include -#include -#include -#include - -namespace netgen -{ -#include "writeuser.hpp" - -// Mapping of entities from Netgen definitions to GMSH definitions -enum GMSH_ELEMENTS {GMSH_TRIG = 2, GMSH_TRIG6 = 9, - GMSH_QUAD = 3, GMSH_QUAD8 = 16, - GMSH_TET = 4, GMSH_TET10 = 11}; -const int triGmsh[7] = {0,1,2,3,6,4,5}; -const int quadGmsh[9] = {0,1,2,3,4,5,8,6,7}; -const int tetGmsh[11] = {0,1,2,3,4,5,8,6,7,10,9}; - - -/*! GMSH v2.xx mesh format export function - * - * This function extends the export capabilities of - * Netgen to include the GMSH v2.xx File Format. - * - * Current features of this function include: - * - * 1. Exports Triangles, Quadrangles and Tetrahedra \n - * 2. Supports upto second order elements of each type - * - */ -void WriteGmsh2Format (const Mesh & mesh, - const CSGeometry & geom, - const string & filename) -{ - ofstream outfile (filename.c_str()); - outfile.precision(6); - outfile.setf (ios::fixed, ios::floatfield); - outfile.setf (ios::showpoint); - - int np = mesh.GetNP(); /// number of points in mesh - int ne = mesh.GetNE(); /// number of 3D elements in mesh - int nse = mesh.GetNSE(); /// number of surface elements (BC) - int i, j, k, l; - - - /* - * 3D section : Volume elements (currently only tetrahedra) - */ - - if ((ne > 0) - && (mesh.VolumeElement(1).GetNP() <= 10) - && (mesh.SurfaceElement(1).GetNP() <= 6)) - { - cout << "Write GMSH v2.xx Format \n"; - cout << "The GMSH v2.xx export is currently available for elements upto 2nd Order\n" << endl; - - int inverttets = mparam.inverttets; - int invertsurf = mparam.inverttrigs; - - /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) - outfile << "$MeshFormat\n"; - outfile << (float)2.0 << " " - << (int)0 << " " - << (int)sizeof(double) << "\n"; - outfile << "$EndMeshFormat\n"; - - /// Write nodes - outfile << "$Nodes\n"; - outfile << np << "\n"; - - for (i = 1; i <= np; i++) - { - const Point3d & p = mesh.Point(i); - outfile << i << " "; /// node number - outfile << p.X() << " "; - outfile << p.Y() << " "; - outfile << p.Z() << "\n"; - } - - outfile << "$EndNodes\n"; - - /// write elements (both, surface elements and volume elements) - outfile << "$Elements\n"; - outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC - - for (i = 1; i <= nse; i++) - { - int elType = 0; - - Element2d el = mesh.SurfaceElement(i); - if(invertsurf) el.Invert(); - - if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle - if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle - if(elType == 0) - { - cout << " Invalid surface element type for Gmsh 2.0 3D-Mesh Export Format !\n"; - return; - } - - outfile << i; - outfile << " "; - outfile << elType; - outfile << " "; - outfile << "2"; //// Number of tags (2 => Physical and elementary entities) - outfile << " "; - outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; - /// that means that physical entity = elementary entity (arbitrary approach) - outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; - for (j = 1; j <= el.GetNP(); j++) - { - outfile << " "; - outfile << el.PNum(triGmsh[j]); - } - outfile << "\n"; - } - - - for (i = 1; i <= ne; i++) - { - int elType = 0; - - Element el = mesh.VolumeElement(i); - if (inverttets) el.Invert(); - - if(el.GetNP() == 4) elType = GMSH_TET; //// GMSH Element type for 4 node tetrahedron - if(el.GetNP() == 10) elType = GMSH_TET10; //// GMSH Element type for 10 node tetrahedron - if(elType == 0) - { - cout << " Invalid volume element type for Gmsh 2.0 3D-Mesh Export Format !\n"; - return; - } - - outfile << nse + i; //// element number (Remember to add on surface elements) - outfile << " "; - outfile << elType; - outfile << " "; - outfile << "2"; //// Number of tags (2 => Physical and elementary entities) - outfile << " "; - outfile << 100000 + el.GetIndex(); - /// that means that physical entity = elementary entity (arbitrary approach) - outfile << " "; - outfile << 100000 + el.GetIndex(); /// volume number - outfile << " "; - for (j = 1; j <= el.GetNP(); j++) - { - outfile << " "; - outfile << el.PNum(tetGmsh[j]); - } - outfile << "\n"; - } - outfile << "$EndElements\n"; - } - /* - * End of 3D section - */ - - - /* - * 2D section : available for triangles and quadrangles - * upto 2nd Order - */ - else if(ne == 0) /// means that there's no 3D element - { - cout << "\n Write Gmsh v2.xx Surface Mesh (triangle and/or quadrangles upto 2nd Order)" << endl; - - /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) - outfile << "$MeshFormat\n"; - outfile << (float)2.0 << " " - << (int)0 << " " - << (int)sizeof(double) << "\n"; - outfile << "$EndMeshFormat\n"; - - /// Write nodes - outfile << "$Nodes\n"; - outfile << np << "\n"; - - for (i = 1; i <= np; i++) - { - const Point3d & p = mesh.Point(i); - outfile << i << " "; /// node number - outfile << p.X() << " "; - outfile << p.Y() << " "; - outfile << p.Z() << "\n"; - } - outfile << "$EndNodes\n"; - - /// write triangles & quadrangles - outfile << "$Elements\n"; - outfile << nse << "\n"; - - for (k = 1; k <= nse; k++) - { - int elType = 0; - - const Element2d & el = mesh.SurfaceElement(k); - - if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle - if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle - if(el.GetNP() == 4) elType = GMSH_QUAD; //// GMSH Type for a 4 node quadrangle - if(el.GetNP() == 8) elType = GMSH_QUAD8; //// GMSH Type for an 8 node quadrangle - if(elType == 0) - { - cout << " Invalid surface element type for Gmsh 2.0 2D-Mesh Export Format !\n"; - return; - } - - outfile << k; - outfile << " "; - outfile << elType; - outfile << " "; - outfile << "2"; - outfile << " "; - outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; - /// that means that physical entity = elementary entity (arbitrary approach) - outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; - for (l = 1; l <= el.GetNP(); l++) - { - outfile << " "; - if((elType == GMSH_TRIG) || (elType == GMSH_TRIG6)) - { - outfile << el.PNum(triGmsh[l]); - } - else if((elType == GMSH_QUAD) || (elType == GMSH_QUAD8)) - { - outfile << el.PNum(quadGmsh[l]); - } - } - outfile << "\n"; - } - outfile << "$EndElements\n"; - } - /* - * End of 2D section - */ - - else - { - cout << " Invalid element type for Gmsh v2.xx Export Format !\n"; - } -} // End: WriteGmsh2Format -} // End: namespace netgen - - +/*! \file writegmsh2.cpp +* \brief Export Netgen Mesh in the GMSH v2.xx File format +* \author Philippose Rajan +* \date 02 November 2008 +* +* This function extends the export capabilities of +* Netgen to include the GMSH v2.xx File Format. +* +* Current features of this function include: +* +* 1. Exports Triangles, Quadrangles and Tetrahedra \n +* 2. Supports upto second order elements of each type +* +*/ + + +#include + +#include +#include +#include +#include + +namespace netgen +{ +#include "writeuser.hpp" + + // Mapping of entities from Netgen definitions to GMSH definitions + enum GMSH_ELEMENTS {GMSH_TRIG = 2, GMSH_TRIG6 = 9, + GMSH_QUAD = 3, GMSH_QUAD8 = 16, + GMSH_TET = 4, GMSH_TET10 = 11}; + const int triGmsh[7] = {0,1,2,3,6,4,5}; + const int quadGmsh[9] = {0,1,2,3,4,5,8,6,7}; + const int tetGmsh[11] = {0,1,2,3,4,5,8,6,7,10,9}; + + + /*! GMSH v2.xx mesh format export function + * + * This function extends the export capabilities of + * Netgen to include the GMSH v2.xx File Format. + * + * Current features of this function include: + * + * 1. Exports Triangles, Quadrangles and Tetrahedra \n + * 2. Supports upto second order elements of each type + * + */ + void WriteGmsh2Format (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) + { + ofstream outfile (filename.c_str()); + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + int np = mesh.GetNP(); /// number of points in mesh + int ne = mesh.GetNE(); /// number of 3D elements in mesh + int nse = mesh.GetNSE(); /// number of surface elements (BC) + int i, j, k, l; + + + /* + * 3D section : Volume elements (currently only tetrahedra) + */ + + if ((ne > 0) + && (mesh.VolumeElement(1).GetNP() <= 10) + && (mesh.SurfaceElement(1).GetNP() <= 6)) + { + cout << "Write GMSH v2.xx Format \n"; + cout << "The GMSH v2.xx export is currently available for elements upto 2nd Order\n" << endl; + + int inverttets = mparam.inverttets; + int invertsurf = mparam.inverttrigs; + + /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) + outfile << "$MeshFormat\n"; + outfile << (float)2.0 << " " + << (int)0 << " " + << (int)sizeof(double) << "\n"; + outfile << "$EndMeshFormat\n"; + + /// Write nodes + outfile << "$Nodes\n"; + outfile << np << "\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + outfile << i << " "; /// node number + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << "\n"; + } + + outfile << "$EndNodes\n"; + + /// write elements (both, surface elements and volume elements) + outfile << "$Elements\n"; + outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC + + for (i = 1; i <= nse; i++) + { + int elType = 0; + + Element2d el = mesh.SurfaceElement(i); + if(invertsurf) el.Invert(); + + if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle + if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle + if(elType == 0) + { + cout << " Invalid surface element type for Gmsh 2.0 3D-Mesh Export Format !\n"; + return; + } + + outfile << i; + outfile << " "; + outfile << elType; + outfile << " "; + outfile << "2"; //// Number of tags (2 => Physical and elementary entities) + outfile << " "; + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + /// that means that physical entity = elementary entity (arbitrary approach) + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile << el.PNum(triGmsh[j]); + } + outfile << "\n"; + } + + + for (i = 1; i <= ne; i++) + { + int elType = 0; + + Element el = mesh.VolumeElement(i); + if (inverttets) el.Invert(); + + if(el.GetNP() == 4) elType = GMSH_TET; //// GMSH Element type for 4 node tetrahedron + if(el.GetNP() == 10) elType = GMSH_TET10; //// GMSH Element type for 10 node tetrahedron + if(elType == 0) + { + cout << " Invalid volume element type for Gmsh 2.0 3D-Mesh Export Format !\n"; + return; + } + + outfile << nse + i; //// element number (Remember to add on surface elements) + outfile << " "; + outfile << elType; + outfile << " "; + outfile << "2"; //// Number of tags (2 => Physical and elementary entities) + outfile << " "; + outfile << 100000 + el.GetIndex(); + /// that means that physical entity = elementary entity (arbitrary approach) + outfile << " "; + outfile << 100000 + el.GetIndex(); /// volume number + outfile << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile << el.PNum(tetGmsh[j]); + } + outfile << "\n"; + } + outfile << "$EndElements\n"; + } + /* + * End of 3D section + */ + + + /* + * 2D section : available for triangles and quadrangles + * upto 2nd Order + */ + else if(ne == 0) /// means that there's no 3D element + { + cout << "\n Write Gmsh v2.xx Surface Mesh (triangle and/or quadrangles upto 2nd Order)" << endl; + + /// Prepare GMSH 2.0 file (See GMSH 2.0 Documentation) + outfile << "$MeshFormat\n"; + outfile << (float)2.0 << " " + << (int)0 << " " + << (int)sizeof(double) << "\n"; + outfile << "$EndMeshFormat\n"; + + /// Write nodes + outfile << "$Nodes\n"; + outfile << np << "\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + outfile << i << " "; /// node number + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << "\n"; + } + outfile << "$EndNodes\n"; + + /// write triangles & quadrangles + outfile << "$Elements\n"; + outfile << nse << "\n"; + + for (k = 1; k <= nse; k++) + { + int elType = 0; + + const Element2d & el = mesh.SurfaceElement(k); + + if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle + if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle + if(el.GetNP() == 4) elType = GMSH_QUAD; //// GMSH Type for a 4 node quadrangle + if(el.GetNP() == 8) elType = GMSH_QUAD8; //// GMSH Type for an 8 node quadrangle + if(elType == 0) + { + cout << " Invalid surface element type for Gmsh 2.0 2D-Mesh Export Format !\n"; + return; + } + + outfile << k; + outfile << " "; + outfile << elType; + outfile << " "; + outfile << "2"; + outfile << " "; + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + /// that means that physical entity = elementary entity (arbitrary approach) + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + for (l = 1; l <= el.GetNP(); l++) + { + outfile << " "; + if((elType == GMSH_TRIG) || (elType == GMSH_TRIG6)) + { + outfile << el.PNum(triGmsh[l]); + } + else if((elType == GMSH_QUAD) || (elType == GMSH_QUAD8)) + { + outfile << el.PNum(quadGmsh[l]); + } + } + outfile << "\n"; + } + outfile << "$EndElements\n"; + } + /* + * End of 2D section + */ + + else + { + cout << " Invalid element type for Gmsh v2.xx Export Format !\n"; + } + } // End: WriteGmsh2Format +} // End: namespace netgen + + diff --git a/libsrc/interface/writeuser.cpp b/libsrc/interface/writeuser.cpp index 7f884b1a..71c91afb 100644 --- a/libsrc/interface/writeuser.cpp +++ b/libsrc/interface/writeuser.cpp @@ -35,6 +35,7 @@ namespace netgen "VRML Format", ".*", "Gmsh Format", ".gmsh", "Gmsh2 Format", ".gmsh2", + "OpenFOAM 1.5+ Format", "*", "JCMwave Format", ".jcm", "TET Format", ".tet", // { "Chemnitz Format" }, @@ -108,10 +109,15 @@ bool WriteUserFormat (const string & format, WriteGmshFormat (mesh, geom, filename); // Philippose - 29/01/2009 - // Added Gmsh v2.xx export capability + // Added Gmsh v2.xx Mesh export capability else if (format == "Gmsh2 Format") WriteGmsh2Format (mesh, geom, filename); + // Philippose - 25/10/2009 + // Added OpenFOAM 1.5+ Mesh export capability + else if (format == "OpenFOAM 1.5+ Format") + WriteOpenFOAM15xFormat (mesh, filename); + else if (format == "JCMwave Format") WriteJCMFormat (mesh, geom, filename); diff --git a/libsrc/interface/writeuser.hpp b/libsrc/interface/writeuser.hpp index f9b5e9fc..b9fc9869 100644 --- a/libsrc/interface/writeuser.hpp +++ b/libsrc/interface/writeuser.hpp @@ -10,17 +10,17 @@ extern void WriteFile (int typ, - const Mesh & mesh, - const CSGeometry & geom, - const char * filename, - const char * geomfile = NULL, - double h = 0); + const Mesh & mesh, + const CSGeometry & geom, + const char * filename, + const char * geomfile = NULL, + double h = 0); extern void ReadFile (Mesh & mesh, - const string & filename); + const string & filename); @@ -29,43 +29,50 @@ void ReadFile (Mesh & mesh, extern void WriteNeutralFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); extern void WriteSurfaceFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteSTLFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteVRMLFormat (const Mesh & mesh, - bool faces, - const string & filename); + bool faces, + const string & filename); extern void WriteFEPPFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); extern void WriteGmshFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); // Philippose - 29/01/2009 // Added GMSH v2.xx Mesh Export support void WriteGmsh2Format (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); + + +// Philippose - 25/10/2009 +// Added OpenFOAM 1.5+ Mesh Export support +extern +void WriteOpenFOAM15xFormat (const Mesh & mesh, + const string & casename); extern void WriteUserChemnitz (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteJCMFormat (const Mesh & mesh, @@ -75,55 +82,55 @@ void WriteJCMFormat (const Mesh & mesh, extern void WriteDiffPackFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); extern void WriteTochnogFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteTecPlotFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); extern void WriteAbaqusFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteFluentFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WritePermasFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteFEAPFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteElmerFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void WriteEdgeElementFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename); + const CSGeometry & geom, + const string & filename); #ifdef OLIVER extern void WriteTETFormat (const Mesh & mesh, - const string & filename); + const string & filename); #endif extern void ReadTETFormat (Mesh & mesh, - const string & filename); + const string & filename); extern void ReadFNFFormat (Mesh & mesh, @@ -132,20 +139,17 @@ extern void ReadFNFFormat (Mesh & mesh, void WriteDolfinFormat (const Mesh & mesh, - const string & filename); + const string & filename); extern void RegisterUserFormats (Array & names, - Array & extensions); + Array & extensions); extern bool WriteUserFormat (const string & format, - const Mesh & mesh, - const CSGeometry & geom, - const string & filename); - - - + const Mesh & mesh, + const CSGeometry & geom, + const string & filename); #endif diff --git a/ng/menustat.tcl b/ng/menustat.tcl index 3a596a97..b0451b79 100644 --- a/ng/menustat.tcl +++ b/ng/menustat.tcl @@ -144,7 +144,8 @@ loadinifile; Ng_SetVisParameters redraw Ng_ReadStatus; -# Ng_MeshSizeFromSurfaceMesh +# Ng_MeshSizeFromSurfaceMesh + wm title . [concat "$progname - " $file] set dirname [file dirname $file] set basefilename [file tail [file rootname $file]] } @@ -243,8 +244,8 @@ loadmeshinifile; } } - if { $exportfiletype == "Elmer Format" } { - set file [tk_chooseDirectory] + if { $exportfiletype == "Elmer Format" || $exportfiletype == "OpenFOAM 1.5+ Format"} { + set file [file nativename [tk_chooseDirectory]] } else { # set file [tk_getSaveFile -filetypes "{ \"$exportfiletype\" {$extension} }" ] set file [tk_getSaveFile -filetypes "{ \"$exportfiletype\" {*}}" ] @@ -866,7 +867,12 @@ button .bubar.surfm -text "Generate Mesh" -command \ button .bubar.stopm -text "Stop" -command \ { Ng_StopMeshing; set stopdemo 1 } button .bubar.exitb -text "Quit" \ - -command { .ngmenu.file invoke "Quit" } + -command { + set ans [tk_messageBox -title "Quit Netgen?" -message "Do you really want to quit Netgen?" -type yesno -default "no" -icon question] + if { $ans == "yes" } { + .ngmenu.file invoke "Quit"; + } + } pack .bubar.exitb .bubar.surfm .bubar.stopm -side left #button .bubar.scan -text "Scan" \ diff --git a/windows/netgen.vcproj b/windows/netgen.vcproj index 04dc8527..89174cc7 100644 --- a/windows/netgen.vcproj +++ b/windows/netgen.vcproj @@ -920,11 +920,11 @@ > + +