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