/*********************************************************************** * * ELMER, A Computational Fluid Dynamics Program. * * Copyright 1st April 1995 - , Center for Scientific Computing, * Finland. * * All rights reserved. No part of this program may be used, * reproduced or transmitted in any form or by any means * without the written permission of CSC. * * Address: Center for Scientific Computing * Tietotie 6, P.O. BOX 405 * 02101 Espoo, Finland * Tel. +358 0 457 2001 * Telefax: +358 0 457 2302 * EMail: Jari.Jarvinen@csc.fi ************************************************************************/ /*********************************************************************** Program: ELMER Front Module: ecif_inputThetis.cpp Language: C++ Date: 01.10.98 Version: 1.00 Author(s): Martti Verho Revisions: Abstract: Implementation ************************************************************************/ #include "ecif_bodyElement.h" #include "ecif_control.h" #include "ecif_geometry.h" #include "ecif_inputThetis.h" #include "ecif_model.h" #include "ecif_userinterface.h" #include "ecif_timer.h" extern char read_buffer[]; InputThetis::InputThetis(enum ecif_modelDimension m_dim, ifstream& in_file, char* in_filename): Input(m_dim, in_file, in_filename) { } enum ecif_modelDimension InputThetis::findModelDimension(ifstream& in_file) { return modelDimension; } //---Create and update mesh tables bool InputThetis::processMeshFileData() { Timer timer; double time, time1, time2; UserInterface* gui = theControlCenter->getGui(); MeshElementTable* bt = model->getMeshBulkElements(); MeshElementTable* bet = model->getMeshBoundaryElements(); //---Create BULK element connections (neighor ids, sub element indices timer.start(); time1 = 0; gui->showMsg("---Creating volume element connections ..."); time2 = timer.getLapTime(WALL_TIME); time = time2 - time1; time1 = time2; gui->showUsedTimeMsg(time, "---Creating volume element connections", (short)0, false); //---Create bulk element edges model->createMeshBulkElementEdges(); //---Find mesh boundary element neighbors model->findMeshElementNeighbors(bet); //---Create boundary element edges model->createMeshBoundaryElementEdges(); //---Finish timer.stop(); time = timer.getEndTime(WALL_TIME); gui->showUsedTimeMsg(time, "Creating mesh bodies and boundaries", 1, true); return modelDimension; } // Read nodes and elements from the Thetis Mesh File (.tmf) bool InputThetis::readMeshGeometry() { int i; int nofNodes, nofElements; int nofBodies; int nofBoundaries; int nofBoundaryElements; // Fem elements Rc rc; // Read header information readFileLine(infile, read_buffer); istrstream strmline(read_buffer); if (! (strmline >> nofNodes >> maxExternalNodeId >> nofElements >> maxExternalElementId >> nofBodies >> nofBoundaries >> nofBoundaryElements ) ) { cerr << endl << "ERROR: in reading mesh header info in InputThetis::readMeshGeoemtry"; return false; } //---Allocate basic tables in the model model->allocateMeshBodies(nofBodies); model->allocateMeshNodes(nofNodes, maxExternalNodeId); model->allocateMeshInputElements(nofElements, maxExternalElementId); //---Read nodes from the mesh input file if ( ECIF_OK != readMeshNodes(nofNodes) ) return false; //---Read volume elements from the mesh input file // NOTE: model dimension known only after reading // volume elements if ( ECIF_OK != readMeshElements(nofElements) ) return false; //---Read all boundary elements from the mesh input file // NOTE: We cannot read Thetis boundary elements, because we do not know the // material (body id) for them, tehy must be created from bulk faces!!! // //if ( ECIF_OK != readMeshBoundaryElements(nofBoundaryElements) ) return false; model->setModelDimension(modelDimension); if (modelDimension == ECIF_ND) return false; model->setMeshNodes(); return true; } // Read a boundary element from the Thetis Mesh File and store it into the model. bool InputThetis::read_boundary() { UserInterface* gui = theControlCenter->getGui(); int i; bool result_code = true; int boundary_tag, external_body1_tag, external_body2_tag; int nof_bndr_elements; readFileLine(infile, read_buffer); istrstream strmline(read_buffer); if ( !(strmline >> boundary_tag >> external_body1_tag >> external_body2_tag >> nof_bndr_elements) ) { gui->errMsg(1, "could not read boundary data in InputThetis::read_boundaries()"); return false; } int body1_tag = model->getBodyTagExt2Int(external_body1_tag); int body2_tag = model->getBodyTagExt2Int(external_body2_tag); int body1_lr = 0; int body2_lr = 0; // Check if boundary is already stored (as a normal model boundary!) BodyElement* be; if ( model->getDimension() == ECIF_2D ) be = model->getEdgeByTag(boundary_tag); else be = model->getFaceByTag(boundary_tag); if (be != NULL) { be->allocateMeshElements(nof_bndr_elements); } else { model->createBodyElement(boundary_tag, body1_tag, body1_lr, body2_tag, body2_lr, nof_bndr_elements); } return result_code; } // Read a boundary element from the Thetis Mesh File and store it into the model. Rc InputThetis::readMeshBoundaryElements(int nof_bndr_elements) { UserInterface* gui = theControlCenter->getGui(); bool result_code = true; int sequence_nbr, bndr_tag; int ext_parent1_id, ext_parent2_id; int ext_body1_tag, ext_body2_tag; int elem_type, nof_nodes; meshElementCode elem_code; static int ext_node_ids[MAX_NOF_BNDR_NODES]; char* strm_buffer = new char[BUFFER_LEN]; strstream strm(strm_buffer, BUFFER_LEN, ios::app); short i; for (int index = 0; index < nof_bndr_elements; index++) { readFileLine(infile, read_buffer); reset(strm); strm << read_buffer << ends; if ( !(strm >> sequence_nbr >> bndr_tag >> ext_parent1_id >> ext_parent2_id >> ext_body1_tag >> ext_body2_tag >> elem_type ) ) { gui->errMsg(1, "could not read element data-1 in InputThetis::read_boundary_element()"); return ECIF_ERROR; } // Read nodes for the element (external ids!) if ( !(strm >> nof_nodes) ) { gui->errMsg(1, "could not read nof nodes per element in InputThetis::read_boundary_element()"); return ECIF_ERROR; } // NOTE: For boundary elements we have to convert id "manually", because // they where not yet available when createMeshBodyTables (which // converts bulk elem- and node-ids) was called for (i = 0; i < nof_nodes; i++) { if (!(strm >> ext_node_ids[i])) { gui->errMsg(1, "could not read nodeId in InputThetis::read_boundary_element()"); return ECIF_ERROR; } } // NOTE: We do not know the material id for the boundaries // so they cannot be actually added like this! // --> We do not read the boundary elements fromt the Thetis mesh file!!! model->addMeshInputElement(elem_type, index, NO_INDEX, bndr_tag, ext_node_ids); nofInputBoundaryElements++; } // for all boundary elements return ECIF_OK; } // Read an element from the Thetis Mesh File and store it into the model. Rc InputThetis::readMeshElements(int nof_elements) { UserInterface* gui = theControlCenter->getGui(); int external_id; int material_id; int elem_type; meshElementCode elem_code; int nof_nodes, nof_neighbors; static int ext_node_ids[27]; static int ext_neighbor_ids[27]; char* strm_buffer = new char[BUFFER_LEN]; strstream strm(strm_buffer, BUFFER_LEN, ios::app); short i; for (int index = 0; index < nof_elements; index++) { readFileLine(infile, read_buffer); reset(strm); strm << read_buffer << ends; // Read element ids and code if ( !(strm >> external_id >> material_id >> elem_type ) ) { gui->errMsg(1, "could not read element ids data in InputThetis::read_element()"); return ECIF_ERROR; } // Read nodes for the element if ( !(strm >> nof_nodes) ) { gui->errMsg(1, "could not read nof nodes per element in InputThetis::read_element()"); return ECIF_ERROR; } for (i = 0; i < nof_nodes; i++) { if ( !(strm >> ext_node_ids[i]) ) { gui->errMsg(1, "could not read nodeId in InputThetis::read_element()"); return ECIF_ERROR; } } // Read neigbour element for the element if ( !(strm >> nof_neighbors) ) { gui->errMsg(1, "could not read nof-neighbors in InputThetis::read_element()"); return ECIF_ERROR; } for (i = 0; i < nof_neighbors; i++) { if ( !(strm >> ext_neighbor_ids[i]) ) { gui->errMsg(1, "could not read neighborIds in InputThetis::read_element()"); return ECIF_ERROR; } } model->addMeshInputElement(elem_type, external_id, material_id, NO_INDEX, ext_node_ids); nofInputBulkElements++; } // for all elements //---Model dimension (based on the last element read!) if (elem_type > 200 && elem_type < 300) modelDimension = ECIF_1D; else if (elem_type > 300 && elem_type < 500) modelDimension = ECIF_2D; else if (elem_type > 500 && elem_type < 900) modelDimension = ECIF_3D; else modelDimension = ECIF_ND; return ECIF_OK; } // Read a node from the Thetis Mesh File and store it into the model Rc InputThetis::readMeshNodes(int nof_nodes) { UserInterface* gui = theControlCenter->getGui(); int external_id; static Point3 p; // Init point buffer p[0] = p[1] = p[2] = 0.0; char* strm_buffer = new char[BUFFER_LEN]; strstream strm(strm_buffer, BUFFER_LEN, ios::app); for (int index = 0; index < nof_nodes; index++) { readFileLine(infile, read_buffer); reset(strm); strm << read_buffer << ends; if ( !(strm >> external_id) ) { gui->errMsg(1, "could not NodeId in InputThetis::read_node()"); return ECIF_ERROR; } for (int i = 0; i < 3; i++) { if (!(strm >> p[i])) { gui->errMsg(1, "could not read node coordinates in InputThetis::read_node()"); return ECIF_ERROR; } } model->addMeshNode(index, external_id, p); } return ECIF_OK; }