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