00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <DegreeOfFreedomSetBuilder.hpp>
00021 #include <Mesh.hpp>
00022
00023 #include <DegreeOfFreedomSetManager.hpp>
00024
00025 #include <SpectralMesh.hpp>
00026 #include <Structured3DMesh.hpp>
00027 #include <MeshOfTetrahedra.hpp>
00028 #include <MeshOfHexahedra.hpp>
00029
00030 #include <OctreeMesh.hpp>
00031
00032 #include <FiniteElementTraits.hpp>
00033
00034 #include <ErrorHandler.hpp>
00035
00036 #include <ScalarDiscretizationTypeSpectral.hpp>
00037
00038
00039 template <size_t ItemDOFNumber>
00040 struct DegreeOfFreedomSetBuilder::ItemTraits
00041 {
00042 typedef TinyVector<ItemDOFNumber,size_t> DOFList;
00043 };
00044
00045 template <>
00046 struct DegreeOfFreedomSetBuilder::ItemTraits<0>
00047 {
00048
00049
00050 typedef TinyVector<1,size_t> DOFList;
00051 };
00052
00053 template <typename MeshType,
00054 typename FiniteElementType>
00055 size_t DegreeOfFreedomSetBuilder::
00056 __buildFEMCorrespondance(const MeshType& mesh,
00057 DegreeOfFreedomSet::Correspondance& correspondance)
00058 {
00059 size_t numberOfUsedDOF = 0;
00060 size_t dofPositionNumber = 0;
00061
00062 const VerticesCorrespondance& verticesCorrespondance = *mesh.verticesCorrespondance();
00063
00064
00065 if (FiniteElementType::numberOfVertexDegreesOfFreedom > 0) {
00066 for (size_t i=0; i<mesh.numberOfVertices(); ++i) {
00067 correspondance[i] = verticesCorrespondance[i];
00068 numberOfUsedDOF = std::max(verticesCorrespondance[i],numberOfUsedDOF);
00069 dofPositionNumber++;
00070 }
00071 }
00072
00073
00074 if (FiniteElementType::numberOfEdgeDegreesOfFreedom > 0) {
00075 ASSERT(mesh.hasEdges());
00076
00077 typedef TinyVector<2,size_t> VerticesPair;
00078
00079 typedef
00080 typename ItemTraits<FiniteElementType::numberOfEdgeDegreesOfFreedom>::DOFList
00081 EdgeDOFNumbers;
00082
00083 typedef std::map<VerticesPair, EdgeDOFNumbers> SortedEdgeSet;
00084 SortedEdgeSet sortedEdgeSet;
00085
00086 for (size_t i=0; i<mesh.numberOfEdges(); ++i) {
00087 const Edge& edge = mesh.edge(i);
00088 const size_t v0 = verticesCorrespondance[mesh.vertexNumber(edge(0))];
00089 const size_t v1 = verticesCorrespondance[mesh.vertexNumber(edge(1))];
00090
00091 TinyVector<2,size_t> verticesPair;
00092 verticesPair[0] = std::min(v0,v1);
00093 verticesPair[1] = std::max(v0,v1);
00094
00095 typename SortedEdgeSet::iterator iedge = sortedEdgeSet.find(verticesPair);
00096 if (iedge == sortedEdgeSet.end()) {
00097 EdgeDOFNumbers dofNumbers;
00098 for (size_t j=0; j<FiniteElementType::numberOfEdgeDegreesOfFreedom; ++j) {
00099 numberOfUsedDOF++;
00100 dofNumbers[j]=numberOfUsedDOF;
00101 }
00102
00103 iedge = sortedEdgeSet.insert(iedge,std::make_pair(verticesPair, dofNumbers));
00104 }
00105 for (size_t j=0; j<FiniteElementType::numberOfEdgeDegreesOfFreedom; ++j) {
00106 correspondance[dofPositionNumber] = iedge->second[j];
00107 dofPositionNumber++;
00108 }
00109 }
00110 }
00111
00112
00113 if (FiniteElementType::numberOfFaceDegreesOfFreedom > 0) {
00114 ASSERT(mesh.hasFaces());
00115
00116 typedef TinyVector<MeshType::FaceType::NumberOfVertices,size_t> VerticesList;
00117
00118 typedef
00119 typename ItemTraits<FiniteElementType::numberOfFaceDegreesOfFreedom>::DOFList
00120 FaceDOFNumbers;
00121
00122 typedef std::map<VerticesList, FaceDOFNumbers> SortedFaceSet;
00123 SortedFaceSet sortedFaceSet;
00124
00125 for (size_t i=0; i<mesh.numberOfFaces(); ++i) {
00126 const typename MeshType::FaceType& face = mesh.face(i);
00127 std::set<size_t> verticesSet;
00128
00129 for (size_t j=0; j<MeshType::FaceType::NumberOfVertices; ++j) {
00130 verticesSet.insert(verticesCorrespondance[mesh.vertexNumber(face(j))]);
00131 }
00132 VerticesList verticesList;
00133 {
00134 size_t j=0;
00135 for (std::set<size_t>::const_iterator k = verticesSet.begin();
00136 k != verticesSet.end(); ++k, ++j) {
00137 verticesList[j] = *k;
00138 }
00139 }
00140
00141 typename SortedFaceSet::iterator iface = sortedFaceSet.find(verticesList);
00142 if (iface == sortedFaceSet.end()) {
00143 FaceDOFNumbers dofNumbers;
00144 for (size_t j=0; j<FiniteElementType::numberOfFaceDegreesOfFreedom; ++j) {
00145 numberOfUsedDOF++;
00146 dofNumbers[j]=numberOfUsedDOF;
00147 }
00148
00149 iface = sortedFaceSet.insert(iface,std::make_pair(verticesList, dofNumbers));
00150 }
00151 for (size_t j=0; j<FiniteElementType::numberOfFaceDegreesOfFreedom; ++j) {
00152 correspondance[dofPositionNumber] = iface->second[j];
00153 dofPositionNumber++;
00154 }
00155 }
00156 }
00157
00158
00159 if (FiniteElementType::numberOfVolumeDegreesOfFreedom > 0) {
00160 for (size_t i=0;i<mesh.numberOfCells(); ++i) {
00161 for (size_t j=0;j<FiniteElementType::numberOfVolumeDegreesOfFreedom; ++j) {
00162 correspondance[dofPositionNumber] = numberOfUsedDOF;
00163 dofPositionNumber++;
00164 numberOfUsedDOF++;
00165 }
00166 }
00167 }
00168 return numberOfUsedDOF+1;
00169 }
00170
00171 template <typename MeshType>
00172 void DegreeOfFreedomSetBuilder::
00173 __buildCorrespondance(const MeshType& mesh,
00174 const DiscretizationType& discretization,
00175 DegreeOfFreedomSet::Correspondance& correspondance)
00176 {
00177 if (not mesh.isPeriodic()) {
00178 for (size_t i=0; i<correspondance.size(); ++i) {
00179 correspondance[i]=i;
00180 }
00181 return;
00182 }
00183
00184 typedef typename MeshType::CellType CellType;
00185
00186 switch (discretization[0].type()) {
00187 case ScalarDiscretizationTypeBase::lagrangianFEM1: {
00188 typedef
00189 typename FiniteElementTraits<CellType,
00190 ScalarDiscretizationTypeBase::lagrangianFEM1>::Type
00191 FiniteElementType;
00192
00193 this->__buildFEMCorrespondance<MeshType,FiniteElementType>(mesh,correspondance);
00194 break;
00195 }
00196 case ScalarDiscretizationTypeBase::lagrangianFEM2: {
00197 typedef
00198 typename FiniteElementTraits<CellType,
00199 ScalarDiscretizationTypeBase::lagrangianFEM2>::Type
00200 FiniteElementType;
00201
00202 this->__buildFEMCorrespondance<MeshType,FiniteElementType>(mesh,correspondance);
00203 break;
00204 }
00205 default: {
00206 throw ErrorHandler(__FILE__,__LINE__,
00207 "not implemented",
00208 ErrorHandler::unexpected);
00209 }
00210 }
00211
00212 {
00213 #warning this only works for Pk-Pk elements
00214 size_t offset = 0;
00215 for (size_t i=1; i<__dofPositionSet->number(); ++i) {
00216 offset += (*__dofPositionSet)[i-1].number();
00217 for (size_t j=0; j<(*__dofPositionSet)[i].number(); ++j) {
00218 correspondance[j+offset] = correspondance[j]+offset;
00219 }
00220 }
00221 }
00222 }
00223
00224 template <typename MeshType,
00225 typename FiniteElementType>
00226 void DegreeOfFreedomSetBuilder::
00227 __buildFEMFictitious(const size_t& numberOfVariables,
00228 const MeshType& mesh,
00229 const Domain& domain)
00230 {
00231 typedef DegreeOfFreedomSet::Correspondance Correspondance;
00232
00233 size_t numberOfCorrespondances = 0;
00234 for (size_t i=0; i<__dofPositionSet->number(); ++i) {
00235 numberOfCorrespondances += (*__dofPositionSet)[i].number();
00236 }
00237
00238 ReferenceCounting<Correspondance> pCorrespondance
00239 = new Correspondance(numberOfCorrespondances);
00240
00241 Correspondance& correspondance = *pCorrespondance;
00242
00243
00244 this->__buildFEMCorrespondance<MeshType,FiniteElementType>(mesh,correspondance);
00245
00246 {
00247 #warning this only works for Pk-Pk elements
00248 size_t offset = 0;
00249 for (size_t i=1; i<__dofPositionSet->number(); ++i) {
00250 offset += (*__dofPositionSet)[i-1].number();
00251 for (size_t j=0; j<(*__dofPositionSet)[i].number(); ++j) {
00252 correspondance[j+offset] = correspondance[j]+offset;
00253 }
00254 }
00255 }
00256
00257 Vector<bool> nonFictitiousDOF(numberOfCorrespondances);
00258 nonFictitiousDOF = false;
00259
00260 {
00261 size_t offset = 0;
00262 for(size_t i=0; i<__dofPositionSet->number(); ++i) {
00263 const ScalarDegreeOfFreedomPositionsSet& scalarDOFPositions = (*__dofPositionSet)[i];
00264 if (i>0) offset += (*__dofPositionSet)[i-1].number();
00265 for (size_t j=0; j<scalarDOFPositions.number(); ++j) {
00266 nonFictitiousDOF[offset+j] = domain.inside(scalarDOFPositions.vertex(j));
00267 }
00268 }
00269 }
00270
00271 typedef typename MeshType::CellType CellType;
00272
00273 size_t offset = 0;
00274 for(size_t i=0; i<(*__dofPositionSet).number(); ++i) {
00275 if (i>0) offset += (*__dofPositionSet)[i-1].number();
00276 const ScalarDegreeOfFreedomPositionsSet& scalarDOFPositions = (*__dofPositionSet)[i];
00277 for (size_t j=0; j<mesh.numberOfCells();++j) {
00278 size_t numberIn = 0;
00279 const CellType& C = mesh.cell(j);
00280 const size_t cellNumer = mesh.cellNumber(C);
00281
00282 for (size_t k=0; k<FiniteElementType::numberOfDegreesOfFreedom; ++k) {
00283 numberIn += (nonFictitiousDOF(offset+scalarDOFPositions(cellNumer,k)))?1:0;
00284 }
00285
00286
00287 if (numberIn != 0) {
00288 for (size_t k=0; k<FiniteElementType::numberOfDegreesOfFreedom; ++k) {
00289 const size_t n = scalarDOFPositions(cellNumer,k);
00290 nonFictitiousDOF[offset+n] = true;
00291 }
00292 }
00293 }
00294 }
00295
00296
00297 std::map<size_t, size_t> newVerticesCorrespondance;
00298 for (size_t i=0; i<numberOfCorrespondances; ++i) {
00299 if (nonFictitiousDOF[i]) {
00300 newVerticesCorrespondance[correspondance[i]] = 0;
00301 }
00302 }
00303
00304 size_t numberOfDLVertices = 0;
00305 for (std::map<size_t, size_t>::iterator i=newVerticesCorrespondance.begin();
00306 i != newVerticesCorrespondance.end(); ++i) {
00307 i->second = numberOfDLVertices++;
00308 }
00309
00310 ReferenceCounting<Correspondance> pFDMCorrespondance
00311 = new Correspondance(numberOfCorrespondances);
00312
00313 DegreeOfFreedomSet::Correspondance& fdmCorrespondance = *pFDMCorrespondance;
00314 fdmCorrespondance = -1;
00315
00316 for(size_t i=0; i<correspondance.size(); ++i) {
00317 if (nonFictitiousDOF[i]) {
00318 fdmCorrespondance[i] = newVerticesCorrespondance[correspondance[i]];
00319 }
00320 }
00321
00322 __degreeOfFreedomSet
00323 = new DegreeOfFreedomSet(__dofPositionSet,
00324 pFDMCorrespondance);
00325 }
00326
00327 template <typename MeshType>
00328 void DegreeOfFreedomSetBuilder::
00329 __buildFictitious(const size_t& numberOfVariables,
00330 const ScalarDiscretizationTypeBase& discretization,
00331 const MeshType& mesh,
00332 const Domain& domain)
00333 {
00334 typedef typename MeshType::CellType CellType;
00335
00336 switch (discretization.type()) {
00337 case ScalarDiscretizationTypeBase::lagrangianFEM1: {
00338 typedef
00339 typename FiniteElementTraits<CellType,
00340 ScalarDiscretizationTypeBase::lagrangianFEM1>::Type
00341 FiniteElementType;
00342
00343 this->__buildFEMFictitious<MeshType,FiniteElementType>(numberOfVariables,
00344 mesh,
00345 domain);
00346 break;
00347 }
00348 case ScalarDiscretizationTypeBase::lagrangianFEM2: {
00349 typedef
00350 typename FiniteElementTraits<CellType,
00351 ScalarDiscretizationTypeBase::lagrangianFEM2>::Type
00352 FiniteElementType;
00353
00354 this->__buildFEMFictitious<MeshType,FiniteElementType>(numberOfVariables,
00355 mesh,
00356 domain);
00357 break;
00358 }
00359 default: {
00360 throw ErrorHandler(__FILE__,__LINE__,
00361 "not implemented",
00362 ErrorHandler::unexpected);
00363 }
00364 }
00365 }
00366
00367 DegreeOfFreedomSetBuilder::
00368 DegreeOfFreedomSetBuilder(const DiscretizationType& discretizationType,
00369 const Mesh& mesh)
00370 : __dofPositionSet(new DegreeOfFreedomPositionsSet)
00371 {
00372 for (size_t i=0; i<discretizationType.number(); ++i) {
00373 __dofPositionSet->add(DegreeOfFreedomSetManager::instance().getDOFPositionsSet(mesh,
00374 discretizationType[i]));
00375 }
00376
00377 typedef DegreeOfFreedomSet::Correspondance Correspondance;
00378
00379 size_t numberOfCorrespondances = 0;
00380 for (size_t i=0; i<__dofPositionSet->number(); ++i) {
00381 numberOfCorrespondances += (*__dofPositionSet)[i].number();
00382 }
00383
00384 ReferenceCounting<Correspondance> pCorrespondance
00385 = new Correspondance(numberOfCorrespondances);
00386 Correspondance& correspondance = *pCorrespondance;
00387
00388 switch(mesh.type()) {
00389 case Mesh::cartesianHexahedraMesh: {
00390 this->__buildCorrespondance(static_cast<const Structured3DMesh&>(mesh),
00391 discretizationType,
00392 correspondance);
00393 break;
00394 }
00395 case Mesh::hexahedraMesh: {
00396 this->__buildCorrespondance(static_cast<const MeshOfHexahedra&>(mesh),
00397 discretizationType,
00398 correspondance);
00399 break;
00400 }
00401 case Mesh::tetrahedraMesh: {
00402 this->__buildCorrespondance(static_cast<const MeshOfTetrahedra&>(mesh),
00403 discretizationType,
00404 correspondance);
00405 break;
00406 }
00407 case Mesh::spectralMesh: {
00408 this->__buildCorrespondance(static_cast<const SpectralMesh&>(mesh),
00409 discretizationType,
00410 correspondance);
00411 break;
00412 }
00413 case Mesh::octreeMesh: {
00414 this->__buildCorrespondance(static_cast<const OctreeMesh&>(mesh),
00415 discretizationType,
00416 correspondance);
00417 break;
00418 }
00419 default: {
00420 throw ErrorHandler(__FILE__,__LINE__,
00421 "not implemented yet",
00422 ErrorHandler::unexpected);
00423 }
00424 }
00425
00426 __degreeOfFreedomSet
00427 = new DegreeOfFreedomSet(__dofPositionSet,
00428 pCorrespondance);
00429
00430 }
00431
00432 DegreeOfFreedomSetBuilder::
00433 DegreeOfFreedomSetBuilder(const DiscretizationType& discretizationType,
00434 const Mesh& mesh,
00435 const Domain& domain)
00436 : __dofPositionSet(new DegreeOfFreedomPositionsSet)
00437 {
00438 for (size_t i=0; i<discretizationType.number(); ++i) {
00439 __dofPositionSet->add(DegreeOfFreedomSetManager::instance().getDOFPositionsSet(mesh,
00440 discretizationType[i]));
00441 }
00442
00443 switch(mesh.type()) {
00444 case Mesh::cartesianHexahedraMesh: {
00445 this->__buildFictitious(discretizationType.number(),
00446 discretizationType[0],
00447 static_cast<const Structured3DMesh&>(mesh),
00448 domain);
00449 break;
00450 }
00451 case Mesh::tetrahedraMesh: {
00452 this->__buildFictitious(discretizationType.number(),
00453 discretizationType[0],
00454 static_cast<const Structured3DMesh&>(mesh),
00455 domain);
00456 break;
00457 }
00458 case Mesh::hexahedraMesh: {
00459 this->__buildFictitious(discretizationType.number(),
00460 discretizationType[0],
00461 static_cast<const Structured3DMesh&>(mesh),
00462 domain);
00463 break;
00464 }
00465 default: {
00466 throw ErrorHandler(__FILE__,__LINE__,
00467 "not implemented yet",
00468 ErrorHandler::unexpected);
00469 }
00470 }
00471 }
00472
00473
00474 DegreeOfFreedomSetBuilder::
00475 ~DegreeOfFreedomSetBuilder()
00476 {
00477 ;
00478 }