Example #1
0
/* A malha deve estar alocada.
 * */
void MeshIoMsh::readFileMsh(const char* filename, Mesh * mesh)
{
    /*
     * O que é feito:
     *
     * 1) primeiramente lê-se apenas as células (conectividade clássica);
     * 2) depois são construídos as facet-edges e(ou) facet-faces, lendo-se
     *    os elementos de dimensões menores.
     *
     * */

    FEPIC_ASSERT(mesh, "invalid mesh pointer", std::invalid_argument);


    this->fi_registerFile(filename, ".msh");

    FILE * file_ptr = fopen(filename, "r");

    double  coord[3];
    int     type_tag;
    char    buffer[256];
    std::tr1::shared_ptr<Point> p_ptr(new Point());
    std::tr1::shared_ptr<Cell> c_ptr(mesh->createCell());

    int const spacedim = mesh->spaceDim();
    FEPIC_ASSERT(spacedim>0 && spacedim < 4, "mesh has invalid spacedim", std::invalid_argument);

    long    nodes_file_pos;  // $Nodes
    long    elems_file_pos;  // $Elements

    // nós
    nodes_file_pos = find_keyword("$Nodes", 6, file_ptr);
    //nodes_file_pos++;  // only to avoid gcc warning: variable ‘nodes_file_pos’ set but not used [-Wunused-but-set-variable]

    FEPIC_ASSERT(nodes_file_pos>0, "invalid file format", std::invalid_argument);

    int num_pts(0);
    int node_number(0);
    if ( EOF == fscanf(file_ptr, "%d", &num_pts) )
        FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);

    //mesh->resizePointL(num_pts);

    //mesh->printInfo();
    //std::cout << "DEBUGGGGGGGGGGGGGGGGGGG:  "<<mesh << std::endl;
    //printf("DEBUGGGGGGGGGGGGGGGGGGGGGGGGGGG num_pts=%d; numNodesTotal()=%d; numNodes()=%d\n",num_pts,mesh->numNodesTotal(), mesh->numNodes());

    if (NULL == fgets(buffer, sizeof(buffer), file_ptr)) // escapa do \n
        FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
    for (int i=0; i< num_pts; ++i)
    {
        if ( NULL == fgets(buffer, sizeof(buffer), file_ptr) )
            FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
        sscanf(buffer, "%d %lf %lf %lf", &node_number, &coord[0], &coord[1], &coord[2]);
        FEPIC_ASSERT(node_number==i+1, "wrong file format", std::invalid_argument);
        p_ptr->setCoord(coord, spacedim);
        //mesh->getNodePtr(i)->setCoord(coord,spacedim);
        mesh->pushPoint(p_ptr.get());
    }
    // os pontos não estão completas: falta atribuir os labels

    // contagem de elementos e alocação

    elems_file_pos = find_keyword("$Elements", 9, file_ptr);

    FEPIC_ASSERT(elems_file_pos>0, "invalid file format", std::invalid_argument);

    int num_cells=0;
    int num_elms;

    if (EOF == fscanf(file_ptr, "%d", &num_elms) )
        FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);

    /* ---------------------------------------
     * Detectando a ordem da malha, verificando sequencia dos elementos,
     * e contando o número de células.
     * --------------------------------------- */
    const int meshm_cell_msh_tag = mesh->cellMshTag();

    if (mshTag2ctype(EMshTag(meshm_cell_msh_tag)) != mesh->cellType())
    {
        //FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
        printf("ERROR: ctype2mshTag() = %d\n", ctype2mshTag(mesh->cellType()));
        printf("ERROR: cell->getMshTag() = %d\n", c_ptr->getMshTag());
        throw;
    }


    bool wrong_file_err=true;
    int  elem_number;               // contagem para verificação de erros.
    for (int k = 0; k < num_elms; ++k)
    {

        if (EOF == fscanf(file_ptr, "%d %d", &elem_number, &type_tag) )
            FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);

        // check sequence
        if (elem_number != k+1)
        {
            wrong_file_err=true;
            break;
        }

        // check type
        if (type_tag == meshm_cell_msh_tag)
        {
            wrong_file_err=false;
            ++num_cells;
        }

        if (!fgets(buffer, sizeof(buffer), file_ptr) || feof(file_ptr))
        {
            wrong_file_err=true;
            break;
        }

    }
    FEPIC_ASSERT(!wrong_file_err, "Wrong file format. Make sure you created the mesh with correct file format. ", std::invalid_argument);

    Cell*  cell;
    //cell = Cell::create(mesh->cellType());



    /* --------------------------------------
     * Lendo as células
     * -------------------------------------- */
    fseek (file_ptr , elems_file_pos , SEEK_SET );
    if (EOF == fscanf(file_ptr, "%d", &num_elms) )
        FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);

    this->timer.restart();

    int  inc(0);
    int  nodes_per_cell = mesh->nodesPerCell();
    int  id_aux;
    int  numm_tags;
    int  elm_dim;
    int  physical;
    int const cell_dim = mesh->cellDim();
    int const cell_msh_tag = mesh->cellMshTag();
    for (int k=0; k < num_elms; ++k)
    {
        if ( EOF == fscanf(file_ptr, "%d %d %d %d", &elem_number, &type_tag, &numm_tags, &physical) )
            FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);

        // sincronização
        FEPIC_ASSERT(elem_number==k+1, "invalid file format", std::invalid_argument);

        for (int j=1; j<numm_tags; ++j)
        {
            if ( EOF == fscanf(file_ptr, "%s", buffer) )
                FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
        }

        elm_dim = dimForMshTag(EMshTag(type_tag));

        if (elm_dim==0)
        {
            if ( EOF == fscanf(file_ptr, "%d", &id_aux) )
                FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
            --id_aux;
            mesh->getNodePtr(id_aux)->setTag(physical);
        }
        else if (elm_dim == cell_dim)
        {
            cell = mesh->pushCell((int*)0);
            ++inc;
            FEPIC_ASSERT(cell_msh_tag == type_tag, "Invalid cell or invalid mesh", std::runtime_error);
            for (int i=0; i< nodes_per_cell; ++i)
            {
                if ( EOF == fscanf(file_ptr, "%d", &id_aux) )
                    FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
                cell->setNodeId(i, id_aux-1);
            }
            cell->setTag(physical);
            //mesh->pushCell(cell);
        }
        else
        {
            if ( NULL == fgets(buffer, sizeof(buffer), file_ptr) )
                FEPIC_ASSERT(false, "invalid msh format", std::runtime_error);
        }
    }// end for k


    this->timer.elapsed("readFileMsh(): read connectivity");
    // até aqui, apenas foi lido a conectividade
    //

    /* constroi as facets e Corners */
    if (mesh->qBuildAdjacency())
        mesh->buildAdjacency();
    else
    {
        fclose(file_ptr);
        return;
    }

    /*
    ___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|__
    _|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___| */

    this->timer.restart();
    /* Procura por elementos no contorno que coincidam com as facets. Quando encontrados,
     * os labels são propagados para as respectivas facet que por sua vez propagam os
     * labels para seus nós. Os labels só são propagados se eles não foram definidos
     * nos nós anteriormente.
     */
    fseek (file_ptr , elems_file_pos , SEEK_SET );
    fscanf(file_ptr, "%d", &num_elms);

    int n_nodes               = mesh->nodesPerCell();
    //int n_vertices_per_facet  = mesh->verticesPerFacet();
    int n_nodes_per_facet     = mesh->nodesPerFacet();
    //int n_vertices_per_corner = mesh->verticesPerCorner();
    int n_nodes_per_corner    = mesh->nodesPerCorner();


    int* nodes  = new int[n_nodes_per_facet];      // facet nodes
    //int* vtcs   = new int[n_vertices_per_facet];
    int* bnodes = new int[n_nodes_per_corner];     // corner nodes
    //int* bvtcs  = new int[n_vertices_per_corner];
    int facet_id;
    int corner_id;

    for (int k=0; k < num_elms; ++k)
    {

        fscanf(file_ptr, "%d %d %d %d", &elem_number, &type_tag, &numm_tags, &physical);

        //// sincronização
        //FEPIC_ASSERT(elem_number==k+1, "invalid file format", std::invalid_argument);

        for (int j=1; j<numm_tags; ++j)
        {
            fscanf(file_ptr, "%s", buffer);
        }

        elm_dim = dimForMshTag(EMshTag(type_tag));

        if ((elm_dim == 0) && (cell_dim!=2))
        {
            fscanf(file_ptr, "%d", &id_aux);
        }
        else if (elm_dim == cell_dim-1) // facets
        {
            for (int i=0; i<n_nodes_per_facet; ++i)
            {
                fscanf(file_ptr, "%d", &nodes[i]);
                --nodes[i];
                if (mesh->getNodePtr(nodes[i])->getTag() == 0)
                    mesh->getNodePtr(nodes[i])->setTag(physical);
            }
            //std::copy( nodes, nodes + n_vertices_per_facet, vtcs );
            if (cell_dim > 1)
            {
                if (mesh->getFacetIdFromVertices(nodes, facet_id))
                    mesh->getFacetPtr(abs(facet_id))->setTag(physical); //std::cout << (++TESTE) << std::endl;
                else
                {
                    printf("WARNING: INVALID FACET IN INPUT MESH! vtcs: ");
                    for (int zz = 0; zz < n_nodes_per_facet; ++zz)
                        printf("%d ", nodes[zz]);
                    printf("\n");
                }
            }
        }
        else if (elm_dim == cell_dim-2) // corners
        {
            for (int i=0; i<n_nodes_per_corner; ++i)
            {
                fscanf(file_ptr, "%d", &bnodes[i]);
                --bnodes[i];
                if (mesh->getNodePtr(bnodes[i])->getTag() == 0)
                    mesh->getNodePtr(bnodes[i])->setTag(physical);
            }
            //std::copy( bnodes, bnodes + n_vertices_per_corner, bvtcs );
            if (cell_dim>2)
            {
                if (mesh->getCornerIdFromVertices(bnodes, corner_id))
                {
                    mesh->getCornerPtr(abs(corner_id))->setTag(physical); //std::cout << (++TESTE) << std::endl;
                }
                else if (mesh->isVertex(mesh->getNodePtr(bnodes[0])) ) // if is vertex
                    printf("WARNING: INVALID CORNER IN INPUT MESH!\n");
            }
        }
        else
        {
            for (int i=0; i<n_nodes; ++i)
            {
                fscanf(file_ptr, "%d", &id_aux);
                --id_aux;

                if ((mesh->getNodePtr(id_aux)->getTag()) == 0)
                    mesh->getNodePtr(id_aux)->setTag(physical);
            }
        }


    }

    this->timer.elapsed("readFileMsh(): search for boundary elements");

    if (mesh->cellDim()>2)
    {
        const int n_corners_per_facet = mesh->numCornersPerFacet();
        // int facetm_facets[n_corners_per_facet];
        int *facetm_facets = new int [n_corners_per_facet];
        Facet const* facet;
        Corner* corner;
        for (int i = 0; i < mesh->numFacetsTotal(); ++i)
        {
            facet = mesh->getFacetPtr(i);
            if (facet->isDisabled())
                continue;
            mesh->getCellPtr(facet->getIncidCell())->getFacetCornersId(facet->getPosition(), facetm_facets);

            for (int j = 0; j < n_corners_per_facet; ++j)
            {
                corner = mesh->getCornerPtr(facetm_facets[j]);
                if (corner->getTag() == 0)
                    corner->setTag(facet->getTag());
            }
        }

        delete [] facetm_facets;
        facetm_facets = NULL;
    }

    if (mesh->cellDim()>1)
    {
        const int n_cells_total = mesh->numCellsTotal();
        Cell * cell;
        Facet * facet;
        for (int i = 0; i < n_cells_total; ++i)
        {
            cell = mesh->getCellPtr(i);
            if (cell->isDisabled())
                continue;
            for (int j = 0; j < mesh->numFacetsPerCell(); ++j)
            {
                facet = mesh->getFacetPtr(cell->getFacetId(j));

                if (facet->getTag() == 0)
                    facet->setTag(cell->getTag());
            }
        } // end loop
    } // endif

    fclose(file_ptr);
    //File.close();

    delete [] nodes;
    //delete [] vtcs;
    delete [] bnodes;
    //delete [] bvtcs;

    mesh->timer.addItems(this->timer);
}