⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 localmeshcoarsening.cpp

📁 利用C
💻 CPP
字号:
// Copyright (C) 2006 Johan Hoffman.// Licensed under the GNU LGPL Version 2.1.//// Modified by Anders Logg, 2008.// // First added:  2006-11-01// Last changed: 2008-05-28#include <list>#include <dolfin/math/dolfin_math.h>#include <dolfin/log/dolfin_log.h>#include "Mesh.h"#include "MeshTopology.h"#include "MeshGeometry.h"#include "MeshData.h"#include "MeshConnectivity.h"#include "MeshEditor.h"#include "MeshFunction.h"#include "Vertex.h"#include "Edge.h"#include "Cell.h"#include "BoundaryMesh.h"#include "MeshGeometry.h"#include "LocalMeshCoarsening.h"#include "CellType.h"#include "TriangleCell.h"#include "TetrahedronCell.h"using namespace dolfin;//-----------------------------------------------------------------------------void LocalMeshCoarsening::coarsenMeshByEdgeCollapse(Mesh& mesh,                                                     MeshFunction<bool>& cell_marker,                                                    bool coarsen_boundary){  message("Coarsen simplicial mesh by edge collapse.");  // Get size of old mesh  //const uint num_vertices = mesh.size(0);  const uint num_cells = mesh.size(mesh.topology().dim());    // Check cell marker   if ( cell_marker.size() != num_cells ) error("Wrong dimension of cell_marker");    // Generate cell - edge connectivity if not generated  mesh.init(mesh.topology().dim(), 1);    // Generate edge - vertex connectivity if not generated  mesh.init(1, 0);    // Get cell type  //const CellType& cell_type = mesh.type();    // Create new mesh  Mesh coarse_mesh(mesh);    // Initialise forbidden cells   MeshFunction<bool> cell_forbidden(mesh);    cell_forbidden.init(mesh.topology().dim());  for (CellIterator c(mesh); !c.end(); ++c)    cell_forbidden.set(c->index(),false);    // Init new vertices and cells  Array<int> old2new_cell(mesh.numCells());  Array<int> old2new_vertex(mesh.numVertices());  std::list<int> cells_to_coarsen(0);  // Compute cells to delete  for (CellIterator c(mesh); !c.end(); ++c)  {    if (cell_marker.get(*c) == true)    {      cells_to_coarsen.push_back(c->index());      //cout << "coarsen midpoint: " << c->midpoint() << endl;    }  }  // Define cell mapping between old and new mesh  for (CellIterator c(mesh); !c.end(); ++c)  {    old2new_cell[c->index()] = c->index();  }  bool improving = true;  while(improving)  {    uint presize = cells_to_coarsen.size();    //cout << "presize: " << presize << endl;    for(std::list<int>::iterator iter = cells_to_coarsen.begin();	iter != cells_to_coarsen.end(); iter++)    {      // Map cells to new mesh      if(*iter >= 0)      {	*iter = old2new_cell[*iter];      }    }    old2new_cell.resize(mesh.numCells());    old2new_vertex.resize(mesh.numVertices());    // Coarsen cells in list    for(std::list<int>::iterator iter = cells_to_coarsen.begin();	iter != cells_to_coarsen.end(); iter++)    {      bool mesh_ok = false;      int cid = *iter;      if(cid != -1)      {	mesh_ok = coarsenCell(mesh, coarse_mesh, cid,			      old2new_vertex, old2new_cell,			      coarsen_boundary);	if(!mesh_ok)	{	  warning("Mesh not ok");	}	else	{	  mesh = coarse_mesh;	  cells_to_coarsen.erase(iter);	  break;	}      }    }    if(presize == cells_to_coarsen.size())    {      break;    }  }}//-----------------------------------------------------------------------------void LocalMeshCoarsening::collapseEdge(Mesh& mesh, Edge& edge,                                        Vertex& vertex_to_remove,                                        MeshFunction<bool>& cell_to_remove,                                        Array<int>& old2new_vertex,                                        Array<int>& old2new_cell,                                        MeshEditor& editor,                                        uint& current_cell) {  const CellType& cell_type = mesh.type();  Array<uint> cell_vertices(cell_type.numEntities(0));  uint vert_slave = vertex_to_remove.index();  uint vert_master = 0;   uint* edge_vertex = edge.entities(0);  //cout << "edge vertices: " << edge_vertex[0] << " " << edge_vertex[1] << endl;  //cout << "vertex: " << vertex_to_remove.index() << endl;  if ( edge_vertex[0] == vert_slave )     vert_master = edge_vertex[1];   else if ( edge_vertex[1] == vert_slave )     vert_master = edge_vertex[0];   else    error("Node to delete and edge to collapse not compatible.");  for (CellIterator c(vertex_to_remove); !c.end(); ++c)  {    if ( cell_to_remove.get(*c) == false )     {      uint cv_idx = 0;      for (VertexIterator v(*c); !v.end(); ++v)      {          if ( v->index() == vert_slave )	  cell_vertices[cv_idx++] = old2new_vertex[vert_master];         else	  cell_vertices[cv_idx++] = old2new_vertex[v->index()];      }      //cout << "adding new cell" << endl;      editor.addCell(current_cell++, cell_vertices);      // Update cell map      old2new_cell[c->index()] = current_cell - 1;    }      }  }//-----------------------------------------------------------------------------bool LocalMeshCoarsening::coarsenCell(Mesh& mesh, Mesh& coarse_mesh,				      int cellid,				      Array<int>& old2new_vertex,				      Array<int>& old2new_cell,				      bool coarsen_boundary){  cout << "coarsenCell: " << cellid << endl;  cout << "numCells: " << mesh.numCells() << endl;  const uint num_vertices = mesh.size(0);  const uint num_cells = mesh.size(mesh.topology().dim());  // Initialise forbidden verticies     MeshFunction<bool> vertex_forbidden(mesh);    vertex_forbidden.init(0);  for (VertexIterator v(mesh); !v.end(); ++v)    vertex_forbidden.set(v->index(),false);  // Initialise boundary verticies     MeshFunction<bool> vertex_boundary(mesh);    vertex_boundary.init(0);  for (VertexIterator v(mesh); !v.end(); ++v)    vertex_boundary.set(v->index(),false);  BoundaryMesh boundary(mesh);  MeshFunction<uint>* bnd_vertex_map = boundary.data().meshFunction("vertex map");  dolfin_assert(bnd_vertex_map);  for (VertexIterator v(boundary); !v.end(); ++v)    vertex_boundary.set(bnd_vertex_map->get(v->index()),true);  // If coarsen boundary is forbidden   if ( coarsen_boundary == false )  {    for (VertexIterator v(boundary); !v.end(); ++v)      vertex_forbidden.set(bnd_vertex_map->get(v->index()),true);  }  // Initialise data for finding which vertex to remove     bool collapse_edge = false;  uint* edge_vertex;  uint shortest_edge_index = 0;  real lmin, l;  uint num_cells_to_remove = 0;    // Get cell type  const CellType& cell_type = mesh.type();  Cell c(mesh, cellid);  MeshEditor editor;  editor.open(coarse_mesh, cell_type.cellType(),	      mesh.topology().dim(), mesh.geometry().dim());  MeshFunction<bool> cell_to_remove(mesh);    cell_to_remove.init(mesh.topology().dim());  for (CellIterator ci(mesh); !ci.end(); ++ci)    cell_to_remove.set(ci->index(), false);  MeshFunction<bool> cell_to_regenerate(mesh);    cell_to_regenerate.init(mesh.topology().dim());  for (CellIterator ci(mesh); !ci.end(); ++ci)    cell_to_regenerate.set(ci->index(), false);  // Find shortest edge of cell c  collapse_edge = false;  lmin = 1.0e10 * c.diameter();  for (EdgeIterator e(c); !e.end(); ++e)  {    edge_vertex = e->entities(0);    if ( (vertex_forbidden.get(edge_vertex[0]) == false) || 	 (vertex_forbidden.get(edge_vertex[1]) == false) )    {      l = e->length();      if ( lmin > l )      {	lmin = l;	shortest_edge_index = e->index(); 	collapse_edge = true;      }    }  }    Edge shortest_edge(mesh, shortest_edge_index);  // Decide which vertex to remove  uint vert2remove_idx = 0;      // If at least one vertex should be removed   if ( collapse_edge == true )  {    edge_vertex = shortest_edge.entities(0);        if(vertex_forbidden.get(edge_vertex[0]) &&       vertex_forbidden.get(edge_vertex[1]))    {      // Both vertices are forbidden, cannot coarsen      cout << "both vertices forbidden" << endl;      editor.close();      return false;    }    if(vertex_forbidden.get(edge_vertex[0]) == true)    {      vert2remove_idx = edge_vertex[1];    }    else if(vertex_forbidden.get(edge_vertex[1]) == true)    {      vert2remove_idx = edge_vertex[0];    }    else if(vertex_boundary.get(edge_vertex[1]) == true &&	    vertex_boundary.get(edge_vertex[0]) == false)    {      vert2remove_idx = edge_vertex[0];    }    else if(vertex_boundary.get(edge_vertex[0]) == true &&	    vertex_boundary.get(edge_vertex[1]) == false)    {      vert2remove_idx = edge_vertex[1];    }    else if ( edge_vertex[0] > edge_vertex[1] )     {      vert2remove_idx = edge_vertex[0];    }    else    {      vert2remove_idx = edge_vertex[1];    }             }  else  {    // No vertices to remove, cannot coarsen    cout << "all vertices forbidden" << endl;    editor.close();    return false;  }  Vertex vertex_to_remove(mesh, vert2remove_idx);  //cout << "edge vertices2: " << edge_vertex[0] << " " << edge_vertex[1] << endl;  //cout << "vertex2: " << vertex_to_remove.index() << endl;  //cout << "collapse: " << collapse_edge << endl;  // Remove cells around edge   num_cells_to_remove = 0;  for (CellIterator cn(shortest_edge); !cn.end(); ++cn)  {    cell_to_remove.set(cn->index(),true);    num_cells_to_remove++;    // Update cell map    old2new_cell[cn->index()] = -1;  }  // Regenerate cells around vertex  for (CellIterator cn(vertex_to_remove); !cn.end(); ++cn)  {    cell_to_regenerate.set(cn->index(),true);    // Update cell map (will be filled in with correct index)    old2new_cell[cn->index()] = -1;  }    // Specify number of vertices and cells  editor.initVertices(num_vertices - 1);  editor.initCells(num_cells - num_cells_to_remove);    cout << "Number of cells in old mesh: " << num_cells << "; to remove: " <<    num_cells_to_remove << endl;  // Add old vertices  uint vertex = 0;  for(VertexIterator v(mesh); !v.end(); ++v)  {    if(vertex_to_remove.index() == v->index())     {      old2new_vertex[v->index()] = -1;    }    else    {      //cout << "adding old vertex at: " << v->point() << endl;      old2new_vertex[v->index()] = vertex;      editor.addVertex(vertex++, v->point());    }  }  // Add old unrefined cells   uint cv_idx;  uint current_cell = 0;  Array<uint> cell_vertices(cell_type.numEntities(0));  for (CellIterator c(mesh); !c.end(); ++c)  {    if(cell_to_remove.get(*c) == false && cell_to_regenerate(*c) == false)    {      cv_idx = 0;      for (VertexIterator v(*c); !v.end(); ++v)        cell_vertices[cv_idx++] = old2new_vertex[v->index()];       //cout << "adding old cell" << endl;      editor.addCell(current_cell++, cell_vertices);      // Update cell maps      old2new_cell[c->index()] = current_cell - 1;    }  }    // Add new cells.   collapseEdge(mesh, shortest_edge, vertex_to_remove, cell_to_remove,	       old2new_vertex, old2new_cell, editor, current_cell);  editor.close();  // Set volume tolerance. This parameter detemines a quality criterion   // for the new mesh: higher value indicates a sharper criterion.   real vol_tol = 1.0e-3;   bool mesh_ok = true;  Cell removed_cell(mesh, cellid);  // Check mesh quality (volume)  for (CellIterator c(removed_cell); !c.end(); ++c)  {    uint id = c->index();    int nid = old2new_cell[id];    if(nid != -1)    {      Cell cn(coarse_mesh, nid);      real qm = cn.volume() / cn.diameter();      if(qm < vol_tol)      {	warning("Cell quality too low");	cout << "qm: " << qm << endl;	mesh_ok = false;	return mesh_ok;      }    }  }  // Checking for inverted cells  for (CellIterator c(removed_cell); !c.end(); ++c)  {    uint id = c->index();    int nid = old2new_cell[id];    if(nid != -1)    {      Cell cn(coarse_mesh, nid);      if(c->orientation() != cn.orientation())      {	cout << "cell orientation inverted" << endl;	mesh_ok = false;	return mesh_ok;      }    }  }  return mesh_ok;}//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -