/*********************************************************************** * * 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_bodyelement.cpp Language: C++ Date: 15.10.98 Version: 1.00 Author(s): Martti Verho Revisions: Abstract: Implementation ************************************************************************/ #include "ecif_body.h" #include "ecif_bodyElement.h" #include "ecif_bodyElement1D.h" #include "ecif_bodyElement2D.h" #include "ecif_bodyElement3D.h" #include "ecif_bodyElementLoop.h" #include "ecif_bodyElementGroup.h" #include "ecif_boundaryCondition.h" #include "ecif_geometry.h" #include "ecif_mesh.h" #include "ecif_model.h" #include "ecif_parameter.h" #include "ecif_renderer.h" #include "ecif_userinterface.h" //Initialize static class variables. int BodyElement::last_boundaryTag = 0; // BoundaryPoint struct // =================== BoundaryPoint::BoundaryPoint() { activeInMeshing = false; checked = false; tag = NO_INDEX; //boundaryTag = NO_INDEX; point = NULL; vertexTag = NO_INDEX; meshDensityType = ' '; meshDensityValue = 0.0; } BoundaryPoint::~BoundaryPoint() {}; void BoundaryPoint::copy(BoundaryPoint& other) { activeInMeshing = other.activeInMeshing; checked = other.checked; meshDensityType = other.meshDensityType; meshDensityValue = other.meshDensityValue; tag = other.tag; vertexTag = other.vertexTag; point->setPos(X, other.point->Pos(X)); point->setPos(Y, other.point->Pos(Y)); point->setPos(Z, other.point->Pos(Z)); } // GridHData struct // ============== BodyElementGridHData::BodyElementGridHData() { nofIds = 0; gridHIds = NULL; meshIndices = NULL; meshIndex = -1; hValueType = ' '; hValue = 0.0; } BodyElementGridHData::BodyElementGridHData(int nof_ids, int* grid_h_ids, int* mesh_indices) { nofIds = nof_ids; meshIndex = -1; hValueType = ' '; hValue = 0.0; if ( nofIds <= 0) return; gridHIds = new int[nofIds]; meshIndices = new int[nofIds]; for (int i = 0; i < nofIds; i++) { gridHIds[i] = grid_h_ids[i]; meshIndices[i] = mesh_indices[i]; } } BodyElementGridHData::~BodyElementGridHData() { delete[] gridHIds; delete[] meshIndices; } void BodyElementGridHData::setData(int nof_ids, int* grid_h_ids, int* mesh_indices, bool force) { int i; nofIds = nof_ids; // If directly set density values for the mesh already exist and parameters // are to be forced, delete direct definitions! for ( i = 0; i < nofIds; i++) { if ( mesh_indices[i] == meshIndex && force ) { meshIndex = -1; hValueType = ' '; hValue = 0.0; break; } } delete[] gridHIds; delete[] meshIndices; gridHIds = NULL; meshIndices = NULL; if ( nofIds <= 0) return; gridHIds = new int[nofIds]; meshIndices = new int[nofIds]; for (i = 0; i < nofIds; i++) { gridHIds[i] = grid_h_ids[i]; meshIndices[i] = mesh_indices[i]; } } void BodyElementGridHData::setData(int mesh_index, char value_type, double value, bool force) { int i; // If grid parameter for the mesh already exista and values // not to forced (overwrite), do nothing! for ( i = 0; i < nofIds; i++) { if ( meshIndices[i] == mesh_index && !force ) return; } meshIndex = mesh_index; hValueType = value_type; hValue = value; } // QuadGridData struct // =================== BodyElementQuadGridData::BodyElementQuadGridData() { nofIds = 0; meshIndices = NULL; nValues = NULL; } BodyElementQuadGridData::BodyElementQuadGridData(int nof_ids, int* mesh_indices, int* n_values) { nofIds = nof_ids; if ( nofIds <= 0) return; meshIndices = new int[nofIds]; nValues = new int[nofIds]; for (int i = 0; i < nofIds; i++) { meshIndices[i] = mesh_indices[i]; nValues[i] = n_values[i]; } } BodyElementQuadGridData::~BodyElementQuadGridData() { delete[] meshIndices; delete[] nValues; } void BodyElementQuadGridData::setData(int nof_ids, int* mesh_indices, int* n_values) { nofIds = nof_ids; delete[] meshIndices; delete[] nValues; meshIndices = NULL; nValues = NULL; if ( nofIds <= 0) return; meshIndices = new int[nofIds]; nValues = new int[nofIds]; for (int i = 0; i < nofIds; i++) { meshIndices[i] = mesh_indices[i]; nValues[i] = n_values[i]; } } // ModelData struct // ================ BodyElementModelData::BodyElementModelData() { status = 0; nofBoundaryPoints = 0; nofBoundaryPointsU = 0; nofBoundaryPointsV = 0; boundaryPoints = NULL; nofSubElements = 0; subElementIds = new IdArray; nofVertices = 0; vertexIds = new IdArray; code = 0; isClosedU = false; isClosedV = false; isIntraLayerBoundary = false; parent1Id = NO_INDEX; parent2Id = NO_INDEX; parent1Tag = NO_INDEX; parent2Tag = NO_INDEX; parent1Layer = NO_INDEX; parent2Layer = NO_INDEX; } BodyElementModelData::~BodyElementModelData() { deleteBoundaryPoints(); delete subElementIds; delete vertexIds; } void BodyElementModelData::deleteBoundaryPoints() { // In closed boundaries, start and end points // are same pointers ==> we cannot delete them twice!!! int nof_points_u = nofBoundaryPointsU; int nof_points_v = nofBoundaryPointsV; if ( isClosedU ) { nof_points_u--; } if ( isClosedV ) { nof_points_v--; } // Find nof-points to be deleted // ============================= int nof_points; if ( nof_points_v > 0 ) nof_points = nof_points_u * nof_points_v; else nof_points = nof_points_u; // Delete point coordinates (but not if original vertex!) // ============================================== for (int i = 0; i < nof_points; i++) { BoundaryPoint* bp = boundaryPoints[i]; // We can delete "internal" points, but NOT the original // vertex points!!! if ( !bp->isVertex() ) { delete bp->point; } delete bp; } // Delete table itself // =================== nofBoundaryPoints = 0; nofBoundaryPointsU = 0; nofBoundaryPointsV = 0; delete[] boundaryPoints; boundaryPoints = NULL; } // Return subelement tags int the buffer "element_tags" // NOTE: Buffer is allocated here, but each client should delete it! bool BodyElementModelData::getSubElementTags(Model* model, objectType sub_type, int& count, int*& element_tags) { count = 0; element_tags = NULL; if ( nofSubElements == 0 ) return false; int i; // Count sub-elements of proper type for (i = 0; i < nofSubElements; i++) { int element_id = (*subElementIds)[i]; BodyElement* se = model->getBodyElementById(element_id); if ( se != NULL && sub_type == se->getObjectType() ) { count++; } } element_tags = new int[count]; // Collect sub-element tags of proper type for (i = 0; i < nofSubElements; i++) { int element_id = (*subElementIds)[i]; BodyElement* se = model->getBodyElementById(element_id); if ( se != NULL && sub_type == se->getObjectType() ) { element_tags[i] = se->Tag(); } } return true; } // Return vertex tags int the buffer "vertex_tags" // NOTE: Buffer is allocated here, but each client should delete it! bool BodyElementModelData::getVertexTags(Model* model, int& count, int*& vertex_tags) { count = nofVertices; vertex_tags = NULL; if ( count == 0 ) return false; vertex_tags = new int[count]; for (int i = 0; i < count; i++) { int vertex_id = (*vertexIds)[i]; BodyElement* v = model->getVertexById(vertex_id); if ( v != NULL ) vertex_tags[i] = v->Tag(); else vertex_tags[i] = NO_INDEX; } return true; } // MeshData struct // =============== BodyElementMeshData::BodyElementMeshData() { maxNofMeshElements = 0; nofMeshElements = 0; meshElementIds = NULL; meshElementDirs = NULL; maxNofPendingMeshElements = 0; nofPendingMeshElements = 0; pendingMeshElementInfos = NULL; nofMeshSelectedElements = 0; nofMeshBorderElements = 0; meshBorderElementIds = NULL; meshBorderElementDirs = NULL; backupData = NULL; } BodyElementMeshData::~BodyElementMeshData() { delete[] meshElementIds; delete[] meshElementDirs; delete[] meshBorderElementIds; delete[] meshBorderElementDirs; for ( int i = 0; i < maxNofPendingMeshElements; i++) { delete[] pendingMeshElementInfos[i]; } delete[] pendingMeshElementInfos; delete backupData; } // MeshDataBackup struct // ===================== BodyElementMeshDataBackup::BodyElementMeshDataBackup() { nofMeshElements = 0; meshElementIds = NULL; meshElementDirs = NULL; nofMeshBorderElements = 0; meshBorderElementIds = NULL; meshBorderElementDirs = NULL; }; BodyElementMeshDataBackup::~BodyElementMeshDataBackup() { delete[] meshElementIds; delete[] meshElementDirs; delete[] meshBorderElementIds; delete[] meshBorderElementDirs; }; // ================= // BodyElement class // ================= BodyElement::BodyElement() { init(); } BodyElement::BodyElement(int int_tag) { tag = int_tag; init(); } BodyElement::BodyElement(int cd, char* nm) { init(); if ( modelData != NULL ) modelData->code = cd; update_dyna_string(name, nm); update_dyna_string(name_old, nm); } //-Create a bodyelement from a modelfile bodyelement BodyElement::BodyElement(ecif_Element_X& tx) { tag = tx.tag; init(); boundaryTag = tx.bndr_tag; checkLastBoundaryTag(); // NOTE: Boundary conditions are stored // finally in element groups // txBndrConditionId = tx.bndr_cond_id; boundaryParameterId = tx.bndr_param_id; elementGroupTag = tx.bndr_group_tag; if ( tx.nof_gridh_ids > 0 ) { gridHData = new BodyElementGridHData(tx.nof_gridh_ids, tx.gridh_ids, tx.gridh_mesh_indices); } } //-Create a bodyelement from a modelfile vertex BodyElement::BodyElement(ecif_Vertex_X& tx) { tag = tx.tag; init(); boundaryTag = tx.bndr_tag; elementGroupTag = tx.bndr_group_tag; checkLastBoundaryTag(); txBndrConditionId = tx.bndr_cond_id; if ( tx.nof_grid_h_ids > 0 ) { gridHData = new BodyElementGridHData(tx.nof_grid_h_ids, tx.grid_h_ids, tx.mesh_indices); } } // NOTE: ptrGmtr is deleted in the implementation // classes BodyElement3D ..., cause they know when to // delete and when not (those vertices...!!!) // BodyElement::~BodyElement() { delete[] name_old; } int BodyElement::addAllPendingMeshElements() { MeshInfo* mi = (MeshInfo*)model->getMeshInfo(); int element_count = 0; if ( getObjectType() != OT_EDGE || meshData == NULL || meshData->nofPendingMeshElements == 0 ) { return 0; } MeshElementTable* source = model->getMeshBoundaryElementEdges(); for ( int i = 0; i < meshData->nofPendingMeshElements; i++) { int* info = meshData->pendingMeshElementInfos[i]; int elem_code = info[0]; info++; int nof_nodes = MeshElementDesc[elem_code][DESC_NOF_NODES]; short dir, start; for ( int j = 0; j < source->NofElements(); j++) { if ( source->isSameElement(j, dir, start, elem_code, nof_nodes, info) ) { addMeshElement(j, dir); mi->nofUsedElementTypes[elem_code]++; element_count++; if ( element_count == meshData->nofPendingMeshElements ) { break; } } } if ( element_count == meshData->nofPendingMeshElements ) { break; } } return element_count; } // Add one mesh (fem) element id // Returns the internal index of the new mesh element int BodyElement::addMeshElement(int elem_id, short direction) { if ( meshData == NULL ) return 0; if (meshData->meshElementIds == NULL) allocateMeshElements(meshData->maxNofMeshElements); if (meshData->nofMeshElements == meshData->maxNofMeshElements) reallocateMeshElements(); meshData->meshElementDirs[meshData->nofMeshElements] = direction; meshData->meshElementIds[meshData->nofMeshElements] = elem_id; return meshData->nofMeshElements++; } int BodyElement::addPendingMeshElementAsNodes(int element_type, int* ext_node_ids) { if ( meshData == NULL ) return 0; if ( meshData->pendingMeshElementInfos == NULL ) allocatePendingMeshElementInfos(meshData->maxNofPendingMeshElements); if (meshData->nofPendingMeshElements == meshData->maxNofPendingMeshElements) reallocatePendingMeshElementInfos(); meshElementCode el_code = model->convertElementType(element_type); int nof_nodes = MeshElementDesc[el_code][DESC_NOF_NODES]; int* node_info = new int[1 + nof_nodes]; node_info[0] = el_code; for (int i = 0; i < nof_nodes; i++) { node_info[1 + i] = model->getMeshNodeIdExt2Int(ext_node_ids[i]); } int index = meshData->nofPendingMeshElements; meshData->pendingMeshElementInfos[index] = node_info; return ++meshData->nofPendingMeshElements; } beStatus BodyElement::addStatus(beStatus new_status) { if ( modelData == NULL ) return BE_NONE; else return modelData->status |= new_status; } // Add sublement ( Edge for a Face, Veretx for an Edge) int BodyElement::addSubElement(BodyElement* be) { return addSubElement(be->Id()); } // Add sublement ( Edge for a Face, Vertex for an Edge) int BodyElement::addSubElement(int sub_id) { if ( modelData == NULL ) return NO_INDEX; if ( modelData->subElementIds->size() == 0 || (int)NULL == (*(modelData->subElementIds))[sub_id] ) { modelData->subElementIds->push_back(sub_id); modelData->nofSubElements++; } // Return index for the element, so that // clients can use it return modelData->nofSubElements - 1; } // Allocate space for fem elements void BodyElement::allocateMeshElements(int nof_elements) { delete[] meshData->meshElementDirs; meshData->meshElementDirs = NULL; delete[] meshData->meshElementIds; meshData->meshElementIds = NULL; if (nof_elements > 0) { meshData->meshElementDirs = new short[nof_elements]; meshData->meshElementIds = new int[nof_elements]; } meshData->maxNofMeshElements = nof_elements; // No elements stored yet! meshData->nofMeshElements = 0; } // Allocate space for pending fem element infos void BodyElement::allocatePendingMeshElementInfos(int nof_infos) { delete[] meshData->pendingMeshElementInfos; meshData->pendingMeshElementInfos = NULL; if (nof_infos > 0) { meshData->pendingMeshElementInfos = new int*[nof_infos]; for (int i = 0; i < nof_infos; i++) { meshData->pendingMeshElementInfos[i] = NULL; } } meshData->maxNofPendingMeshElements = nof_infos; // No infos stored yet! meshData->nofPendingMeshElements = 0; } void BodyElement::backupMeshData() { if ( meshData == NULL ) return; meshData->backupData = new BodyElementMeshDataBackup; int i; //--Mesh elements meshData->backupData->nofMeshElements = meshData->nofMeshElements; meshData->backupData->meshElementIds = new int[meshData->nofMeshElements]; meshData->backupData->meshElementDirs = new short[meshData->nofMeshElements]; for (i = 0; i < meshData->nofMeshElements; i++) { meshData->backupData->meshElementIds[i] = meshData->meshElementIds[i]; meshData->backupData->meshElementDirs[i] = meshData->meshElementDirs[i]; } //--Mesh border elements meshData->backupData->nofMeshBorderElements = meshData->nofMeshBorderElements; meshData->backupData->meshBorderElementIds = new int[meshData->nofMeshBorderElements]; meshData->backupData->meshBorderElementDirs = new short[meshData->nofMeshBorderElements]; for (i = 0; i < meshData->nofMeshBorderElements; i++) { meshData->backupData->meshBorderElementIds[i] = meshData->meshBorderElementIds[i]; meshData->backupData->meshBorderElementDirs[i] = meshData->meshBorderElementDirs[i]; } } // Linearize geometry and store linearizing points in the 'bpoints' buffer // NOTE: Buffer is allocated here!!! void BodyElement::calcBoundaryPoints(double delta_u, double delta_v) { if ( modelData == NULL ) { return; } modelData->deleteBoundaryPoints(); if ( ptrGmtr == NULL ) return; ptrGmtr->calcBoundaryPoints(); return; // Old version!!! // int nof_points_u; int nof_points_v; GcPoint** points; ptrGmtr->calcLinearizingPoints(nof_points_u, nof_points_v, points, delta_u, delta_v); int nof_points = 0; if ( nof_points_v > 0 ) nof_points = nof_points_u * nof_points_v; else nof_points = nof_points_u; if (nof_points == 0) return; modelData->boundaryPoints = new BoundaryPoint*[nof_points]; for (int i = 0; i < nof_points; i++) { BoundaryPoint* bp = new BoundaryPoint; modelData->boundaryPoints[i] = bp; // Check if bp is an existing vertex! BodyElement* v = model->getVertex(points[i]); if ( v != NULL ) { bp->tag = v->Tag(); bp->vertexTag = v->Tag(); } //bp->boundaryTag = boundaryTag; bp->point = points[i]; } // Handle possibly closed geometry // ------------------------------- int nof_u = nof_points_u; int nof_v = (nof_points_v > 0)?nof_points_v:1; //-Copy start points to end points if U-closed // if (ptrGmtr->isClosedU()) { for (int i = 1; i <= nof_v; i++) { int pos0 = (i - 1) * nof_u; int pos1 = pos0 + nof_u - 1; BoundaryPoint* tmp = modelData->boundaryPoints[pos1]; modelData->boundaryPoints[pos1] = modelData->boundaryPoints[pos0]; delete tmp; } } //-Copy start points to end points if V-closed // if (ptrGmtr->isClosedV()) { for (int i = 1; i <= nof_u; i++) { int pos0 = (i - 1) * nof_v; int pos1 = pos0 + nof_v - 1; BoundaryPoint* tmp = modelData->boundaryPoints[pos1]; modelData->boundaryPoints[pos1] = modelData->boundaryPoints[pos0]; delete tmp; } } modelData->nofBoundaryPointsU = nof_points_u; modelData->nofBoundaryPointsV = nof_points_v; if ( nof_points_v == 0 ) modelData->nofBoundaryPoints = nof_points_u; else modelData->nofBoundaryPoints = nof_points_u * nof_points_v; delete[] points; } // Check boundary group data // // NOTE: Each element must belong to some boundary group!!! // If boundary group data is not complete, make sure that // element is inserted to the group (the grop will be created // if it does not exist) // bool BodyElement::checkElementGroupData() { // NOTE: No group is created (explicitely) for an intra layer boundary! if ( isIntraLayerBoundary() ) return true; if ( elementGroupTag == NO_INDEX || elementGroupId == NO_INDEX ) { // Get group id, possibly create a new group if tag is no-index elementGroupId = model->addToElementGroup(this, elementGroupTag); // Pick group BodyElementGroup* beg = model->getBodyElementGroupById(elementGroupId); if ( beg == NULL ) return false; // If a new group was created for this boundary, get the group tag and set also // boundaryCondition-id for the group // NOTE: This is a single boundary group, only for this element! // if ( elementGroupTag == NO_INDEX) { elementGroupTag = beg->Tag(); beg->setType(IMPLICIT_GROUP); beg->setBoundaryConditionId(txBndrConditionId); // Set parent info into group beg->setParentId(1,getParentId(1)); beg->setParentId(2,getParentId(2)); beg->setParentLayer(1,getParentLayer(1)); beg->setParentLayer(2,getParentLayer(2)); beg->setParentTag(1,getParentTag(1)); beg->setParentTag(2,getParentTag(2)); } } return true; } // If body element is added or deleted from the model // we have to check that class attribute "lastBoundaryTag" // remains correct. // NOTE: Each subclasses (1D, 2D, 3D) have a common last_boundaryTag void BodyElement::checkLastBoundaryTag(bool being_deleted) { // Nothing to do if ( boundaryTag == NO_INDEX ) return; // If the last element is being deleted if (being_deleted) { if (last_boundaryTag == boundaryTag) { last_boundaryTag--; } } // If this element has larger id than what // corresponds to the current lastId else { if (last_boundaryTag < boundaryTag) { last_boundaryTag = boundaryTag; } } } // If body element is added or deleted from the model // we have to check that class attribute "last_tag" // remains correct. // NOTE: Each subclass (1D, 2D, 3D) has its own tags which // starts from 1 void BodyElement::checkLastTag(bool being_deleted) { int last_tag = getLastTag(); // Nothing to do (no last tag defined!) if ( last_tag == NO_INDEX ) return; // If the last element is being deleted if (being_deleted) { if (last_tag == tag) { last_tag--; } } // If this element has larger id than what // corresponds to the current lastId else { if (last_tag < tag) { last_tag = tag; } } setLastTag(last_tag); } // Check if boundary is an intra-layer boundary // // NOTE: Such boundaries are displayed only on GridParameter // panel for grid controlling purposes // // NOTE: They will be however output to Elmer mesh, because Mesh2D // cannot drop them away! // bool BodyElement::isIntraLayerBoundary() { if ( modelData == NULL ) return false; else return modelData->isIntraLayerBoundary; } // Check if we have to create at least one vertex for the // body element (this is mainly needed for mesh geometries // where we want to have at least one vertex at the boundaries // for Dirichlet boundary conditions // void BodyElement::createExtraVertices() { // No need to create an extra vertex! if ( modelData == NULL || modelData->nofVertices > 0 || modelData->nofSubElements > 0 ) { return; } // No way to create an extra vertex! if ( meshData == NULL || meshData->nofMeshElements == 0 ) { return; } MeshElementTable* source; Point3* nodes = model->getMeshNodeData(); const int* node_ids; objectType otype = getObjectType(); ecif_modelDimension dim = model->getDimension(); // 3D face or a normal 2D boundary if ( (dim == ECIF_3D && otype == OT_FACE) || (dim == ECIF_2D && otype == OT_EDGE) ) { source = model->getMeshBoundaryElements(); // 3D edge boundary or 2D vertex boundary } else if ( (dim == ECIF_3D && otype == OT_EDGE) || (dim == ECIF_2D && otype == OT_VERTEX) ) { source = model->getMeshBoundaryElementEdges(); } else { return; } // Pick first node from the first element! node_ids = source->getNodeIds(meshData->meshElementIds[0]); // Something went wrong! if ( node_ids == NULL ) { return; } // Check if vertex already exists, and if not // create a new vertex BodyElement* v = NULL; GcPoint gp(nodes[node_ids[0]]); // Find model point GcPoint* mp = model->getPoint(&gp); if ( mp != NULL ) { v = model->getVertex(mp); } if ( v == NULL ) { v = new BodyElement1D(&gp); v->addMeshElement(node_ids[0], 1); model->addBodyElement(v); } // Add vertex to the body element modelData->nofSubElements = 1; modelData->subElementIds->push_back(v->Id()); } bool BodyElement::convertTags2Ids() { UserInterface* gui = (UserInterface*)model->getGui(); strstream strm1, strm2; if ( modelData == NULL ) { strm1 << "***ERROR in definition for the edge " << tag << ":" << ends; strm2 << "---No data defined in the input!" << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str(), 1); return false; } int i; // Subelement tag -> ids for (i = 0; i < modelData->nofSubElements; i++) { int se_tag = (*modelData->subElementIds)[i]; BodyElement* se; if ( model->getDimension() == ECIF_3D ) se = model->getEdgeByTag(se_tag); else se = model->getVertexByTag(se_tag); if ( se != NULL ) { (*modelData->subElementIds)[i] = se->Id(); } else { (*modelData->subElementIds)[i] = NO_INDEX; strm1 << "***ERROR in geometry for the edge " << tag << ":" << ends; strm2 << "---Sub element " << se_tag << " not found!" << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str(), 1); return false; } } // Vertex tags -> ids for (i = 0; i < modelData->nofVertices; i++) { int v_tag = (*modelData->vertexIds)[i]; BodyElement* v = model->getVertexByTag(v_tag); if ( v != NULL ) { (*modelData->vertexIds)[i] = v->Id(); } else { (*modelData->vertexIds)[i] = NO_INDEX; strm1 << "***ERROR in geometry for the edge " << tag << ":" << ends; strm2 << "---Vertex " << v_tag << " not defined in the input!" << ends; gui->showMsg(strm1.str()); gui->showMsg(strm2.str(), 1); return false; } } return true; } void BodyElement::deleteCadData() { delete ptrGmtr; ptrGmtr = NULL; } void BodyElement::deleteMeshDataBackup() { if (meshData == NULL || meshData->backupData == NULL ) return; delete[] meshData->backupData->meshElementIds; delete[] meshData->backupData->meshElementDirs; delete[] meshData->backupData->meshBorderElementIds; delete[] meshData->backupData->meshBorderElementDirs; delete meshData->backupData; meshData->backupData = NULL; } void BodyElement::deleteMeshElements() { if ( meshData == NULL ) { return; } delete meshData; meshData = new BodyElementMeshData; } void BodyElement::deleteMeshElements(bool* delete_flags) { if ( meshData == NULL ) { return; } int i; // Count nof elements left int nof_elements = 0; for (i = 0; i < meshData->nofMeshElements; i++) { if ( !delete_flags[i] ) { nof_elements++; } } // If no elements left!!! if (nof_elements == 0) { deleteMeshElements(); return; } int* tmp_ids = new int[nof_elements]; short* tmp_dirs = new short[nof_elements]; int counter = 0; for (i = 0; i < meshData->nofMeshElements; i++) { if ( delete_flags[i] ) { continue; } int index = meshData->meshElementIds[i]; short dir = meshData->meshElementDirs[i]; tmp_ids[counter] = index; tmp_dirs[counter] = dir; counter++; } delete[] meshData->meshElementIds; delete[] meshData->meshElementDirs; meshData->meshElementIds = tmp_ids; meshData->meshElementDirs = tmp_dirs; meshData->nofMeshElements = nof_elements; meshData->maxNofMeshElements = nof_elements; // For sake of sure! meshData->nofMeshSelectedElements = 0; } // Draw element by geometry component index // void BodyElement::draw(int gmtr_index, Renderer* renderer, flagName geometry_type, int body_id, int direction, bool is_first_loop) { if ( isIntraLayerBoundary() ) { //drawMode = DM_INTRA_LAYER; } Body* bd = model->getBodyById(body_id); int layer; if ( body_id == modelData->parent1Id ) layer = modelData->parent1Layer; else if ( body_id == modelData->parent2Id ) layer = modelData->parent2Layer; else layer = NO_INDEX; // If this is a hidden boundary or an exluded mesh boundary if ( (drawMode == DM_HIDDEN && drawState != DS_SELECTED ) || ( geometry_type == DRAW_SOURCE_MESH && bd->isExcludedFromCurrentMesh(layer) ) ) { return; } // Store element name and draw renderer->name_save(id); if ( geometry_type == DRAW_SOURCE_MESH ) { drawMesh(renderer, body_id, direction); } else { ptrGmtr->draw(gmtr_index, renderer, drawMode, drawState, direction, is_first_loop); } // Draw sub elements (edges/vertices) if ( gmtr_index == 0 ) { drawSubElements(renderer, geometry_type, body_id, direction, is_first_loop); } renderer->name_delete(id); } // Draw element // void BodyElement::draw(Renderer* renderer, flagName geometry_type, int body_id, int direction, bool is_first_loop) { if ( isIntraLayerBoundary() ) { //drawMode = DM_INTRA_LAYER; } Body* bd = model->getBodyById(body_id); int layer; if ( body_id == modelData->parent1Id ) layer = modelData->parent1Layer; else if ( body_id == modelData->parent2Id ) layer = modelData->parent2Layer; else layer = NO_INDEX; // If this is a hidden boundary or an exluded mesh boundary if ( (drawMode == DM_HIDDEN && drawState != DS_SELECTED) || ( geometry_type == DRAW_SOURCE_MESH && bd->isExcludedFromCurrentMesh(layer) ) ) { return; } // Store element name and draw renderer->name_save(id); if ( geometry_type == DRAW_SOURCE_MESH ) { drawMesh(renderer, body_id, direction); } else { ptrGmtr->draw(renderer, drawMode, drawState, direction, is_first_loop); } // Draw sub elements (edges/vertices) drawSubElements(renderer, geometry_type, body_id, direction, is_first_loop); renderer->name_delete(id); } void BodyElement::drawLabel(Renderer* renderer, bool draw_sub_labels) { if ( isIntraLayerBoundary() ) return; if (labelData != NULL && model->getLabelDisplayFlagValue(this) ) { renderer->drawElementLabel(labelData->label, labelData->position); } if ( !draw_sub_labels || modelData == NULL ) { return; } for (int i = 0; i < modelData->nofSubElements; i++ ) { BodyElement* se = model->getBodyElementById((*modelData->subElementIds)[i]); if ( se != NULL && (se->getDrawMode() == DM_NORMAL || se->getDrawState() == DS_SELECTED) ) { se->drawLabel(renderer, draw_sub_labels); } } } void BodyElement::drawSubElements(Renderer* renderer, flagName geometry_type, int body_id, int direction, bool is_first_loop) { int nof_sub_elements = getNofSubElements(); for (int i = 0; i < nof_sub_elements; i++) { BodyElement* se = getSubElement(i); if ( se != NULL ) { se->draw(renderer, geometry_type, body_id, direction, is_first_loop); } } } void BodyElement::drawMesh(Renderer* renderer, int body_id, int direction) { if ( meshData == NULL || meshData->nofMeshElements == 0) { return; } if ( renderer->isPickingMesh() && drawState != DS_SELECTED ) { return; } //============================================= if ( renderer->isEditingMesh() ) { //---Draw border for the element if ( ECIF_3D == model->getDimension() ) { drawMeshBorder(renderer, true); } else { drawMeshBorder(renderer, false); } } MeshElementTable* elements; MeshElementTable* parents; MeshElementTable* et; bool isLevel2 = false; if ( model->getDimension() == ECIF_3D && getObjectType() == OT_EDGE ) { isLevel2 = true; } if ( isLevel2) { elements = model->getMeshBoundaryElementEdges(); parents = NULL; et = model->getMeshBoundaryElementVertices(); } else { elements = model->getMeshBoundaryElements(); parents = model->getMeshBulkElements(); et = model->getMeshBoundaryElementEdges(); } Point3* node_data = model->getMeshNodeData(); int i, j, index; short dir; //============================================= //---Surface elements drawing loop (draw "boundaries" filled) renderer->startDrawingMeshSurface(); meshData->nofMeshSelectedElements = 0; // Set state flags // =============== bool filled = false; bool selected = false; bool two_sided = false; //--3D surface mode if ( model->getDimension() == ECIF_3D ) { two_sided = true; if ( model->getFlagValue(DRAW_TARGET_BOUNDARIES) || drawState == DS_SELECTED ) { filled = true; } //--2D "surface" mode } else { if ( model->getFlagValue(DRAW_TARGET_EDGES) ) { filled = true; } } if ( !model->getFlagValue(DRAW_TARGET_BOUNDARIES) && drawState == DS_SELECTED ) { two_sided = true; } if ( two_sided ) { renderer->drawTwoSidedPolygons(true); } if ( !filled) { renderer->setLightUndirected(); } // Loop mesh elements in the boundary // ================================== for (i = 0; i < meshData->nofMeshElements; i++) { selected = false; index = meshData->meshElementIds[i]; dir = meshData->meshElementDirs[i]; if ( parents != NULL ) { int parent1_elem_id = elements->parentIds[index][0]; int parent1_body_id = parents->getParentId(parent1_elem_id, 0); if ( parent1_body_id != body_id ) { dir = -dir; } } // Mesh element's selected state is taken into account only when // boundary itself is selected if ( drawState == DS_SELECTED ) { if ( elements->getSelected(index) ) { selected = true; meshData->nofMeshSelectedElements++; } } // Draw // ==== if (filled) { elements->drawElement(renderer, index, dir, selected); } else { elements->drawEdges(renderer, et, index, selected); } elements->resetRendered(index); } // Reset state flags // ================= if ( two_sided ) { renderer->drawTwoSidedPolygons(false); } if ( !filled) { renderer->setLightDirected(); } renderer->stopDrawingMeshSurface(); //============================================= // If boundary is not selected, we can stop here if (drawState != DS_SELECTED) { return; } //============================================= //---Mark selected element's border edges as // selected (to be drawn thicker!) // Set first all edges as non-selected for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; meshElementCode bndr_code = elements->getElementCode(index); int nof_edges = MeshElementDesc[bndr_code][DESC_NOF_EDGES]; const int* edge_ids = elements->getEdgeIds(index); for (j = 0; j < nof_edges; j++) { et->setSelected(edge_ids[j], false, false); } } // Then set the edges of the selected elements selected so // that the interior edges are left non-selected! for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; if ( !elements->selected[index] ) { continue; } meshElementCode bndr_code = elements->getElementCode(index); int nof_edges = MeshElementDesc[bndr_code][DESC_NOF_EDGES]; const int* edge_ids = elements->getEdgeIds(index); for (j = 0; j < nof_edges; j++) { et->setSelected(edge_ids[j], true, true); } } //============================================= //---Surface mesh drawing loop (element edges) renderer->startDrawingMeshSurfaceEdges(); for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; bool as_selected = false; if (isLevel2) { as_selected = true; } elements->drawEdges(renderer, et, index, as_selected); } renderer->stopDrawingMeshSurfaceEdges(); } // Draw border elements (edges (3D) or vertices (2D)) void BodyElement::drawMeshBorder(Renderer* renderer, bool selected) { if ( model->modelHasCadGeometry() || meshData == NULL || meshData->nofMeshBorderElements == 0 ) { return; } MeshElementTable* et = model->getMeshBoundaryElementEdges(); Point3* node_data = model->getMeshNodeData(); int i, index; for (i = 0; i < meshData->nofMeshBorderElements; i++) { index = meshData->meshBorderElementIds[i]; et->drawElement(renderer, index, selected); } } // Checks if bodyelement has a common boundary with an other bodyelement. // Returns the matching type matchType BodyElement::findCommonBoundary(BodyElement* other, BodyElement*& common) { matchType match_type = MATCH_NONE; common = NULL; if ( ptrGmtr == NULL) return MATCH_NONE; // Method to be called depends on geometry. ecif_geometryType tg1 = this->ptrGmtr->getType(); ecif_geometryType tg2 = other->ptrGmtr->getType(); // We have edges which are both linear: if ( (tg1 == ECIF_LINE || tg1 == ECIF_POLYLINE) && (tg2 == ECIF_LINE || tg2 == ECIF_POLYLINE) ) { match_type = this->matchToLinear(other, common); } else if (tg1 == ECIF_NURBS && tg2 == ECIF_NURBS) { match_type = this->matchToNurbs(other, common); } return match_type; } int BodyElement::findMeshBorder() { if ( meshData == NULL || meshData->nofMeshElements == 0) return 0; MeshElementTable* bet = model->getMeshBoundaryElements(); MeshElementTable* et = model->getMeshBoundaryElementEdges(); int i, index; // Set first all subelements (edges or vertices) as non-selected for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; meshElementCode bndr_code = bet->getElementCode(index); int nof_edges = MeshElementDesc[bndr_code][DESC_NOF_EDGES]; const int* edge_ids = bet->getEdgeIds(index); for (int j = 0; j < nof_edges; j++) { et->setSelected(edge_ids[j], false, false); } } // Then set the sublements selected so // that the interior ones are left non-selected! for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; meshElementCode bndr_code = bet->getElementCode(index); int nof_edges = MeshElementDesc[bndr_code][DESC_NOF_EDGES]; const int* edge_ids = bet->getEdgeIds(index); for (int j = 0; j < nof_edges; j++) { et->setSelected(edge_ids[j], true, true); } } meshData->nofMeshBorderElements = 0; // Finally calculate number of selected sub_elements for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; meshElementCode bndr_code = bet->getElementCode(index); int nof_edges = MeshElementDesc[bndr_code][DESC_NOF_EDGES]; const int* edge_ids = bet->getEdgeIds(index); for (int j = 0; j < nof_edges; j++) { if ( et->getSelected(edge_ids[j]) ) { meshData->nofMeshBorderElements++; } } } // Create ids and direction indicator tables delete[] meshData->meshBorderElementIds; meshData->meshBorderElementIds = new int[meshData->nofMeshBorderElements]; delete[] meshData->meshBorderElementDirs; meshData->meshBorderElementDirs = new short[meshData->nofMeshBorderElements]; // Pick mesh border element ids int counter = 0; for (i = 0; i < meshData->nofMeshElements; i++) { index = meshData->meshElementIds[i]; meshElementCode bndr_code = bet->getElementCode(index); int nof_edges = MeshElementDesc[bndr_code][DESC_NOF_EDGES]; const int* edge_ids = bet->getEdgeIds(index); for (int j = 0; j < nof_edges; j++) { int edge_id = edge_ids[j]; // If subelement is selected if ( et->getSelected(edge_ids[j]) ) { meshData->meshBorderElementIds[counter] = edge_id; meshData->meshBorderElementDirs[counter] = 1; // Currently always 1 !!!###!!! counter++; } } } return meshData->nofMeshBorderElements; } int BodyElement::findSelectedMeshElement(Renderer* renderer, Point3& ray_start, Point3& ray_dir, Point3& isec_point, int& bndr_id, int& body1_id, int& layer1_id, int& body2_id, int& layer2_id) { bndr_id = id; body1_id = NO_INDEX; body2_id = NO_INDEX; layer1_id = NO_INDEX; layer2_id = NO_INDEX; if ( meshData == NULL || meshData->nofMeshElements == 0 || drawMode == DM_HIDDEN ) { return NO_INDEX; } int bd1_id = modelData->parent1Id; int bd2_id = modelData->parent2Id; Body* bd1 = model->getBodyById(bd1_id); Body* bd2 = model->getBodyById(bd2_id); int lr1_id = NO_INDEX; int lr2_id = NO_INDEX; if ( bd1 != NULL ) { lr1_id = bd1->getLayerId(modelData->parent1Layer); } if ( bd2 != NULL ) { lr2_id = bd2->getLayerId(modelData->parent2Layer); } // Filter: If both parent bodies are hidden if ( (bd1 == NULL || bd1->getDrawMode() == DM_HIDDEN) && (bd2 == NULL || bd2->getDrawMode() == DM_HIDDEN) ) { return NO_INDEX; } // Filter: In 3D, if both parent bodies are visible, we cannot select this boundary! // // NOTE: If bd1_id==bd2_id this is an outer boundary and then no problems! // if ( ECIF_3D == model->getDimension() && (bd1_id != bd2_id) && (bd1 != NULL && bd1->getDrawMode() != DM_HIDDEN) && (bd2 != NULL && bd2->getDrawMode() != DM_HIDDEN) ) { return NO_INDEX; } short direction; if ( bd1->getDrawMode() == DM_HIDDEN ) { body1_id = bd2_id; body2_id = bd1_id; layer1_id = lr2_id; layer2_id = lr1_id; direction = -1; } else { body1_id = bd1_id; body2_id = bd2_id; layer1_id = lr1_id; layer2_id = lr2_id; direction = 1; } // A Bem boundary (body) can be selected // form both sides! if ( isBemBoundary() ) { direction = 0; } flagName select_mode = model->getSelectionMode(); MeshElementTable* elements = model->getMeshBoundaryElements(); MeshElementTable* parents = model->getMeshBulkElements(); double min_distance = 1.0e100; int isec_elem_index = NO_INDEX; for (int i = 0; i < meshData->nofMeshElements; i++) { int elem_index = meshData->meshElementIds[i]; int nof_isections = elements->calcLineIntersections(elem_index, direction, ray_start, ray_dir, &isec_point); #if 0 if ( nof_isections > 0 ) { return elem_index; } #endif if ( nof_isections == 0 ) { continue; } double distance = ray_start[2] - isec_point[2]; distance = (distance < 0 ) ? -distance : distance; if ( distance < min_distance ) { min_distance = distance; isec_elem_index = elem_index; } } // for all mesh elements //return NO_INDEX; return isec_elem_index; } // Linearize original geometry and replace it with the polyline geometry // // NOTE: This should be used only for internal purposes in the cases it is easier // to handle geometry in discretized form (intersection calculations etc.) // Geometry imported from Cad files should be stored in the original format!!! // void BodyElement::formLinearizedGeometry() { if ( modelData == NULL ) { return; } int nof_points_u; int nof_points_v; GcPoint** points; ptrGmtr->calcLinearizingPoints(nof_points_u, nof_points_v, points); if ( points == NULL ) return; int nof_points = 0; if ( nof_points_v > 0 ) { nof_points = nof_points_u * nof_points_v; } else { nof_points = nof_points_u; } // Replace the original geometry // delete ptrGmtr; ptrGmtr = new GcPolyLine(nof_points, points); delete[] points; } int BodyElement::getBoundaryConditionId() const { BodyElementGroup* beg = model->getBodyElementGroupById(elementGroupId); if ( beg == NULL ) return NO_INDEX; return beg->getBoundaryConditionId(); } int BodyElement::getBoundaryParameterId() const { return boundaryParameterId; } void BodyElement::getBoundaryPoints(int& count, BoundaryPoint**& points) { if ( ptrGmtr == NULL ) { count = 0; points = NULL; } else { ptrGmtr->getBoundaryPoints(count, points); } } void BodyElement::getDiscretizationData(int& nof_components, linDeltaType*& types, double*& valuesU, double*& valuesV, bool*& useFixedN) { nof_components = 0; types = NULL; valuesU = NULL; valuesV = NULL; useFixedN = NULL; if ( ptrGmtr == NULL ) return; ptrGmtr->getDiscretizationData(nof_components, types, valuesU, valuesV, useFixedN); } const BodyElementGroup* BodyElement::getElementGroup() const { return model->getBodyElementGroupById(elementGroupId); } enum elementGroupType BodyElement::getElementGroupType() const { BodyElementGroup* beg = model->getBodyElementGroupById(elementGroupId); if ( beg == NULL ) return NONE_GROUP; return beg->getGroupType(); } BodyElement* BodyElement::getFirstSubElement() { if ( modelData == NULL || modelData->nofSubElements == 0 ) return NULL; return getSubElement(0); } const int* BodyElement::getGridHIds() { if ( gridHData != NULL ) return gridHData->gridHIds; else return NULL; } const int* BodyElement::getGridMeshIndices() { if ( gridHData != NULL ) return gridHData->meshIndices; else return NULL; } BodyElement* BodyElement::getLastSubElement() { if ( modelData == NULL || modelData->nofSubElements == 0 ) return NULL; return getSubElement(modelData->nofSubElements - 1); } bool BodyElement::getMeshDensityValues(int mesh_index, char& type, int& nof_values, double values[4]) { if ( gridHData == NULL && modelData == NULL ) return false; if ( mesh_index < 0 || mesh_index >= model->getNofMeshes() ) return false; // If directly set value available for the mesh // ============================================ if ( gridHData != NULL && gridHData->meshIndex == mesh_index && gridHData->hValueType != ' ' && gridHData->hValue > 0 ) { type = gridHData->hValueType; nof_values = 1; values[0] = gridHData->hValue; return true; } // Check quadgrid mesh density // =========================== Body* bd1 = model->getBodyById(getParentId(1)); Body* bd2 = model->getBodyById(getParentId(2)); if ( bd1 != NULL ) { double n = bd1->getMeshQuadGridN(modelData->parent1Layer, mesh_index, id); if ( n > 0 ) { type = 'N'; nof_values = 1; values[0] = n; return true; } } if ( bd2 != NULL ) { double n = bd2->getMeshQuadGridN(modelData->parent2Layer, mesh_index, id); if ( n > 0 ) { type = 'N'; nof_values = 1; values[0] = n; return true; } } // Check normal mesh density // ========================= if ( gridHData == NULL ) return false; type = ' '; nof_values = 0; values[0] = values[1] = values[2] = values[3] = 0; char dtype[2] = " "; double* dvalues = NULL; // Check if some parameter defined for the mesh for (int i = 0; i < gridHData->nofIds; i++) { if ( mesh_index == gridHData->meshIndices[i] ) { Parameter* param = model->getParameterById(ECIF_GRID_H, gridHData->gridHIds[i]); if ( param == NULL ) return false; // If value type given if ( param->getFieldValueBySifName("Mesh Density Type", 1, (char*)dtype) ) { // MeshH if ( dtype[0] == 'H' && param->getFieldValueBySifName("Mesh H", nof_values, dvalues) ) { type = 'H'; // Mesh R } else if ( dtype[0] == 'R' && param->getFieldValueBySifName("Mesh R", nof_values, dvalues) ) { type = 'R'; // Mesh N } else if ( dtype[0] == 'N' && param->getFieldValueBySifName("Mesh N", nof_values, dvalues) ) { type = 'N'; } } break; } } if ( nof_values == 0 ) return false; for (int j = 0; j < nof_values; j++) { values[j] = dvalues[j]; } delete[] dvalues; return true; } short BodyElement::getMeshElementDir(int index) { if ( meshData == NULL || meshData->nofMeshElements == 0 ) return 0; if ( index < 0 || index >= meshData->nofMeshElements ) return 0; return meshData->meshElementDirs[index]; } int BodyElement::getMeshElementId(int index) { if ( meshData == NULL || index < 0 || index >= meshData->nofMeshElements) return NO_INDEX; return meshData->meshElementIds[index]; } const char* BodyElement::getName() { if ( name == NULL || name[0] == '\0' ) { initName(); } return name; } int BodyElement::getNofBoundaryPoints() const { if ( ptrGmtr == NULL ) { return 0; } else { return ptrGmtr->getNofBoundaryPoints(); } } int BodyElement::getNofComponents(bool only_emf_components) const { if ( ptrGmtr != NULL ) return ptrGmtr->getNofComponents(only_emf_components); else if ( meshData != NULL ) return 1; else return 0; } int BodyElement::getNofGridHIds() const { if ( gridHData != NULL ) return gridHData->nofIds; else return 0; } int BodyElement::getNofMeshElements() const { if ( meshData == NULL ) return 0; else return meshData->nofMeshElements; } int BodyElement::getNofMeshSelectedElements() const { if ( meshData == NULL ) return 0; else return meshData->nofMeshSelectedElements; } int BodyElement::getNofSubElements() const { if ( modelData == NULL ) return 0; else return modelData->nofSubElements; } int BodyElement::getNofVertices() const { if ( modelData == NULL ) return 0; return modelData->nofVertices; } // Method returns a list of bodyelements which together form // the outer boundary-part of the element. BodyElementList* BodyElement::getOuterBoundary() { if ( modelData == NULL || !(modelData->status & BE_OUTER_CHECKED) ) return NULL; return findOuterBoundary(); } int BodyElement::getParentId(short parent) const { if ( modelData == NULL ) return NO_INDEX; if (parent == 1) return modelData->parent1Id; else if (parent == 2) return modelData->parent2Id; else return NO_INDEX; } int BodyElement::getParentLayer(short parent) const { if ( modelData == NULL ) return NO_INDEX; if (parent == 1) return modelData->parent1Layer; else if (parent == 2) return modelData->parent2Layer; else return NO_INDEX; } int BodyElement::getParentTag(short parent) const { if ( modelData == NULL ) return NO_INDEX; if (parent == 1) return modelData->parent1Tag; else if (parent == 2) return modelData->parent2Tag; else return NO_INDEX; } bool BodyElement::getRangeVector(RangeVector rv) { if ( ptrGmtr == NULL ) { return false; } ptrGmtr->getRangeVector(rv); return true; } void BodyElement::getSelectedMeshElementIds(int& nof_ids, int*& ids) { nof_ids = 0; if ( meshData == NULL || meshData->nofMeshElements == 0) return; MeshElementTable* bet = model->getMeshBoundaryElements(); int counter, i; counter = 0; for (i = 0; i < meshData->nofMeshElements; i++) { int index = meshData->meshElementIds[i]; if ( bet->selected[index] ) { counter++; } } nof_ids = counter; if (nof_ids == 0) return; ids = new int[nof_ids]; counter = 0; for (i = 0; i < meshData->nofMeshElements; i++) { int index = meshData->meshElementIds[i]; if ( bet->selected[index] ) { ids[counter++] = index; } } } int BodyElement::getSubElementTag(int index) { if ( modelData == NULL || modelData->nofSubElements == 0 ) return NO_INDEX; if ( index < 0 || index >= modelData->nofSubElements ) return NO_INDEX; return model->getModelObjectTagById((*modelData->subElementIds)[index]); } beStatus BodyElement::getStatus() { if ( modelData == NULL ) return BE_NONE; else return modelData->status; } // Checks if bodyelement contains completely an other bodyelement. bool BodyElement::hasInside(BodyElement* other_element) { if (ptrGmtr == NULL) return false; BoundBox* box1 = ptrGmtr->boundbox; BoundBox* box2 = other_element->ptrGmtr->boundbox; return box1->contains(box2); } /* // Method tells if bodyelement has an outer boundary. bool BodyElement::hasOuterBoundary(int dir_in_body) { if ( !(status & BE_OUTER_CHECKED) ) checkOuterBoundary(dir_in_body); //-Return true if element is an outer boundary // or includes some as sub-elements. return (status & BE_INCLUDES_OUTER); } */ bool BodyElement::hasZeroVelocityBC() { int bc_id = getBoundaryConditionId(); if ( bc_id == NO_INDEX ) { return false; } BoundaryCondition* bc; bc = (BoundaryCondition*) model->getParameterById(ECIF_BOUNDARY_CONDITION, bc_id); if ( bc != NULL && bc->hasZeroVelocity() ) { return true; } else { return false; } } void BodyElement::init() { gridHData = NULL; modelData = NULL; meshData = NULL; labelData = NULL; ptrGmtr = NULL; boundaryTag = NO_INDEX; elementGroupTag = NO_INDEX; elementGroupId = NO_INDEX; txBndrConditionId = NO_INDEX; boundaryParameterId = NO_INDEX; create_dyna_string(name, NULL); create_dyna_string(name_old, NULL); drawMode = DM_NORMAL; drawState = DS_NORMAL; } void BodyElement::initLabelData() { if ( ptrGmtr == NULL ) return; if ( labelData == NULL ) { labelData = new LabelData; labelData->label = NULL; } // Make an id-string. ostrstream id_str; id_str << Tag() << ends; update_dyna_string(labelData->label, id_str.str()); //---Get 'nice' position for the id-label ptrGmtr->getLabelPoint(labelData->position); } void BodyElement::initName(char* be_name) { // If name already set if (name != NULL && name[0] != '\0') return; // If name given as argument if ( be_name != NULL && be_name[0] !='\0' ) { update_dyna_string(name, be_name); update_dyna_string(name_old, name); return; } // Set default name strstream strm; objectType otp = getObjectType(); switch (otp) { case OT_FACE: strm << "Boundary"; break; case OT_EDGE: if ( model->getDimension() == ECIF_3D ) strm << "Edge"; else strm << "Boundary"; break; case OT_VERTEX: strm << "Vertex"; break; } if (tag != NO_INDEX) { strm << tag; } strm << ends; update_dyna_string(name, strm.str()); update_dyna_string(name_old, name); } void BodyElement::initClass(Model* mdl) { BodyElement::last_boundaryTag = 0; // Init also sub-classe (for setting last_tag!) BodyElement1D::initClass(mdl); BodyElement2D::initClass(mdl); BodyElement3D::initClass(mdl); } bool BodyElement::isBemBoundary() { int bd_id = getParentId(1); Body* bd = model->getBodyById(bd_id); if ( bd != NULL && BEM_BODY == bd->getType() ) return true; else return false; } // Nof of intersections with a line which is parallel to x-axis. RayHit* BodyElement::isectionsWithXdir(GcPoint* startp, bool& negative_on_left) { negative_on_left = false; if (ptrGmtr == NULL ) { return NULL; } else { return ptrGmtr->isectionsWithXdir(startp, negative_on_left); } } bool BodyElement::isInnerBoundary() { if ( ( (getObjectType() == OT_EDGE && model->getDimension() == ECIF_2D) || (getObjectType() == OT_FACE && model->getDimension() == ECIF_3D) ) && modelData != NULL && modelData->parent1Id != NO_INDEX && modelData->parent2Id != NO_INDEX && !isIntraLayerBoundary() ) { return true; } else { return false; } } void BodyElement::markActiveMeshObjects(bool*& active_object_flags) { // Subelements int nof_subs = getNofSubElements(); int i; for (i = 0; i < nof_subs; i++) { BodyElement* se = getSubElement(i); if ( se == NULL || !se->isActive() ) continue; active_object_flags[se->Id()] = true; se->markActiveMeshObjects(active_object_flags); } // Boundary points int bp_count; BoundaryPoint** bp_points; getBoundaryPoints(bp_count, bp_points); for (i = 0; i < bp_count; i++ ) { BoundaryPoint* bp = bp_points[i]; bp->activeInMeshing = true; } } void BodyElement::markActiveObjects() { if ( modelData == NULL ) return; int i; // Subelements for (i = 0; i < modelData->nofSubElements; i++) { int se_id = (*modelData->subElementIds)[i]; model->markObjectActive(se_id); BodyElement* sbe = model->getBodyElementById(se_id); sbe->markActiveObjects(); } // Vertices for (i = 0; i < modelData->nofVertices; i++) { int v_id = (*modelData->vertexIds)[i]; model->markObjectActive(v_id); } } ostream& BodyElement::output_emf(ostream& out, short indent_size, short indent_level, bool output_geometry) { char* QM = "\""; short is = indent_size; short il = indent_level; char* fn = NULL; objectType otp = getObjectType(); //--Element type and tag if ( otp == OT_VERTEX ) { LibFront::output_scalar(out, is, il, EMF_VERTEX, NULL, tag); fn = "Vertex"; } else if (otp == OT_EDGE ) { LibFront::output_scalar(out, is, il, EMF_EDGE, NULL, tag); } else if (otp == OT_FACE ) { LibFront::output_scalar(out, is, il, EMF_FACE, NULL, tag); } else { return out; } //--Boundary tag LibFront::output_scalar(out, is, 1 + il, "Boundary Tag", NULL, boundaryTag); //--Name if ( name != NULL && name[0] != '\0' ) { LibFront::output_scalar(out, is, 1 + il, "Name", NULL, name); } //--Subelements (edges or vertices) // // NOTE: No subelements for Edges. Their vertices are ouput via Components!!! // if ( modelData != NULL && modelData->nofSubElements > 0 ) { int count = 0; int* element_tags; if ( otp == OT_FACE ) { // Try edges modelData->getSubElementTags(model, OT_EDGE, count, element_tags); if ( count > 0 ) { LibFront::output_vector(out, is, 1 + il, EMF_EDGES, NULL, count, element_tags, false); delete[] element_tags; } // Try vertices modelData->getSubElementTags(model, OT_VERTEX, count, element_tags); if ( count > 0 ) { LibFront::output_vector(out, is, 1 + il, EMF_VERTICES, NULL, count, element_tags, false); delete[] element_tags; } // NOTE: No actual subelements for Edges. // Their vertices are ouput via Components! // } else if ( otp == OT_EDGE && ( ptrGmtr == NULL || 0 == ptrGmtr->getNofVertices() ) ) { // Try (extra) vertices modelData->getSubElementTags(model, OT_VERTEX, count, element_tags); if ( count > 0 ) { LibFront::output_vector(out, is, 1 + il, EMF_EXTRA_VERTICES, NULL, count, element_tags, false); delete[] element_tags; } } } //--Geometry if ( output_geometry && ptrGmtr != NULL ) { ptrGmtr->output_emf(out, is, 1 + il); } // If boundary forms a single (logical) group), output // boundary condition and parameter info (because no group // is output!) // if ( EXPLICIT_GROUP != getElementGroupType() ) { //--Boundary Parameter Id int pid = getBoundaryParameterId(); if ( pid != NO_INDEX ) { LibFront::output_scalar(out, is, 1 + il, EMF_BOUNDARY_PARAMETER, NULL, pid); } //--Boundary Condition Id int cid = getBoundaryConditionId(); if ( cid != NO_INDEX ) { LibFront::output_scalar(out, is, 1 + il, EMF_BOUNDARY_CONDITION, NULL, cid); } } //--GridH if ( gridHData != NULL && gridHData->nofIds > 0 ) { int nof_ids = gridHData->nofIds; int* gids = gridHData->gridHIds; int* mids = gridHData->meshIndices; LibFront::output_vector(out, is, 1 + il, "Gridh Ids", NULL, nof_ids, gids, false); LibFront::output_vector(out, is, 1 + il, "Gridh Mesh Indices", NULL, nof_ids, mids, false); } return out; } // Output Boundary data into sif-file // // NOTE: Only boundary parameter data is output! // ostream& BodyElement::output_sif(ostream& out, short indent_size, short indent_level) { char* QM = "\""; short is = indent_size; short il = indent_level; // Boundary header and id LibFront::output_scalar(out, is, il, SIF_BOUNDARY, NULL, boundaryTag); // Name (in quotes) if ( model->getSolverKeywordTypeGiven(SIF_BOUNDARY, "Name") ) { LibFront::output_scalar(out, is, il + 1, "Name =", NULL, (char*)getName(), true); } else { LibFront::output_scalar(out, is, il + 1, "Name = String", NULL, (char*)getName(), true); } out << endl; #if 0 // Body1 tag if ( model->getSolverKeywordTypeGiven(SIF_BOUNDARY, "Body 1") ) { LibFront::output_scalar(out, is, il + 1, "Body 1 =", NULL, getParentTag(1)); } else { LibFront::output_scalar(out, is, il + 1, "Body 1 = Integer", NULL, getParentTag(1)); } // Body2 tag if ( model->getSolverKeywordTypeGiven(SIF_BOUNDARY, "Body 2") ) { LibFront::output_scalar(out, is, il + 1, "Body 2 =", NULL, getParentTag(2)); } else { LibFront::output_scalar(out, is, il + 1, "Body 2 = Integer", NULL, getParentTag(2)); } #endif // Boundary parameter if ( boundaryParameterId != NO_INDEX ) { Parameter* p = model->getParameterById(ECIF_BOUNDARY_PARAMETER, boundaryParameterId); if ( p != NULL ) { SifOutputControl soc; soc.outputId = false; soc.outputName = false; soc.outputType = false; soc.outputAll = false; soc.sectionName = SIF_BOUNDARY; p->output_sif(out, is, il, soc); } } return out; } // Output boundary point tags (for Elmer Mesh input file) // ostream& BodyElement::outputBoundaryPointTags(ostream& out, int indent_size) { if ( modelData == NULL ) { return out; } int max_per_line = 20; //--Normal vertices if ( modelData->nofBoundaryPoints == 0 ) { int count; int* vertex_tags; modelData->getVertexTags(model, count, vertex_tags); for (int i = 0; i < count; i++) { out << vertex_tags[i] << " "; } delete[] vertex_tags; //--Discretizating points } else { int counter = 0; for (int i = 0; i < modelData->nofBoundaryPoints; i++) { BoundaryPoint* bp = modelData->boundaryPoints[i]; if ( bp != NULL ) { out << bp->tag << " "; counter++; } // Continue from next line if ( counter >= max_per_line ) { out << endl; indent(out, indent_size); counter = 0; } } } return out; } // Output bodylements as a list of sub-element ids. // Direction tells bodyelement's direction in the parent body. // ostream& BodyElement::outputCoveringElementTags(ostream& out, int direction, int& nof_output_tags) { nof_output_tags = 0; if ( modelData == NULL || modelData->nofSubElements == 0 ) return out; if ( !(modelData->status & BE_DEVIDED) ) { out << direction * Tag(); return out; } int se_tag; IdList* se_list = model->getCoveringElementList(this->tag); // Element is in positive loop-order (ccw) // Start reading from head forwards. if (direction == 1) { IdList::iterator pos = se_list->begin(); while (pos != se_list->end()) { se_tag = *pos++; out << direction * se_tag << " "; nof_output_tags++; } } // Element is in negative loop-order (cw) // Start reading from tail backwards. else { IdList::reverse_iterator pos = se_list->rbegin(); while (pos != se_list->rend()) { se_tag = *pos++; out << direction * se_tag << " "; nof_output_tags++; } } return out; } // Get point corresponding parametric values. GcPoint* BodyElement::param2Point(double u_p, double v_p) { if ( ptrGmtr != NULL ) { return ptrGmtr->param2Point(u_p, v_p); } else { return NULL; } } // Get parametric values corresponding a point. ParamPair* BodyElement::point2Param(GcPoint* p) { if ( ptrGmtr != NULL ) { return ptrGmtr->point2Param(p); } else { return NULL; } } // Increase mesh element tables void BodyElement::reallocateMeshElements() { if ( meshData == NULL ) return; meshData->maxNofMeshElements += 50; int size = meshData->maxNofMeshElements; int* element_ids = new int[size]; short* element_dirs = new short[size]; for (int i = 0; i < meshData->nofMeshElements; i++) { element_ids[i] = meshData->meshElementIds[i]; element_dirs[i] = meshData->meshElementDirs[i]; } delete[] meshData->meshElementIds; meshData->meshElementIds = element_ids; delete[] meshData->meshElementDirs; meshData->meshElementDirs = element_dirs; } // Increase pending mesh element info table void BodyElement::reallocatePendingMeshElementInfos() { if ( meshData == NULL ) return; meshData->maxNofPendingMeshElements += 50; int size = meshData->maxNofPendingMeshElements; int** infos = new int*[size]; for (int i = 0; i < size; i++) { if ( i < meshData->nofPendingMeshElements ) { infos[i] = meshData->pendingMeshElementInfos[i]; } else { infos[i] = NULL; } } delete[] meshData->pendingMeshElementInfos; meshData->pendingMeshElementInfos = infos; } // Delete given (with index!) mesh elements // from the boundary void BodyElement::removeMeshElements(int nof_elements, int* element_indices) { if ( meshData == NULL ) return; if (nof_elements == 0 || meshData->nofMeshElements == 0) return; // construct a flag array and init it bool* delete_flags = new bool[meshData->nofMeshElements]; for (int i = 0; i < meshData->nofMeshElements; i++) { delete_flags[i] = false; } // Set flag active for the indices to be removed for (int j = 0; j < nof_elements; j++) { delete_flags[element_indices[j]] = true; } deleteMeshElements(delete_flags); delete[] delete_flags; } // Delete selected (in the display meaning!) mesh elements // from the boundary void BodyElement::removeSelectedMeshElements(int* removed_elements_storage) { if ( meshData == NULL || meshData->nofMeshSelectedElements == 0) return; bool* delete_flags = new bool[meshData->nofMeshElements]; MeshElementTable* elements = model->getMeshBoundaryElements(); int remove_counter = 0; for (int i = 0; i < meshData->nofMeshElements; i++) { int index = meshData->meshElementIds[i]; //--Selected mesh element if ( elements->selected[index] ) { delete_flags[i] = true; // If we should store removed indices (for split redo!) if (removed_elements_storage != NULL) removed_elements_storage[remove_counter++] = i; } //--Non selected mesh element else { delete_flags[i] = false; } } deleteMeshElements(delete_flags); meshData->nofMeshSelectedElements = 0; delete[] delete_flags; } beStatus BodyElement::removeStatus(beStatus old_status) { if ( modelData == NULL ) return BE_NONE; else return modelData->status &= ~old_status; } // Copy data from backup // NOTE: "pointer copy" DO NOT delete // meshDataBackup arries, just repoint // them and then make "unvisible" void BodyElement::restoreMeshDataBackup() { if ( meshData == NULL || meshData->backupData == NULL) return; //--Mesh elements meshData->maxNofMeshElements = meshData->backupData->nofMeshElements; meshData->nofMeshElements = meshData->backupData->nofMeshElements; delete[] meshData->meshElementIds; meshData->meshElementIds = meshData->backupData->meshElementIds; delete[] meshData->meshElementDirs; meshData->meshElementDirs = meshData->backupData->meshElementDirs; //--Mesh border elements meshData->nofMeshBorderElements = meshData->backupData->nofMeshBorderElements; delete[] meshData->meshBorderElementIds; meshData->meshBorderElementIds = meshData->backupData->meshBorderElementIds; delete[] meshData->meshBorderElementDirs; meshData->meshBorderElementDirs = meshData->backupData->meshBorderElementDirs; //--Delete backup struct (but NOT the arries inside!!!) delete meshData->backupData; meshData->backupData = NULL; } void BodyElement::restoreName() { create_dyna_string(name, name_old); } void BodyElement::setBoundaryParameterId(int pid) { boundaryParameterId = pid; } void BodyElement::setBoundaryPointsMeshDensityValue(int mesh_index) { char dtype; int nof_dvalues; double dvalues[4]; BodyElement* v; Point3 p1; Point3 p2; double delta; double tot_length, cum_length; int i; if ( modelData->nofBoundaryPoints == 0 ) { return; } BoundaryPoint* bp; // Reset old values for (i = 1; i < modelData->nofBoundaryPoints; i++) { bp = modelData->boundaryPoints[i]; bp->meshDensityType = ' '; bp->meshDensityValue = 0; // Delete density values also from any vertex if ( bp->vertexTag != NO_INDEX ) { v = model->getVertexByTag(bp->vertexTag); if ( v != NULL ) { v->setGridHValues(NO_INDEX, ' ', 0, true); } } } getMeshDensityValues(mesh_index, dtype, nof_dvalues, dvalues); if ( nof_dvalues < 2 || dtype == 'N' ) return; delta = dvalues[1] - dvalues[0]; BoundaryPoint* bp1; BoundaryPoint* bp2; // Calc total boundary length tot_length = 0.0; for (i = 1; i < modelData->nofBoundaryPoints; i++) { bp1 = modelData->boundaryPoints[i-1]; bp2 = modelData->boundaryPoints[i]; bp1->point->getPoint(p1); bp2->point->getPoint(p2); tot_length += dist3(p1, p2); } // Set values for the first point bp = modelData->boundaryPoints[0]; bp->meshDensityType = dtype; bp->meshDensityValue = dvalues[0]; if ( bp->vertexTag != NO_INDEX ) { v = model->getVertexByTag(bp->vertexTag); if ( v != NULL ) { v->setGridHValues(mesh_index, dtype, dvalues[0]); } } int last; // If closed, do not set value again for the first point! if (modelData->isClosedU) { last = modelData->nofBoundaryPoints - 1; } else { last = modelData->nofBoundaryPoints; } cum_length = 0.0; for (i = 1; i < last; i++) { bp1 = modelData->boundaryPoints[i-1]; bp2 = modelData->boundaryPoints[i]; bp1->point->getPoint(p1); bp2->point->getPoint(p2); cum_length += dist3(p1, p2); double dvalue = dvalues[0] + (cum_length / tot_length) * delta; bp2->meshDensityType = dtype; bp2->meshDensityValue = dvalue; if ( bp2->vertexTag != NO_INDEX ) { v = model->getVertexByTag(bp2->vertexTag); if ( v != NULL ) { v->setGridHValues(mesh_index, dtype, dvalue); } } } } void BodyElement::setElementGroupId(int gr_id) { elementGroupId = gr_id; } void BodyElement::setElementGroupTag(int gr_tag) { elementGroupTag = gr_tag; } void BodyElement::setBoundaryTag(int tag) { boundaryTag = tag; } void BodyElement::setDiscretizationData(int nof_components, linDeltaType* types, double* valuesU, double* valuesV, bool* useFixedN) { if ( ptrGmtr == NULL ) return; ptrGmtr->setDiscretizationData(nof_components, types, valuesU, valuesV, useFixedN); } void BodyElement::setMeshElementDir(int index, short direction) { if ( meshData == NULL || meshData->nofMeshElements == 0 ) return; if ( index < 0 || index >= meshData->nofMeshElements) return; meshData->meshElementDirs[index] = direction; } void BodyElement::setGridHData(int nof_ids, int* grid_h_ids, int* mesh_indices, bool force) { if ( gridHData == NULL ) { if ( nof_ids > 0 ) { gridHData = new BodyElementGridHData(); } else { return; } } gridHData->setData(nof_ids, grid_h_ids, mesh_indices); } void BodyElement::setGridHValues(int mesh_index, char value_type, double value, bool force) { if ( gridHData == NULL ) { gridHData = new BodyElementGridHData(); } gridHData->setData(mesh_index, value_type, value, force); #if 0 if ( value_type == 'N' ) { ptrGmtr->setDeltaU(LIN_DELTA_N, value); } else if ( value_type == 'H' ) { ptrGmtr->setDeltaU(LIN_DELTA_H, value); } else if ( value_type == 'R' ) { ptrGmtr->setDeltaU(LIN_DELTA_H, value * model->getMeshH(mesh_index)); } ptrGmtr->calcBoundaryPoints(); #endif } void BodyElement::setIsIntraLayerBoundary(bool value) { if ( modelData != NULL ) { modelData->isIntraLayerBoundary = value; } } void BodyElement::setName(char* new_name) { update_dyna_string(name, new_name); } void BodyElement::setParentId(short parent_nbr, int parent_id) { if ( modelData == NULL ) return; if ( parent_nbr == 1 ) { modelData->parent1Id = parent_id; } else { modelData->parent2Id = parent_id; } } void BodyElement::setParentIds(int parent1_id, int parent2_id) { if ( modelData == NULL ) return; modelData->parent1Id = parent1_id; modelData->parent2Id = parent2_id; } void BodyElement::setParentLayer(short parent_nbr, int layer) { if ( modelData == NULL ) return; if ( parent_nbr == 1 ) { modelData->parent1Layer = layer; } else { modelData->parent2Layer = layer; } } void BodyElement::setParentLayers(int parent1_layer, int parent2_layer) { if ( modelData == NULL ) return; modelData->parent1Layer = parent1_layer; modelData->parent2Layer = parent2_layer; } void BodyElement::setParentTag(short parent_nbr, int parent_tag) { if ( modelData == NULL ) return; if ( parent_nbr == 1 ) { modelData->parent1Tag = parent_tag; } else { modelData->parent2Tag = parent_tag; } } void BodyElement::setParentTags(int parent1_tag, int parent2_tag) { if ( modelData == NULL ) return; modelData->parent1Tag = parent1_tag; modelData->parent2Tag = parent2_tag; } beStatus BodyElement::setStatus(beStatus new_status) { if ( modelData == NULL ) return BE_NONE; else return modelData->status = new_status; } void BodyElement::storeName() { create_dyna_string(name_old, name); } // Add new data into element // // NOTE: Only non-geometry related data is update here! // void BodyElement::update(ecif_Element_X& tx) { if ( tx.name != NULL ) { update_dyna_string(name, tx.name); } if ( tx.bndr_cond_id != NO_INDEX ) { txBndrConditionId = tx.bndr_cond_id; } if ( tx.bndr_param_id != NO_INDEX ) { boundaryParameterId = tx.bndr_param_id; } if ( tx.bndr_tag != NO_INDEX ) { boundaryTag = tx.bndr_tag; checkLastBoundaryTag(); } if ( tx.bndr_group_tag != NO_INDEX ) { elementGroupTag = tx.bndr_group_tag; } if ( tx.nof_gridh_ids > 0 ) { gridHData = new BodyElementGridHData(tx.nof_gridh_ids, tx.gridh_ids, tx.gridh_mesh_indices); } } bool BodyElement::updateGeometry() { IdList vertex_tags; if ( ptrGmtr != NULL ) { if ( !ptrGmtr->updateGeometry(tag, vertex_tags) ) return false; } update(); return true; } void BodyElement::update() { initLabelData(); if ( modelData != NULL && ptrGmtr != NULL ) { modelData->isClosedU = ptrGmtr->isClosedU(); modelData->isClosedV = ptrGmtr->isClosedV(); } }