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 #include "HoneycombMeshGenerator.hpp"
00030 #include "RandomNumberGenerator.hpp"
00031 #include "UblasCustomFunctions.hpp"
00032
00033
00034 HoneycombMeshGenerator::HoneycombMeshGenerator(unsigned numNodesAlongWidth, unsigned numNodesAlongLength, unsigned ghosts, bool cylindrical, double scaleFactor)
00035 : mpMesh(NULL),
00036 mDomainWidth(numNodesAlongWidth*scaleFactor),
00037 mNumCellWidth(numNodesAlongWidth),
00038 mNumCellLength(numNodesAlongLength),
00039 mCylindrical(cylindrical)
00040 {
00041 mGhostNodeIndices.empty();
00042
00043 std::stringstream pid;
00044
00045 assert(PetscTools::IsSequential());
00046 pid << getpid();
00047 mMeshFilename = "2D_temporary_honeycomb_mesh_" + pid.str();
00048 Make2dPeriodicMesh(mDomainWidth, ghosts);
00049 OutputFileHandler output_file_handler("");
00050 std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
00051
00052 TrianglesMeshReader<2,2> mesh_reader(output_dir + mMeshFilename);
00053
00054 if (!mCylindrical)
00055 {
00056 mpMesh = new MutableMesh<2,2>;
00057 mpMesh->ConstructFromMeshReader(mesh_reader);
00058 }
00059 else
00060 {
00061 mpMesh = new Cylindrical2dMesh(mDomainWidth);
00062 mpMesh->ConstructFromMeshReader(mesh_reader);
00063 NodeMap map(mpMesh->GetNumNodes());
00064 mpMesh->ReMesh(map);
00065 }
00066
00067
00068 std::string command = "rm " + output_dir + mMeshFilename + ".*";
00069 int return_value = system(command.c_str());
00070 if (return_value != 0)
00071 {
00072
00073 #define COVERAGE_IGNORE
00074 EXCEPTION("HoneycombMeshGenerator cannot delete temporary files\n");
00075 #undef COVERAGE_IGNORE
00076 }
00077 }
00078
00079
00080 HoneycombMeshGenerator::~HoneycombMeshGenerator()
00081 {
00082 delete mpMesh;
00083 }
00084
00085
00086 MutableMesh<2,2>* HoneycombMeshGenerator::GetMesh()
00087 {
00088 if (mCylindrical)
00089 {
00090 EXCEPTION("A cylindrical mesh was created but a normal mesh is being requested.");
00091 }
00092 return mpMesh;
00093 }
00094
00095
00096 Cylindrical2dMesh* HoneycombMeshGenerator::GetCylindricalMesh()
00097 {
00098 if (!mCylindrical)
00099 {
00100 EXCEPTION("A normal mesh was created but a cylindrical mesh is being requested.");
00101 }
00102 return (Cylindrical2dMesh*) mpMesh;
00103 }
00104
00105 std::vector<unsigned> HoneycombMeshGenerator::GetCellLocationIndices()
00106 {
00107 std::vector<unsigned> location_indices;
00108
00109 for (unsigned i=0; i<mpMesh->GetNumNodes(); i++)
00110 {
00111 if (mGhostNodeIndices.find(i)==mGhostNodeIndices.end())
00112 {
00113 location_indices.push_back(i);
00114 }
00115 }
00116 return location_indices;
00117 }
00118
00119 MutableMesh<2,2>* HoneycombMeshGenerator::GetCircularMesh(double radius)
00120 {
00121 assert(!mCylindrical);
00122
00123
00124 c_vector<double,2> centre = zero_vector<double>(2);
00125 for (unsigned i=0; i<mpMesh->GetNumNodes(); i++)
00126 {
00127 centre += mpMesh->GetNode(i)->rGetLocation();
00128 }
00129 centre /= (double)mpMesh->GetNumNodes();
00130
00131 mpMesh->Translate(-centre[0], -centre[1]);
00132
00133
00134
00135 for (unsigned i=0; i<mpMesh->GetNumAllNodes(); i++)
00136 {
00137 if ( norm_2(mpMesh->GetNode(i)->rGetLocation()) >= radius)
00138 {
00139 mpMesh->DeleteNodePriorToReMesh(i);
00140 }
00141 else
00142 {
00143
00144 c_vector<double,2>& r_location = mpMesh->GetNode(i)->rGetModifiableLocation();
00145 c_vector<double,2> shift;
00146 RandomNumberGenerator* p_gen = RandomNumberGenerator::Instance();
00147 double max_jiggle = radius*5e-6;
00148 shift[0] = max_jiggle*(p_gen->ranf()-0.5);
00149 shift[1] = max_jiggle*(p_gen->ranf()-0.5);
00150 r_location += shift;
00151 }
00152 }
00153
00154
00155 NodeMap map(mpMesh->GetNumNodes());
00156 mpMesh->ReMesh(map);
00157
00158 return mpMesh;
00159 }
00160
00161 void HoneycombMeshGenerator::Make2dPeriodicMesh(double width, unsigned ghosts)
00162 {
00163 OutputFileHandler output_file_handler("");
00164
00165 if (PetscTools::AmMaster())
00166 {
00167 out_stream p_node_file = output_file_handler.OpenOutputFile(mMeshFilename+".node");
00168 (*p_node_file) << std::scientific;
00169
00170 out_stream p_elem_file = output_file_handler.OpenOutputFile(mMeshFilename+".ele");
00171 (*p_elem_file) << std::scientific;
00172
00173 unsigned numNodesAlongWidth = mNumCellWidth;
00174 unsigned numNodesAlongLength = mNumCellLength;
00175 double horizontal_spacing = width / (double)numNodesAlongWidth;
00176 double vertical_spacing = (sqrt(3)/2)*horizontal_spacing;
00177
00178
00179 mDomainDepth = (double)(numNodesAlongLength) * vertical_spacing;
00180
00181
00182 if (!mCylindrical)
00183 {
00184 numNodesAlongWidth = numNodesAlongWidth + 2*ghosts;
00185 }
00186 numNodesAlongLength = numNodesAlongLength + 2*ghosts;
00187
00188 unsigned num_nodes = numNodesAlongWidth*numNodesAlongLength;
00189 unsigned num_elem_along_width = numNodesAlongWidth-1;
00190 unsigned num_elem_along_length = numNodesAlongLength-1;
00191 unsigned num_elem = 2*num_elem_along_width*num_elem_along_length;
00192 unsigned num_edges = 3*num_elem_along_width*num_elem_along_length + num_elem_along_width + num_elem_along_length;
00193
00194 double x0 = -horizontal_spacing*ghosts;
00195 if (mCylindrical)
00196 {
00197 x0 = 0;
00198 }
00199 double y0 = -vertical_spacing*ghosts;
00200 mBottom = -vertical_spacing*ghosts;
00201 mTop = mBottom + vertical_spacing*(numNodesAlongLength-1);
00202
00203 (*p_node_file) << num_nodes << "\t2\t0\t1" << std::endl;
00204 unsigned node = 0;
00205
00206 for (unsigned i=0; i<numNodesAlongLength; i++)
00207 {
00208 for (unsigned j=0; j<numNodesAlongWidth; j++)
00209 {
00210 if ( i<ghosts || i>=(ghosts+mNumCellLength))
00211 {
00212 mGhostNodeIndices.insert(node);
00213 }
00214 else if ( !mCylindrical && (j < ghosts || j >= (ghosts+mNumCellWidth)))
00215 {
00216 mGhostNodeIndices.insert(node);
00217 }
00218 unsigned boundary = 0;
00219 if ((i==0) || (i==numNodesAlongLength-1))
00220 {
00221 boundary = 1;
00222 }
00223 if (!mCylindrical)
00224 {
00225 if ((j==0) || (j==numNodesAlongWidth-1))
00226 {
00227 boundary = 1;
00228 }
00229 }
00230
00231 double x = x0 + horizontal_spacing*((double)j + 0.25*(1.0+ SmallPow(-1,i+1)));
00232 double y = y0 + vertical_spacing*(double)i;
00233
00234
00235 if ( (y<0.0) && (y>-1e-12) )
00236 {
00237
00238 #define COVERAGE_IGNORE
00239 y = 0.0;
00240 #undef COVERAGE_IGNORE
00241 }
00242
00243 (*p_node_file) << node++ << "\t" << x << "\t" << y << "\t" << boundary << std::endl;
00244 }
00245 }
00246 p_node_file->close();
00247
00248 out_stream p_edge_file = output_file_handler.OpenOutputFile(mMeshFilename+".edge");
00249 (*p_node_file) << std::scientific;
00250
00251 (*p_elem_file) << num_elem << "\t3\t0" << std::endl;
00252 (*p_edge_file) << num_edges << "\t1" << std::endl;
00253
00254 unsigned elem = 0;
00255 unsigned edge = 0;
00256 for (unsigned i=0; i<num_elem_along_length; i++)
00257 {
00258 for (unsigned j=0; j < num_elem_along_width; j++)
00259 {
00260 unsigned node0 = i*numNodesAlongWidth + j;
00261 unsigned node1 = i*numNodesAlongWidth + j+1;
00262 unsigned node2 = (i+1)*numNodesAlongWidth + j;
00263
00264 if (i%2 != 0)
00265 {
00266 node2 = node2 + 1;
00267 }
00268
00269 (*p_elem_file) << elem++ << "\t" << node0 << "\t" << node1 << "\t" << node2 << std::endl;
00270
00271 unsigned horizontal_edge_is_boundary_edge = 0;
00272 unsigned vertical_edge_is_boundary_edge = 0;
00273 if (i==0)
00274 {
00275 horizontal_edge_is_boundary_edge = 1;
00276 }
00277 if (j==0 && i%2==0 && !mCylindrical)
00278 {
00279 vertical_edge_is_boundary_edge = 1;
00280 }
00281
00282 (*p_edge_file) << edge++ << "\t" << node0 << "\t" << node1 << "\t" << horizontal_edge_is_boundary_edge << std::endl;
00283 (*p_edge_file) << edge++ << "\t" << node1 << "\t" << node2 << "\t" << 0 << std::endl;
00284 (*p_edge_file) << edge++ << "\t" << node2 << "\t" << node0 << "\t" << vertical_edge_is_boundary_edge << std::endl;
00285
00286 node0 = i*numNodesAlongWidth + j + 1;
00287
00288 if (i%2 != 0)
00289 {
00290 node0 = node0 - 1;
00291 }
00292 node1 = (i+1)*numNodesAlongWidth + j+1;
00293 node2 = (i+1)*numNodesAlongWidth + j;
00294
00295 (*p_elem_file) << elem++ << "\t" << node0 << "\t" << node1 << "\t" << node2 << std::endl;
00296 }
00297 }
00298
00299 for (unsigned i=0; i<num_elem_along_length; i++)
00300 {
00301 unsigned node0, node1;
00302
00303 if (i%2==0)
00304 {
00305 node0 = (i+1)*numNodesAlongWidth - 1;
00306 node1 = (i+2)*numNodesAlongWidth - 1;
00307 }
00308 else
00309 {
00310 node0 = (i+1)*numNodesAlongWidth;
00311 node1 = (i)*numNodesAlongWidth;
00312 }
00313 (*p_edge_file) << edge++ << "\t" << node0 << "\t" << node1 << "\t" << 1 << std::endl;
00314 }
00315
00316 for (unsigned j=0; j<num_elem_along_width; j++)
00317 {
00318 unsigned node0 = numNodesAlongWidth*(numNodesAlongLength-1) + j;
00319 unsigned node1 = numNodesAlongWidth*(numNodesAlongLength-1) + j+1;
00320 (*p_edge_file) << edge++ << "\t" << node1 << "\t" << node0 << "\t" << 1 << std::endl;
00321 }
00322
00323 p_elem_file->close();
00324 p_edge_file->close();
00325 }
00326
00327
00328 PetscTools::Barrier();
00329 }