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