00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <SpectralMesh.hpp>
00021 #include <Structured3DMesh.hpp>
00022 #include <MeshOfTetrahedra.hpp>
00023 #include <MeshOfHexahedra.hpp>
00024 #include <MeshOfTriangles.hpp>
00025
00026 #include <OctreeMesh.hpp>
00027
00028 #include <FiniteElementTraits.hpp>
00029
00030 #include <DegreeOfFreedomPositionsSet.hpp>
00031 #include <ScalarDegreeOfFreedomPositionsSet.hpp>
00032
00033 #include <ScalarDiscretizationTypeSpectral.hpp>
00034
00035 #include <ConnectivityBuilder.hpp>
00036
00044 class ScalarDegreeOfFreedomPositionsSet::Builder
00045 {
00046 private:
00047 ScalarDegreeOfFreedomPositionsSet&
00048 __dofPositionsSet;
00059 template <typename FiniteElementType,
00060 typename MeshType>
00061 size_t __computeFEMNbDOF(const MeshType& mesh)
00062 {
00063 size_t nbDOF = 0;
00064 size_t neededConnectivities = 0;
00065
00066
00067 if (FiniteElementType::numberOfVertexDegreesOfFreedom > 0) {
00068 nbDOF
00069 += FiniteElementType::numberOfVertexDegreesOfFreedom
00070 * mesh.numberOfVertices();
00071 }
00072
00073
00074 if (FiniteElementType::numberOfEdgeDegreesOfFreedom > 0) {
00075 if (not(mesh.hasEdges())) {
00076 const_cast<MeshType&>(mesh).buildEdges();
00077 }
00078 if (not(mesh.connectivity().hasCellToEdges())) {
00079 neededConnectivities += Connectivity<MeshType>::CellToEdges;
00080 }
00081
00082 nbDOF
00083 += FiniteElementType::numberOfEdgeDegreesOfFreedom
00084 * mesh.numberOfEdges();
00085 }
00086
00087
00088 if (FiniteElementType::numberOfFaceDegreesOfFreedom > 0) {
00089 if (not(mesh.hasFaces())) {
00090 const_cast<MeshType&>(mesh).buildFaces();
00091 }
00092 if (not(mesh.connectivity().hasCellToFaces())) {
00093 neededConnectivities += Connectivity<MeshType>::CellToFaces;
00094 }
00095 nbDOF
00096 += FiniteElementType::numberOfFaceDegreesOfFreedom
00097 * mesh.numberOfFaces();
00098 }
00099
00100
00101 if (FiniteElementType::numberOfVolumeDegreesOfFreedom > 0) {
00102 nbDOF
00103 += FiniteElementType::numberOfVolumeDegreesOfFreedom
00104 * mesh.numberOfCells();
00105 }
00106
00107 if (neededConnectivities > 0) {
00108 ConnectivityBuilder<MeshType> builder(mesh);
00109 builder.generates(neededConnectivities);
00110 }
00111
00112 ffout(3) << "- number of degrees of freedom positions: " << nbDOF << '\n';
00113 return nbDOF;
00114 }
00115
00122 template<typename MeshType,
00123 typename FiniteElementType>
00124 void __buildFEM(const MeshType& mesh)
00125 {
00126 typedef typename MeshType::CellType CellType;
00127
00128 __dofPositionsSet.__numberOfDOFPerCell = FiniteElementType::numberOfDegreesOfFreedom;
00129 __dofPositionsSet.__dofNumber.resize(mesh.numberOfCells()*FiniteElementType::numberOfDegreesOfFreedom);
00130
00131 __dofPositionsSet.__dofNumber = std::numeric_limits<size_t>::max();
00132
00133
00134 const size_t nbDOF = __computeFEMNbDOF<FiniteElementType>(mesh);
00135
00136 __dofPositionsSet.__positions.resize(nbDOF);
00137
00138 size_t begin = 0;
00139 size_t end = 0;
00140
00141
00142 if (FiniteElementType::numberOfVertexDegreesOfFreedom > 0) {
00143 begin = end;
00144 end += mesh.numberOfVertices();
00145 for (size_t i=begin; i < end; ++i) {
00146 __dofPositionsSet.__positions[i] = mesh.vertex(i);
00147 }
00148 for (size_t i=0; i<mesh.numberOfCells(); ++i) {
00149 const CellType& cell = mesh.cell(i);
00150 for (size_t j=0; j<CellType::NumberOfVertices; ++j) {
00151 const size_t vertexNumber = mesh.vertexNumber(cell(j));
00152 __dofPositionsSet.__dofNumber[i*FiniteElementType::numberOfDegreesOfFreedom+j]
00153 = vertexNumber;
00154 }
00155 }
00156 }
00157
00158
00159 if (FiniteElementType::numberOfEdgeDegreesOfFreedom > 0) {
00160 begin = end;
00161 end += mesh.numberOfEdges();
00162 for (size_t i=begin; i < end; ++i) {
00163 const Edge& edge = mesh.edge(i-begin);
00164 __dofPositionsSet.__positions[i] = 0.5*(edge(0)+edge(1));
00165 }
00166
00167
00168 const size_t inputShift
00169 = FiniteElementType::numberOfVertexDegreesOfFreedom
00170 * CellType::NumberOfVertices;
00171 const size_t outputShift
00172 = mesh.numberOfVertices()
00173 * FiniteElementType::numberOfVertexDegreesOfFreedom;
00174
00175 const Connectivity<MeshType>&
00176 connectivity = mesh.connectivity();
00177
00178 for (size_t i=0; i<mesh.numberOfCells(); ++i) {
00179 const CellType& cell = mesh.cell(i);
00180 const typename Connectivity<MeshType>::CellToEdgesType&
00181 cellEdges = connectivity.edges(cell);
00182 for (size_t j=0; j<CellType::NumberOfEdges; ++j) {
00183 const Edge& edge = *(cellEdges[j]);
00184 const size_t edgeNumber = mesh.edgeNumber(edge);
00185 __dofPositionsSet.__dofNumber[i*FiniteElementType::numberOfDegreesOfFreedom+inputShift+j]
00186 = edgeNumber + outputShift;
00187 }
00188 }
00189 }
00190
00191
00192 if (FiniteElementType::numberOfFaceDegreesOfFreedom > 0) {
00193 begin = end;
00194 end += mesh.numberOfFaces();
00195 for (size_t i=begin; i < end; ++i) {
00196 typedef typename MeshType::CellType::FaceType FaceType;
00197
00198 const FaceType& face = mesh.face(i-begin);
00199 __dofPositionsSet.__positions[i] = 0;
00200 for (size_t j=0; j<FaceType::NumberOfVertices; ++j) {
00201 __dofPositionsSet.__positions[i] += face(j);
00202 }
00203 __dofPositionsSet.__positions[i] *= 1./FaceType::NumberOfVertices;
00204 }
00205
00206
00207
00208 const size_t inputShift
00209 = FiniteElementType::numberOfVertexDegreesOfFreedom
00210 * CellType::NumberOfVertices
00211 + FiniteElementType::numberOfEdgeDegreesOfFreedom
00212 * CellType::NumberOfEdges;
00213 const size_t outputShift
00214 = mesh.numberOfVertices()
00215 * FiniteElementType::numberOfVertexDegreesOfFreedom
00216 + (mesh.hasEdges() ? mesh.numberOfEdges() : 0)
00217 * FiniteElementType::numberOfEdgeDegreesOfFreedom;
00218
00219 const Connectivity<MeshType>&
00220 connectivity = mesh.connectivity();
00221
00222 for (size_t i=0; i<mesh.numberOfCells(); ++i) {
00223 const CellType& cell = mesh.cell(i);
00224 const typename Connectivity<MeshType>::CellToFacesType&
00225 cellFaces = connectivity.faces(cell);
00226
00227 for (size_t j=0; j<CellType::NumberOfFaces; ++j) {
00228 const typename CellType::FaceType& face = *(cellFaces[j]);
00229 const size_t faceNumber = mesh.faceNumber(face);
00230 __dofPositionsSet.__dofNumber[i*FiniteElementType::numberOfDegreesOfFreedom+inputShift+j]
00231 = faceNumber + outputShift;
00232 }
00233 }
00234 }
00235
00236
00237 if (FiniteElementType::numberOfVolumeDegreesOfFreedom > 0) {
00238 begin = end;
00239 end += mesh.numberOfCells();
00240
00241 for (size_t i=0; i<mesh.numberOfCells(); ++i) {
00242 const CellType& cell = mesh.cell(i);
00243 TinyVector<3, real_t> position = 0;
00244 for (size_t l = 0; l<MeshType::CellType::NumberOfVertices; ++l) {
00245 position += cell(l);
00246 }
00247 position /= MeshType::CellType::NumberOfVertices;
00248 __dofPositionsSet.__positions[i+begin] = position;
00249 }
00250
00251
00252
00253 const size_t inputShift
00254 = FiniteElementType::numberOfVertexDegreesOfFreedom
00255 * CellType::NumberOfVertices
00256 + FiniteElementType::numberOfEdgeDegreesOfFreedom
00257 * CellType::NumberOfEdges
00258 + FiniteElementType::numberOfFaceDegreesOfFreedom
00259 * CellType::NumberOfFaces;
00260 const size_t outputShift
00261 = mesh.numberOfVertices()
00262 * FiniteElementType::numberOfVertexDegreesOfFreedom
00263 + (mesh.hasEdges() ? mesh.numberOfEdges() : 0)
00264 * FiniteElementType::numberOfEdgeDegreesOfFreedom
00265 + (mesh.hasFaces() ? mesh.numberOfFaces() : 0)
00266 * FiniteElementType::numberOfFaceDegreesOfFreedom;
00267
00268 for (size_t i=0; i<mesh.numberOfCells(); ++i) {
00269 __dofPositionsSet.__dofNumber[i*FiniteElementType::numberOfDegreesOfFreedom+inputShift]
00270 = i + outputShift;
00271 }
00272 }
00273 }
00274
00275 template<typename MeshType>
00276 void __buildLegendre(const MeshType& mesh,
00277 const ScalarDiscretizationTypeSpectral& spectralDiscretizationType)
00278 {
00279 throw ErrorHandler(__FILE__,__LINE__,
00280 "Cannot build spectral degrees of freefom on '"
00281 +mesh.typeName()+"'",
00282 ErrorHandler::unexpected);
00283 }
00284
00292 template <typename MeshType>
00293 void __build(const ScalarDiscretizationTypeBase& discretizationType,
00294 const MeshType& mesh);
00295 public:
00301 Builder(ScalarDegreeOfFreedomPositionsSet& dofPositionsSet)
00302 : __dofPositionsSet(dofPositionsSet)
00303 {
00304 ;
00305 }
00306
00311 ~Builder()
00312 {
00313 ;
00314 }
00315
00322 void build(const ScalarDiscretizationTypeBase& discretizationType,
00323 const Mesh& mesh);
00324 };
00325
00326
00327 template<>
00328 void ScalarDegreeOfFreedomPositionsSet::Builder::
00329 __buildLegendre<SpectralMesh>(const SpectralMesh& mesh,
00330 const ScalarDiscretizationTypeSpectral& spectralDiscretizationType)
00331 {
00332
00333 const TinyVector<3,size_t>& degrees = spectralDiscretizationType.degrees();
00334 __dofPositionsSet.__numberOfDOFPerCell = (degrees[0]+1)*(degrees[1]+1)*(degrees[2]+1);
00335 __dofPositionsSet.__dofNumber.resize(__dofPositionsSet.__numberOfDOFPerCell);
00336
00337 for (size_t i=0; i<__dofPositionsSet.__dofNumber.size(); ++i) {
00338 __dofPositionsSet.__dofNumber[i]=i;
00339 }
00340
00341
00342 __dofPositionsSet.__positions.resize(__dofPositionsSet.__numberOfDOFPerCell);
00343 __dofPositionsSet.__positions = TinyVector<3,real_t>(0,0,0);
00344 }
00345
00346 template<>
00347 void ScalarDegreeOfFreedomPositionsSet::Builder::
00348 __buildLegendre<OctreeMesh>(const OctreeMesh& mesh,
00349 const ScalarDiscretizationTypeSpectral& spectralDiscretizationType)
00350 {
00351
00352 const TinyVector<3,size_t>& degrees = spectralDiscretizationType.degrees();
00353 __dofPositionsSet.__numberOfDOFPerCell = (degrees[0]+1)*(degrees[1]+1)*(degrees[2]+1);
00354 __dofPositionsSet.__dofNumber.resize(__dofPositionsSet.__numberOfDOFPerCell);
00355
00356 for (size_t i=0; i<__dofPositionsSet.__dofNumber.size(); ++i) {
00357 __dofPositionsSet.__dofNumber[i]=i;
00358 }
00359
00360
00361 __dofPositionsSet.__positions.resize(__dofPositionsSet.__numberOfDOFPerCell);
00362 __dofPositionsSet.__positions = TinyVector<3,real_t>(0,0,0);
00363 }
00364
00365
00366 template <typename MeshType>
00367 void ScalarDegreeOfFreedomPositionsSet::Builder::
00368 __build(const ScalarDiscretizationTypeBase& discretizationType,
00369 const MeshType& mesh)
00370 {
00371 typedef typename MeshType::CellType CellType;
00372 switch(discretizationType.type()) {
00373 case ScalarDiscretizationTypeBase::lagrangianFEM0: {
00374 typedef
00375 typename FiniteElementTraits<CellType,
00376 ScalarDiscretizationTypeBase::lagrangianFEM0>::Type
00377 FiniteElementType;
00378 __buildFEM<MeshType, FiniteElementType>(mesh);
00379 break;
00380 }
00381 case ScalarDiscretizationTypeBase::lagrangianFEM1: {
00382 typedef
00383 typename FiniteElementTraits<CellType,
00384 ScalarDiscretizationTypeBase::lagrangianFEM1>::Type
00385 FiniteElementType;
00386 __buildFEM<MeshType, FiniteElementType>(mesh);
00387 break;
00388 }
00389 case ScalarDiscretizationTypeBase::lagrangianFEM2: {
00390 typedef
00391 typename FiniteElementTraits<CellType,
00392 ScalarDiscretizationTypeBase::lagrangianFEM2>::Type
00393 FiniteElementType;
00394 __buildFEM<MeshType, FiniteElementType>(mesh);
00395 break;
00396 }
00397 case ScalarDiscretizationTypeBase::spectralLegendre: {
00398 switch (discretizationType.type()) {
00399 case ScalarDiscretizationTypeBase::spectralLegendre: {
00400 const ScalarDiscretizationTypeSpectral& spectralDiscretizationType
00401 = dynamic_cast<const ScalarDiscretizationTypeSpectral&>(discretizationType);
00402 __buildLegendre<MeshType>(mesh, spectralDiscretizationType);
00403 break;
00404 }
00405 default: {
00406 throw ErrorHandler(__FILE__,__LINE__,
00407 "Unknown spectral discretization type: '"+
00408 ScalarDiscretizationTypeBase::name(discretizationType)+"'",
00409 ErrorHandler::unexpected);
00410 }
00411 }
00412 break;
00413 }
00414 default: {
00415 throw ErrorHandler(__FILE__,__LINE__,
00416 "not implemented",
00417 ErrorHandler::unexpected);
00418 }
00419 }
00420 }
00421
00422
00423 void ScalarDegreeOfFreedomPositionsSet::Builder::
00424 build(const ScalarDiscretizationTypeBase& discretizationType,
00425 const Mesh& mesh)
00426 {
00427 ffout(2) << "Computing degrees of freedom positions...\n";
00428 switch(mesh.type()) {
00429 case Mesh::cartesianHexahedraMesh: {
00430 __build(discretizationType, static_cast<const Structured3DMesh&>(mesh));
00431 break;
00432 }
00433 case Mesh::octreeMesh: {
00434 __build(discretizationType, static_cast<const OctreeMesh&>(mesh));
00435 break;
00436 }
00437 case Mesh::hexahedraMesh: {
00438 __build(discretizationType, static_cast<const MeshOfHexahedra&>(mesh));
00439 break;
00440 }
00441 case Mesh::spectralMesh: {
00442 __build(discretizationType, static_cast<const SpectralMesh&>(mesh));
00443 break;
00444 }
00445 case Mesh::tetrahedraMesh: {
00446 __build(discretizationType, static_cast<const MeshOfTetrahedra&>(mesh));
00447 break;
00448 }
00449 case Mesh::trianglesMesh: {
00450 __build(discretizationType, static_cast<const MeshOfTriangles&>(mesh));
00451 break;
00452 }
00453 case Mesh::surfaceMeshTriangles:
00454 case Mesh::surfaceMeshQuadrangles: {
00455 throw ErrorHandler(__FILE__,__LINE__,
00456 "Cannot solve problems on surface meshes",
00457 ErrorHandler::normal);
00458 break;
00459 }
00460 default: {
00461 throw ErrorHandler(__FILE__,__LINE__,
00462 "type of mesh not supported",
00463 ErrorHandler::unexpected);
00464 }
00465 }
00466 ffout(2) << "Computing degrees of freedom positions: done\n";
00467 }
00468
00469 void ScalarDegreeOfFreedomPositionsSet::
00470 __build(const ScalarDiscretizationTypeBase& discretizationType,
00471 const Mesh& mesh)
00472 {
00473 Builder builder(*this);
00474
00475 builder.build(discretizationType, mesh);
00476 }