Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (C) Fujitsu Laboratories of Europe, 2009-2010 00004 00005 */ 00006 00007 /* 00008 00009 Copyright (c) 2005-2012, University of Oxford. 00010 All rights reserved. 00011 00012 University of Oxford means the Chancellor, Masters and Scholars of the 00013 University of Oxford, having an administrative office at Wellington 00014 Square, Oxford OX1 2JD, UK. 00015 00016 This file is part of Chaste. 00017 00018 Redistribution and use in source and binary forms, with or without 00019 modification, are permitted provided that the following conditions are met: 00020 * Redistributions of source code must retain the above copyright notice, 00021 this list of conditions and the following disclaimer. 00022 * Redistributions in binary form must reproduce the above copyright notice, 00023 this list of conditions and the following disclaimer in the documentation 00024 and/or other materials provided with the distribution. 00025 * Neither the name of the University of Oxford nor the names of its 00026 contributors may be used to endorse or promote products derived from this 00027 software without specific prior written permission. 00028 00029 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00030 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00031 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00032 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00033 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00034 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00035 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00036 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00037 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00038 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00039 00040 */ 00041 00042 00043 00044 #ifdef CHASTE_ADAPTIVITY 00045 00046 #include "AdaptiveTetrahedralMesh.hpp" 00047 #include "HeartConfig.hpp" 00048 #include "OutputFileHandler.hpp" 00049 00050 AdaptiveTetrahedralMesh::AdaptiveTetrahedralMesh() : 00051 mNumNodes(0), 00052 mNumElements(0), 00053 mNumLocalNodes(0), 00054 mAdaptSuccess(false), 00055 mpDiscreteGeometryConstraints(NULL), 00056 mpErrorMeasure(NULL), 00057 mpAdapt(NULL), 00058 mGoodEdgeRange(0.0), 00059 mBadEdgeCriterion(0.0), 00060 mVerbose(false) 00061 00062 { 00063 mpVtkUnstructuredGrid = vtkUnstructuredGrid::New(); 00064 } 00065 00066 AdaptiveTetrahedralMesh::~AdaptiveTetrahedralMesh() 00067 { 00068 Reset();//Delete multiple-use pointers 00069 mpVtkUnstructuredGrid->Delete(); 00070 } 00071 00072 void AdaptiveTetrahedralMesh::ConstructFromVtuFile(std::string fileName) 00073 { 00074 vtkXMLUnstructuredGridReader *p_vtk_reader = vtkXMLUnstructuredGridReader::New(); 00075 p_vtk_reader->SetFileName(fileName.c_str()); 00076 p_vtk_reader->Update(); 00077 00078 mpVtkUnstructuredGrid->DeepCopy(p_vtk_reader->GetOutput()); 00079 mpVtkUnstructuredGrid->Update(); 00080 00081 p_vtk_reader->Delete(); 00082 00083 mNumNodes = mpVtkUnstructuredGrid->GetNumberOfPoints(); 00084 mNumElements = mpVtkUnstructuredGrid->GetNumberOfCells(); 00085 mNumLocalNodes = mNumNodes; // Since each process has a complete copy of the vtkUnstructuredGrid 00086 } 00087 00088 void AdaptiveTetrahedralMesh::ConstructFromMesh(AbstractTetrahedralMesh<3,3>* rMesh) 00089 { 00090 vtkPoints *p_pts = vtkPoints::New(); 00091 p_pts->SetDataTypeToDouble(); 00092 for (unsigned i=0; i<rMesh->GetNumNodes(); i++) 00093 { 00094 p_pts->InsertPoint(i, rMesh->GetNode(i)->rGetLocation().data()); 00095 } 00096 00097 mpVtkUnstructuredGrid->Allocate(rMesh->GetNumNodes(), rMesh->GetNumNodes()); 00098 mpVtkUnstructuredGrid->SetPoints(p_pts); 00099 mpVtkUnstructuredGrid->Update(); 00100 p_pts->Delete(); // Reference counted 00101 00102 for (unsigned i=0; i<rMesh->GetNumElements(); i++) 00103 { 00104 vtkTetra *p_tetra = vtkTetra::New(); 00105 for (int j = 0; j < 4; ++j) 00106 { 00107 p_tetra->GetPointIds()->SetId(j, rMesh->GetElement(i)->GetNodeGlobalIndex(j)); 00108 } 00109 mpVtkUnstructuredGrid->InsertNextCell(p_tetra->GetCellType(), p_tetra->GetPointIds()); 00110 mpVtkUnstructuredGrid->Update(); 00111 p_tetra->Delete(); // Reference counted 00112 } 00113 00114 mNumNodes = mpVtkUnstructuredGrid->GetNumberOfPoints(); 00115 mNumElements = mpVtkUnstructuredGrid->GetNumberOfCells(); 00116 mNumLocalNodes = mNumNodes; // Since each process has a complete copy of the vtkUnstructuredGrid 00117 } 00118 00119 void AdaptiveTetrahedralMesh::ConstructFromDistributedMesh(DistributedTetrahedralMesh<3,3>* rMesh) 00120 { 00121 vtkPoints *p_pts = vtkPoints::New(); 00122 p_pts->SetDataTypeToDouble(); 00123 00124 std::vector<unsigned> global_node_numbers, halo_nodes; 00125 std::map<unsigned, unsigned> global_to_local_index_map; 00126 00127 // vtkUnsignedIntArray *p_scalars = vtkUnsignedIntArray::New(); 00128 // p_scalars->SetName("GlobalNodeNumbers"); 00129 00130 unsigned index = 0; 00131 for (DistributedTetrahedralMesh<3,3>::NodeIterator it=rMesh->GetNodeIteratorBegin(); 00132 it != rMesh->GetNodeIteratorEnd(); 00133 ++it) 00134 { 00135 p_pts->InsertPoint(index, it->rGetLocation().data()); 00136 global_node_numbers.push_back(it->GetIndex()); 00137 global_to_local_index_map[it->GetIndex()] = index; 00138 index++; 00139 } 00140 00141 rMesh->GetHaloNodeIndices(halo_nodes); 00142 for(unsigned i=0; i<halo_nodes.size(); i++) 00143 { 00144 global_node_numbers.push_back(halo_nodes[i]); 00145 p_pts->InsertPoint(index, rMesh->GetNodeOrHaloNode(halo_nodes[i])->rGetLocation().data()); 00146 global_to_local_index_map[halo_nodes[i]] = index; 00147 index++; 00148 } 00149 00150 AddPointData("GlobalNodeNumbers", global_node_numbers); 00151 00152 mpVtkUnstructuredGrid->Allocate(global_node_numbers.size(), global_node_numbers.size()); 00153 mpVtkUnstructuredGrid->SetPoints(p_pts); 00154 mpVtkUnstructuredGrid->Update(); 00155 p_pts->Delete(); // Reference counted 00156 00157 for (DistributedTetrahedralMesh<3,3>::ElementIterator it=rMesh->GetElementIteratorBegin(); 00158 it != rMesh->GetElementIteratorEnd(); 00159 ++it) 00160 { 00161 vtkTetra *p_tetra = vtkTetra::New(); 00162 for (int j = 0; j < 4; ++j) 00163 { 00164 p_tetra->GetPointIds()->SetId(j, global_to_local_index_map[it->GetNodeGlobalIndex(j)]); 00165 } 00166 mpVtkUnstructuredGrid->InsertNextCell(p_tetra->GetCellType(), p_tetra->GetPointIds()); 00167 mpVtkUnstructuredGrid->Update(); 00168 p_tetra->Delete(); // Reference counted 00169 } 00170 00171 mNumNodes = rMesh->GetNumNodes(); 00172 mNumElements = rMesh->GetNumElements(); 00173 mNumLocalNodes = mpVtkUnstructuredGrid->GetNumberOfPoints() - halo_nodes.size(); 00174 } 00175 00176 void AdaptiveTetrahedralMesh::AddPointData(std::string dataName, std::vector<double> dataPayload) 00177 { 00178 vtkDoubleArray *p_scalars = vtkDoubleArray::New(); 00179 p_scalars->SetName(dataName.c_str()); 00180 for (unsigned i=0; i<dataPayload.size(); i++) 00181 { 00182 p_scalars->InsertNextValue(dataPayload[i]); 00183 } 00184 00185 mpVtkUnstructuredGrid->GetPointData()->AddArray(p_scalars); 00186 mpVtkUnstructuredGrid->Update(); 00187 p_scalars->Delete(); // Reference counted 00188 } 00189 00190 void AdaptiveTetrahedralMesh::AddPointData(std::string dataName, std::vector<unsigned> dataPayload) 00191 { 00192 vtkUnsignedIntArray *p_scalars = vtkUnsignedIntArray::New(); 00193 p_scalars->SetName(dataName.c_str()); 00194 for (unsigned i=0; i<dataPayload.size(); i++) 00195 { 00196 p_scalars->InsertNextValue(dataPayload[i]); 00197 } 00198 00199 mpVtkUnstructuredGrid->GetPointData()->AddArray(p_scalars); 00200 mpVtkUnstructuredGrid->Update(); 00201 p_scalars->Delete(); // Reference counted 00202 } 00203 00204 void AdaptiveTetrahedralMesh::RemoveArray(std::string dataName) 00205 { 00206 mpVtkUnstructuredGrid->GetPointData()->RemoveArray(dataName.c_str()); 00207 } 00208 00209 void AdaptiveTetrahedralMesh::WriteMeshToFile(std::string directory, std::string fileName) 00210 00211 { 00212 std::string vtk_file_name = directory + fileName; 00213 00214 vtkXMLUnstructuredGridWriter *vtk_writer = vtkXMLUnstructuredGridWriter::New(); 00215 //Uninitialised stuff arises (see #1079), but you can remove 00216 //valgrind problems by removing compression: 00217 // **** REMOVE WITH CAUTION ***** 00218 vtk_writer->SetCompressor(NULL); 00219 // **** REMOVE WITH CAUTION ***** 00220 vtk_writer->SetFileName(vtk_file_name.c_str()); 00221 vtk_writer->SetInput(mpVtkUnstructuredGrid); 00222 vtk_writer->Write(); 00223 vtk_writer->Delete(); 00224 } 00225 00226 void AdaptiveTetrahedralMesh::WriteMeshToDistributedFile(std::string directory, std::string fileName) 00227 { 00228 std::string vtk_file_name = directory + fileName; 00229 00230 vtkXMLPUnstructuredGridWriter *vtk_writer = vtkXMLPUnstructuredGridWriter::New(); 00231 //Uninitialised stuff arises (see #1079), but you can remove 00232 //valgrind problems by removing compression: 00233 // **** REMOVE WITH CAUTION ***** 00234 vtk_writer->SetCompressor(NULL); 00235 // **** REMOVE WITH CAUTION ***** 00236 vtk_writer->SetFileName(vtk_file_name.c_str()); 00237 vtk_writer->SetDataModeToBinary(); 00238 00239 vtk_writer->SetNumberOfPieces(PetscTools::GetNumProcs()); 00240 vtk_writer->SetGhostLevel(1); 00241 vtk_writer->SetStartPiece(PetscTools::GetMyRank()); 00242 vtk_writer->SetEndPiece(PetscTools::GetMyRank()); 00243 00244 vtk_writer->SetInput(mpVtkUnstructuredGrid); 00245 vtk_writer->Write(); 00246 vtk_writer->Delete(); 00247 } 00248 00249 vtkUnstructuredGrid* AdaptiveTetrahedralMesh::GetVtkUnstructuredGrid() 00250 { 00251 return mpVtkUnstructuredGrid; 00252 } 00253 00254 void AdaptiveTetrahedralMesh::SetAdaptCriterion(double range, double criterion) 00255 { 00256 mGoodEdgeRange = range; 00257 mBadEdgeCriterion = criterion; 00258 } 00259 00260 unsigned AdaptiveTetrahedralMesh::GetNumNodes() 00261 { 00262 return mNumNodes; 00263 } 00264 00265 unsigned AdaptiveTetrahedralMesh::GetNumLocalNodes() 00266 { 00267 return mNumLocalNodes; 00268 } 00269 00270 unsigned AdaptiveTetrahedralMesh::GetNumLocalAndHaloNodes() 00271 { 00272 return mpVtkUnstructuredGrid->GetNumberOfPoints(); 00273 } 00274 00275 unsigned AdaptiveTetrahedralMesh::GetNumElements() 00276 { 00277 return mNumElements; 00278 } 00279 00280 unsigned AdaptiveTetrahedralMesh::GetNumLocalElements() 00281 { 00282 return mpVtkUnstructuredGrid->GetNumberOfCells(); 00283 } 00284 00285 unsigned AdaptiveTetrahedralMesh::GetNumSurfaceElements() 00286 { 00287 return sids.size(); 00288 } 00289 00290 void AdaptiveTetrahedralMesh::CalculateSENListAndSids(double coplanarTolerance) 00291 { 00292 DiscreteGeometryConstraints constraints; 00293 00294 if (mVerbose) constraints.verbose_on(); 00295 constraints.set_coplanar_tolerance( coplanarTolerance ); 00296 constraints.set_volume_input(mpVtkUnstructuredGrid); 00297 00298 constraints.get_coplanar_ids(sids); 00299 constraints.get_surface(SENList); 00300 assert(sids.size()*3==SENList.size()); 00301 } 00302 00303 void AdaptiveTetrahedralMesh::GetGeometryConstraints() 00304 { 00305 assert(mpDiscreteGeometryConstraints==NULL); 00306 mpDiscreteGeometryConstraints = new DiscreteGeometryConstraints; 00307 00308 if (mVerbose) mpDiscreteGeometryConstraints->verbose_on(); 00309 mpDiscreteGeometryConstraints->set_surface_input(mpVtkUnstructuredGrid, SENList, sids); 00310 mpDiscreteGeometryConstraints->get_constraints(max_len); 00311 // mpDiscreteGeometryConstraints->write_vtk(std::string("sids.vtu")); 00312 } 00313 00314 void AdaptiveTetrahedralMesh::CalculateErrorMetric() 00315 { 00316 double error = HeartConfig::Instance()->GetTargetErrorForAdaptivity(); 00317 double sigma = HeartConfig::Instance()->GetSigmaForAdaptivity(); 00318 double max_edge_length = HeartConfig::Instance()->GetMaxEdgeLengthForAdaptivity(); 00319 double min_edge_length = HeartConfig::Instance()->GetMinEdgeLengthForAdaptivity(); 00320 double gradation = HeartConfig::Instance()->GetGradationForAdaptivity(); 00321 unsigned max_nodes = HeartConfig::Instance()->GetMaxNodesForAdaptivity(); 00322 assert(mpErrorMeasure == NULL); 00323 mpErrorMeasure = new ErrorMeasure; 00324 00325 if (mVerbose) mpErrorMeasure->verbose_on(); 00326 mpErrorMeasure->set_input(mpVtkUnstructuredGrid); 00327 mpErrorMeasure->add_field("Vm", error, false, sigma); 00328 mpErrorMeasure->set_max_length(max_edge_length); 00329 mpErrorMeasure->set_max_length(&(max_len[0]), mpVtkUnstructuredGrid->GetNumberOfPoints()); 00330 mpErrorMeasure->set_min_length(min_edge_length); 00331 mpErrorMeasure->apply_gradation(gradation); 00332 mpErrorMeasure->set_max_nodes(max_nodes); 00333 00334 mpErrorMeasure->diagnostics(); 00335 } 00336 00337 double AdaptiveTetrahedralMesh::GetEdgeLengthDistribution(double range) 00338 { 00339 //This is a temporary adaptivity class 00340 Adaptivity an_adapter; 00341 an_adapter.set_from_vtk(mpVtkUnstructuredGrid, true); 00342 return an_adapter.edgeLengthDistribution(range); 00343 } 00344 00345 void AdaptiveTetrahedralMesh::Adapt() 00346 { 00347 mpAdapt = new Adaptivity; 00348 mAdaptSuccess = false; 00349 00350 if (mVerbose) mpAdapt->verbose_on(); 00351 mpAdapt->set_from_vtk(mpVtkUnstructuredGrid, true); 00352 mpAdapt->set_adapt_sweeps(HeartConfig::Instance()->GetNumberOfAdaptiveSweeps()); 00353 mpAdapt->set_surface_mesh(SENList); 00354 mpAdapt->set_surface_ids(sids); 00355 00356 if ( mpAdapt->edgeLengthDistribution( mGoodEdgeRange ) > mBadEdgeCriterion ) 00357 { 00358 mpAdapt->adapt(); 00359 00360 mpAdapt->get_surface_ids(sids); 00361 mpAdapt->get_surface_mesh(SENList); 00362 00363 vtkUnstructuredGrid *p_new_vtk_unstructured_grid = mpAdapt->get_adapted_vtu(); 00364 mpVtkUnstructuredGrid->DeepCopy( p_new_vtk_unstructured_grid ); 00365 mpVtkUnstructuredGrid->Update(); 00366 p_new_vtk_unstructured_grid->Delete(); 00367 00368 mAdaptSuccess = true; 00369 } 00370 else 00371 { 00373 //mpAdapt->get_adapted_vtu()->Initialize(); 00374 } 00375 00376 mpVtkUnstructuredGrid->GetPointData()->RemoveArray("metric"); 00377 mpVtkUnstructuredGrid->Squeeze(); 00378 00379 // Need to free these pointers as fresh instances are required for the next adapt (else odd things happen) 00380 Reset(); 00381 00382 // Update private member variables - note: these assume that the adapt happens sequentially 00383 mNumNodes = mpVtkUnstructuredGrid->GetNumberOfPoints(); 00384 mNumElements = mpVtkUnstructuredGrid->GetNumberOfCells(); 00385 mNumLocalNodes = mNumNodes; // Since each process has a complete copy of the vtkUnstructuredGrid 00386 } 00387 00388 void AdaptiveTetrahedralMesh::AdaptMesh() 00389 { 00390 GetGeometryConstraints(); 00391 00392 CalculateErrorMetric(); 00393 00394 RemoveArray("mean_desired_lengths"); 00395 RemoveArray("desired_lengths"); 00396 // SetAdaptCriterion( mGoodEdgeRange, mBadEdgeCriterion ); 00397 Adapt(); 00398 } 00399 00400 void AdaptiveTetrahedralMesh::Reset() 00401 { 00402 delete mpDiscreteGeometryConstraints; 00403 delete mpErrorMeasure; 00404 delete mpAdapt; 00405 mpDiscreteGeometryConstraints=NULL; 00406 mpErrorMeasure=NULL; 00407 mpAdapt=NULL; 00408 } 00409 00410 bool AdaptiveTetrahedralMesh::GetAdaptSuccess() 00411 { 00412 return mAdaptSuccess; 00413 } 00414 00415 void AdaptiveTetrahedralMesh::MakeVerbose(bool verbose) 00416 { 00417 mVerbose = verbose; 00418 } 00419 00420 #endif // CHASTE_ADAPTIVITY