HoneycombMeshGenerator.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "HoneycombMeshGenerator.hpp"
00038
00039 #include <boost/foreach.hpp>
00040 #include "TrianglesMeshReader.hpp"
00041 #include "OutputFileHandler.hpp"
00042 #include "RandomNumberGenerator.hpp"
00043 #include "MathsCustomFunctions.hpp"
00044 #include "ChasteSyscalls.hpp"
00045
00046 HoneycombMeshGenerator::HoneycombMeshGenerator(unsigned numNodesAlongWidth, unsigned numNodesAlongLength, unsigned ghosts, double scaleFactor)
00047 : mpMesh(NULL),
00048 mMeshFilename("mesh"),
00049 mDomainWidth(numNodesAlongWidth*scaleFactor),
00050 mNumCellWidth(numNodesAlongWidth),
00051 mNumCellLength(numNodesAlongLength)
00052 {
00053
00054 assert(PetscTools::IsSequential());
00055
00056
00057 assert(scaleFactor > 0.0);
00058
00059
00060 std::stringstream pid;
00061 pid << getpid();
00062 OutputFileHandler output_file_handler("2D_temporary_honeycomb_mesh_" + pid.str());
00063 std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
00064
00065 unsigned num_nodes_along_width = mNumCellWidth;
00066 unsigned num_nodes_along_length = mNumCellLength;
00067 double horizontal_spacing = mDomainWidth / (double)num_nodes_along_width;
00068 double vertical_spacing = (sqrt(3.0)/2)*horizontal_spacing;
00069
00070
00071 mDomainDepth = (double)(num_nodes_along_length) * vertical_spacing;
00072
00073
00074 num_nodes_along_width += 2*ghosts;
00075 num_nodes_along_length += 2*ghosts;
00076
00077 unsigned num_nodes = num_nodes_along_width*num_nodes_along_length;
00078 unsigned num_elem_along_width = num_nodes_along_width-1;
00079 unsigned num_elem_along_length = num_nodes_along_length-1;
00080 unsigned num_elem = 2*num_elem_along_width*num_elem_along_length;
00081 unsigned num_edges = 3*num_elem_along_width*num_elem_along_length + num_elem_along_width + num_elem_along_length;
00082
00083 double x0 = -horizontal_spacing*ghosts;
00084 double y0 = -vertical_spacing*ghosts;
00085
00086 mBottom = -vertical_spacing*ghosts;
00087 mTop = mBottom + vertical_spacing*(num_nodes_along_length-1);
00088
00089
00090 out_stream p_node_file = output_file_handler.OpenOutputFile(mMeshFilename+".node");
00091 (*p_node_file) << std::scientific;
00092 (*p_node_file) << std::setprecision(20);
00093 (*p_node_file) << num_nodes << "\t2\t0\t1" << std::endl;
00094
00095 unsigned node = 0;
00096 for (unsigned i=0; i<num_nodes_along_length; i++)
00097 {
00098 for (unsigned j=0; j<num_nodes_along_width; j++)
00099 {
00100 if (i<ghosts || i>=(ghosts+mNumCellLength))
00101 {
00102 mGhostNodeIndices.insert(node);
00103 }
00104 else if (j < ghosts || j >= (ghosts+mNumCellWidth))
00105 {
00106 mGhostNodeIndices.insert(node);
00107 }
00108 unsigned boundary = 0;
00109 if (i==0 || i==num_nodes_along_length-1 || j==0 || j==num_nodes_along_width-1)
00110 {
00111 boundary = 1;
00112 }
00113
00114 double x = x0 + horizontal_spacing*((double)j + 0.25*(1.0+ SmallPow(-1.0,i+1)));
00115 double y = y0 + vertical_spacing*(double)i;
00116
00117
00118 if ( (y<0.0) && (y>-1e-12) )
00119 {
00120
00121 #define COVERAGE_IGNORE
00122 y = 0.0;
00123 #undef COVERAGE_IGNORE
00124 }
00125
00126 (*p_node_file) << node++ << "\t" << x << "\t" << y << "\t" << boundary << std::endl;
00127 }
00128 }
00129 p_node_file->close();
00130
00131
00132 out_stream p_elem_file = output_file_handler.OpenOutputFile(mMeshFilename+".ele");
00133 (*p_elem_file) << std::scientific;
00134
00135 out_stream p_edge_file = output_file_handler.OpenOutputFile(mMeshFilename+".edge");
00136 (*p_node_file) << std::scientific;
00137
00138 (*p_elem_file) << num_elem << "\t3\t0" << std::endl;
00139 (*p_edge_file) << num_edges << "\t1" << std::endl;
00140
00141 unsigned elem = 0;
00142 unsigned edge = 0;
00143 for (unsigned i=0; i<num_elem_along_length; i++)
00144 {
00145 for (unsigned j=0; j < num_elem_along_width; j++)
00146 {
00147 unsigned node0 = i*num_nodes_along_width + j;
00148 unsigned node1 = i*num_nodes_along_width + j+1;
00149 unsigned node2 = (i+1)*num_nodes_along_width + j;
00150
00151 if (i%2 != 0)
00152 {
00153 node2 = node2 + 1;
00154 }
00155
00156 (*p_elem_file) << elem++ << "\t" << node0 << "\t" << node1 << "\t" << node2 << std::endl;
00157
00158 unsigned horizontal_edge_is_boundary_edge = 0;
00159 unsigned vertical_edge_is_boundary_edge = 0;
00160 if (i==0)
00161 {
00162 horizontal_edge_is_boundary_edge = 1;
00163 }
00164 if (j==0 && i%2==0)
00165 {
00166 vertical_edge_is_boundary_edge = 1;
00167 }
00168
00169 (*p_edge_file) << edge++ << "\t" << node0 << "\t" << node1 << "\t" << horizontal_edge_is_boundary_edge << std::endl;
00170 (*p_edge_file) << edge++ << "\t" << node1 << "\t" << node2 << "\t" << 0 << std::endl;
00171 (*p_edge_file) << edge++ << "\t" << node2 << "\t" << node0 << "\t" << vertical_edge_is_boundary_edge << std::endl;
00172
00173 node0 = i*num_nodes_along_width + j + 1;
00174
00175 if (i%2 != 0)
00176 {
00177 node0 = node0 - 1;
00178 }
00179 node1 = (i+1)*num_nodes_along_width + j+1;
00180 node2 = (i+1)*num_nodes_along_width + j;
00181
00182 (*p_elem_file) << elem++ << "\t" << node0 << "\t" << node1 << "\t" << node2 << std::endl;
00183 }
00184 }
00185
00186 for (unsigned i=0; i<num_elem_along_length; i++)
00187 {
00188 unsigned node0, node1;
00189
00190 if (i%2==0)
00191 {
00192 node0 = (i+1)*num_nodes_along_width - 1;
00193 node1 = (i+2)*num_nodes_along_width - 1;
00194 }
00195 else
00196 {
00197 node0 = (i+1)*num_nodes_along_width;
00198 node1 = (i)*num_nodes_along_width;
00199 }
00200 (*p_edge_file) << edge++ << "\t" << node0 << "\t" << node1 << "\t" << 1 << std::endl;
00201 }
00202
00203 for (unsigned j=0; j<num_elem_along_width; j++)
00204 {
00205 unsigned node0 = num_nodes_along_width*(num_nodes_along_length-1) + j;
00206 unsigned node1 = num_nodes_along_width*(num_nodes_along_length-1) + j+1;
00207 (*p_edge_file) << edge++ << "\t" << node1 << "\t" << node0 << "\t" << 1 << std::endl;
00208 }
00209
00210 p_elem_file->close();
00211 p_edge_file->close();
00212
00213
00214
00215 {
00216 TrianglesMeshReader<2,2> mesh_reader(output_dir + mMeshFilename);
00217 mpMesh = new MutableMesh<2,2>;
00218 mpMesh->ConstructFromMeshReader(mesh_reader);
00219 }
00220
00221
00222 output_file_handler.FindFile("").Remove();
00223
00224
00225 mpMesh->SetMeshHasChangedSinceLoading();
00226 }
00227
00228 HoneycombMeshGenerator::~HoneycombMeshGenerator()
00229 {
00230 delete mpMesh;
00231 }
00232
00233 MutableMesh<2,2>* HoneycombMeshGenerator::GetMesh()
00234 {
00235 return mpMesh;
00236 }
00237
00238 std::vector<unsigned> HoneycombMeshGenerator::GetCellLocationIndices()
00239 {
00240 std::vector<unsigned> location_indices;
00241
00242 for (unsigned i=0; i<mpMesh->GetNumNodes(); i++)
00243 {
00244 if (mGhostNodeIndices.find(i)==mGhostNodeIndices.end())
00245 {
00246 location_indices.push_back(i);
00247 }
00248 }
00249 return location_indices;
00250 }
00251
00252 MutableMesh<2,2>* HoneycombMeshGenerator::GetCircularMesh(double radius)
00253 {
00254 if (!mGhostNodeIndices.empty())
00255 {
00256 EXCEPTION("Cannot call GetCircularMesh on a HoneycombMesh with ghost nodes");
00257 }
00258
00259
00260 c_vector<double,2> centre = zero_vector<double>(2);
00261 for (unsigned i=0; i<mpMesh->GetNumNodes(); i++)
00262 {
00263 centre += mpMesh->GetNode(i)->rGetLocation();
00264 }
00265 centre /= (double)mpMesh->GetNumNodes();
00266
00267 mpMesh->Translate(-centre[0], -centre[1]);
00268
00269
00270 for (unsigned i=0; i<mpMesh->GetNumAllNodes(); i++)
00271 {
00272 if (norm_2(mpMesh->GetNode(i)->rGetLocation()) >= radius)
00273 {
00274 mpMesh->DeleteNodePriorToReMesh(i);
00275 }
00276 else
00277 {
00278
00279 c_vector<double,2>& r_location = mpMesh->GetNode(i)->rGetModifiableLocation();
00280 c_vector<double,2> shift;
00281 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00282 double max_jiggle = radius*5e-6;
00283 shift[0] = max_jiggle*(p_gen->ranf()-0.5);
00284 shift[1] = max_jiggle*(p_gen->ranf()-0.5);
00285 r_location += shift;
00286 }
00287 }
00288
00289
00290 NodeMap map(mpMesh->GetNumNodes());
00291 mpMesh->ReMesh(map);
00292
00293 return mpMesh;
00294 }
00295
00296 double HoneycombMeshGenerator::GetDomainDepth()
00297 {
00298 return mDomainDepth;
00299 }
00300
00301 double HoneycombMeshGenerator::GetDomainWidth()
00302 {
00303 return mDomainWidth;
00304 }