00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef BOUNDARY_CONDITION_COMMON_FEM_DISCRETIZATION_HPP
00022 #define BOUNDARY_CONDITION_COMMON_FEM_DISCRETIZATION_HPP
00023
00024 #include <FiniteElementTraits.hpp>
00025
00026 #include <BoundaryConditionDiscretization.hpp>
00027
00028 #include <SurfaceMeshGenerator.hpp>
00029
00030 #include <SurfaceMeshOfQuadrangles.hpp>
00031 #include <SurfaceMeshOfTriangles.hpp>
00032
00033 #include <MatrixManagement.hpp>
00034
00035 #include <AutoPointer.hpp>
00036 #include <ConformTransformation.hpp>
00037
00038 #include <BoundaryMeshAssociation.hpp>
00039 #include <BoundaryConditionSurfaceMeshAssociation.hpp>
00040
00041 #include <Stringify.hpp>
00042 #include <ErrorHandler.hpp>
00043
00053 template <typename MeshType,
00054 ScalarDiscretizationTypeBase::Type TypeOfDiscretization>
00055 class BoundaryConditionCommonFEMDiscretization
00056 : public BoundaryConditionDiscretization
00057 {
00058 public:
00059 typedef
00060 typename MeshType::CellType
00061 CellType;
00064 typedef
00065 typename FiniteElementTraits<CellType, TypeOfDiscretization>::Type
00066 FiniteElement;
00068 typedef
00069 typename FiniteElement::QuadratureType
00070 QuadratureType;
00072 typedef
00073 typename FiniteElementTraits<CellType, TypeOfDiscretization>::Transformation
00074 ConformTransformation;
00076 protected:
00077 const MeshType& __mesh;
00079 ReferenceCounting<BoundaryConditionSurfaceMeshAssociation>
00080 __bcMeshAssociation;
00087 void __checkBoundaryMeshAssociation(const BoundaryMeshAssociation& bma)
00088 {
00089 for (BoundaryMeshAssociation::const_iterator i = bma.begin();
00090 i != bma.end(); ++i) {
00091 if (i->second == 0) {
00092 throw ErrorHandler(__FILE__,__LINE__,
00093 "The mesh of boundary "
00094 +stringify(*(i->first))+" was not generated",
00095 ErrorHandler::unexpected);
00096 } else {
00097 const SurfaceMesh& s = *(i->second);
00098 if (not(s.isAssociatedTo(__mesh))) {
00099 throw ErrorHandler(__FILE__,__LINE__,
00100 "The mesh of boundary "
00101 +stringify(*(i->first))
00102 +" is not related to the volume mesh"
00103 +"(check your mesh and/or report the error)",
00104 ErrorHandler::normal);
00105 }
00106 }
00107 }
00108 }
00109
00116 void __associatesDefinedMeshToBoundaryConditions(const BoundaryMeshAssociation& bma)
00117 {
00118 __bcMeshAssociation = new BoundaryConditionSurfaceMeshAssociation(__problem,bma);
00119 }
00120
00121 public:
00122
00127 virtual void associatesMeshesToBoundaryConditions()
00128 {
00129 BoundaryMeshAssociation bma(__problem, __mesh);
00130 this->__checkBoundaryMeshAssociation(bma);
00131 this->__associatesDefinedMeshToBoundaryConditions(bma);
00132 }
00133
00139 const MeshType& mesh() const
00140 {
00141 return __mesh;
00142 }
00143
00149 MeshType& mesh()
00150 {
00151 return __mesh;
00152 }
00153
00163 BoundaryConditionCommonFEMDiscretization(const Problem& problem,
00164 const MeshType& aMesh,
00165 const DegreeOfFreedomSet& dof)
00166 : BoundaryConditionDiscretization(problem,dof),
00167 __mesh(aMesh)
00168 {
00169 ;
00170 }
00171
00176 virtual ~BoundaryConditionCommonFEMDiscretization()
00177 {
00178 ;
00179 }
00180
00182 protected:
00183
00184 template <typename MatrixType,
00185 typename BoundaryMeshType>
00186 void
00187 __setVariationalBoundaryConditionsAlphaUV(const ScalarFunctionBase& alpha,
00188 const size_t& equationNumber,
00189 const size_t& unknownNumber,
00190 MatrixType& A,
00191 const BoundaryMeshType& surfaceMesh) const
00192 {
00193 typedef typename BoundaryMeshType::CellType BoundaryCellType;
00194
00195 typedef
00196 typename FiniteElementTraits<BoundaryCellType,
00197 TypeOfDiscretization>::Transformation
00198 BoundaryConformTransformation;
00199
00200 typedef
00201 typename FiniteElementTraits<BoundaryCellType,
00202 TypeOfDiscretization>::JacobianTransformation
00203 BoundaryConformTransformationJacobian;
00204
00205 typedef
00206 typename FiniteElementTraits<BoundaryCellType,
00207 TypeOfDiscretization>::Type
00208 BoundaryFiniteElement;
00209
00210 typedef
00211 typename BoundaryFiniteElement::QuadratureType
00212 BoundaryQuadratureType;
00213
00214 const FiniteElement& finiteElement
00215 = FiniteElement::instance();
00216
00217 const BoundaryQuadratureType& referenceBoundaryQuadrature
00218 = BoundaryQuadratureType::instance();
00219
00220 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00221 = this->__degreeOfFreedomSet.positionsSet(0);
00222
00223 AutoPointer<ConformTransformation> pT;
00224
00225 const CellType* currentCell = 0;
00226
00227 for (typename BoundaryMeshType::const_iterator icell(surfaceMesh);
00228 not(icell.end()); ++icell) {
00229 const BoundaryCellType& cell = *icell;
00230 const BoundaryConformTransformation boundaryT(cell);
00231 const BoundaryConformTransformationJacobian boundaryJ(boundaryT);
00232
00233 const CellType& K
00234 = static_cast<const CellType&>(cell.mother());
00235
00236 if(currentCell != &K) {
00237 pT = new ConformTransformation(K);
00238 currentCell = &K;
00239 }
00240 const size_t cellNumber = __mesh.cellNumber(K);
00241
00242 const ConformTransformation& T = *pT;
00243
00244 for (size_t k=0; k<BoundaryQuadratureType::numberOfQuadraturePoints;
00245 k++) {
00246
00247 TinyVector<3, real_t> q;
00248 boundaryT.value(referenceBoundaryQuadrature[k], q);
00249
00250 const real_t weight
00251 = referenceBoundaryQuadrature.weight(k)
00252 * boundaryJ.jacobianDet();
00253
00254 TinyVector<3> coordinates;
00255 T.invertT(q, coordinates);
00256
00257 const real_t AlphaValue = alpha(q);
00258
00259 typename FiniteElement::ElementaryVector W;
00260 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00261 W[l] = finiteElement.W(l,coordinates);
00262
00263 typename FiniteElement::ElementaryMatrix WiWj;
00264
00265 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00266 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++)
00267 WiWj(l,m) = W[l] * W[m];
00268
00269 size_t indicesI[FiniteElement::numberOfDegreesOfFreedom];
00270 size_t indicesJ[FiniteElement::numberOfDegreesOfFreedom];
00271 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00272 const size_t variableDOFNumber = dofPositions(cellNumber,l);
00273 indicesI[l] = __degreeOfFreedomSet(unknownNumber,
00274 variableDOFNumber);
00275 indicesJ[l] = __degreeOfFreedomSet(equationNumber,
00276 variableDOFNumber);
00277 }
00278
00279 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00280 const size_t I = indicesI[l];
00281 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00282 const size_t J = indicesJ[m];
00283 A(I,J) += weight * AlphaValue * WiWj(l,m);
00284 }
00285 }
00286 }
00287 }
00288 }
00289
00290 template <typename BoundaryMeshType>
00291 void __setSecondMemberDirichlet(const Dirichlet& dirichlet,
00292 const size_t& equationNumber,
00293 const BoundaryMeshType& surfMesh) const
00294 {
00295 typedef FiniteElementTraits<typename BoundaryMeshType::CellType,
00296 TypeOfDiscretization>
00297 FEType;
00298
00299 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00300 = this->__degreeOfFreedomSet.positionsSet(0);
00301
00302 typedef typename FEType::Transformation ConformTransformation;
00303
00304
00305 for (typename BoundaryMeshType::const_iterator iBorderCell(surfMesh);
00306 not(iBorderCell.end()); ++iBorderCell) {
00307 const typename BoundaryMeshType::CellType& borderCell = *iBorderCell;
00308
00309 const size_t cellNumber
00310 = __mesh.cellNumber(static_cast<const CellType&>(borderCell.mother()));
00311 const size_t& faceNumber = borderCell.motherCellFaceNumber();
00312
00313 for (size_t i=0; i<FiniteElement::numberOfFaceLivingDegreesOfFreedom; ++i) {
00314 const size_t& dofNumber = dofPositions(cellNumber,
00315 FiniteElement::facesDOF[faceNumber][i]);
00316 const size_t I = __degreeOfFreedomSet(equationNumber,
00317 dofPositions(cellNumber,
00318 FiniteElement::facesDOF[faceNumber][i]));
00319 if (not(__dirichletList[I])) {
00320 const real_t GValue = dirichlet.g(dofPositions.vertex(dofNumber));
00321 __dirichletValues[I] = GValue;
00322 __dirichletList[I] = true;
00323 }
00324 }
00325 }
00326 }
00327
00328 template <typename VectorType,
00329 typename BoundaryMeshType>
00330 void
00331 __getDiagonalNaturalBoundaryConditions(const ScalarFunctionBase& alpha,
00332 const size_t& equationNumber,
00333 VectorType& z,
00334 const BoundaryMeshType& surfaceMesh) const
00335 {
00336 typedef typename BoundaryMeshType::CellType BoundaryCellType;
00337
00338 typedef
00339 typename FiniteElementTraits<BoundaryCellType,
00340 TypeOfDiscretization>::Transformation
00341 BoundaryConformTransformation;
00342
00343 typedef
00344 typename FiniteElementTraits<BoundaryCellType,
00345 TypeOfDiscretization>::JacobianTransformation
00346 BoundaryConformTransformationJacobian;
00347
00348 typedef
00349 typename FiniteElementTraits<BoundaryCellType,TypeOfDiscretization>::Type
00350 BoundaryFiniteElement;
00351
00352 typedef typename BoundaryFiniteElement::QuadratureType BoundaryQuadratureType;
00353
00354 const FiniteElement& finiteElement
00355 = FiniteElement::instance();
00356
00357 const BoundaryQuadratureType& referenceBoundaryQuadrature
00358 = BoundaryQuadratureType::instance();
00359
00360 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00361 = this->__degreeOfFreedomSet.positionsSet(0);
00362
00363 AutoPointer<ConformTransformation> pT;
00364
00365 const CellType* currentCell = 0;
00366
00367 for (typename BoundaryMeshType::const_iterator icell(surfaceMesh);
00368 not(icell.end()); ++icell) {
00369 const BoundaryCellType& cell = *icell;
00370 const BoundaryConformTransformation boundaryT(cell);
00371 const BoundaryConformTransformationJacobian boundaryJ(boundaryT);
00372
00373 const CellType& K
00374 = static_cast<const CellType&>(cell.mother());
00375
00376 if(currentCell != &K) {
00377 pT = new ConformTransformation(K);
00378 currentCell = &K;
00379 }
00380 const size_t cellNumber = __mesh.cellNumber(K);
00381 const ConformTransformation& T = *pT;
00382
00383 for (size_t k=0; k<BoundaryQuadratureType::numberOfQuadraturePoints;
00384 k++) {
00385
00386 TinyVector<3, real_t> q;
00387 boundaryT.value(referenceBoundaryQuadrature[k], q);
00388
00389 const real_t weight
00390 = referenceBoundaryQuadrature.weight(k)
00391 * boundaryJ.jacobianDet();
00392
00393 TinyVector<3, real_t> coordinates;
00394 T.invertT(q, coordinates);
00395
00396 const real_t AlphaValue = alpha(q);
00397
00398 typename FiniteElement::ElementaryVector W;
00399
00400 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00401 W[l] = finiteElement.W(l,coordinates);
00402
00403 size_t indices[FiniteElement::numberOfDegreesOfFreedom];
00404 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00405 indices[l] = __degreeOfFreedomSet(equationNumber,
00406 dofPositions(cellNumber,l));
00407 }
00408
00409 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00410 const size_t& I = indices[l];
00411 z[I] += W[l] * W[l] * weight * AlphaValue;
00412 }
00413 }
00414 }
00415 }
00416
00417 template <typename VectorType,
00418 typename BoundaryMeshType>
00419 void
00420 __setVariationalBoundaryConditionsFV(const ScalarFunctionBase& g,
00421 const size_t& equationNumber,
00422 VectorType& b,
00423 const BoundaryMeshType& boundaryMesh) const
00424 {
00425 typedef typename BoundaryMeshType::CellType BoundaryCellType;
00426
00427 typedef
00428 typename FiniteElementTraits<BoundaryCellType,
00429 TypeOfDiscretization>::Transformation
00430 BoundaryConformTransformation;
00431
00432 typedef
00433 typename FiniteElementTraits<BoundaryCellType,
00434 TypeOfDiscretization>::JacobianTransformation
00435 BoundaryConformTransformationJacobian;
00436
00437 typedef
00438 typename FiniteElementTraits<BoundaryCellType,
00439 TypeOfDiscretization>::Type
00440 BoundaryFiniteElement;
00441
00442 typedef
00443 typename BoundaryFiniteElement::QuadratureType
00444 BoundaryQuadratureType;
00445
00446 const FiniteElement& finiteElement
00447 = FiniteElement::instance();
00448
00449 const BoundaryQuadratureType& referenceBoundaryQuadrature
00450 = BoundaryQuadratureType::instance();
00451
00452 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00453 = this->__degreeOfFreedomSet.positionsSet(0);
00454
00455 AutoPointer<ConformTransformation> pT;
00456
00457 const CellType* currentCell = 0;
00458
00459 for (typename BoundaryMeshType::const_iterator icell(boundaryMesh);
00460 not(icell.end()); ++icell) {
00461 const BoundaryCellType& cell = *icell;
00462 const BoundaryConformTransformation boundaryT(cell);
00463 const BoundaryConformTransformationJacobian boundaryJ(boundaryT);
00464
00465 const CellType& K
00466 = static_cast<const CellType&>(cell.mother());
00467
00468 if (currentCell != &K) {
00469 pT = new ConformTransformation(K);
00470 currentCell = &K;
00471 }
00472
00473 const ConformTransformation& T = *pT;
00474
00475 for (size_t k=0; k<BoundaryQuadratureType::numberOfQuadraturePoints;
00476 k++) {
00477
00478 TinyVector<3, real_t> q;
00479 boundaryT.value(referenceBoundaryQuadrature[k], q);
00480
00481 const real_t weight
00482 = referenceBoundaryQuadrature.weight(k)
00483 * boundaryJ.jacobianDet();
00484
00485 TinyVector<3> coordinates;
00486 T.invertT(q, coordinates);
00487
00488 const real_t GValue = g(q);
00489
00490 typename FiniteElement::ElementaryVector W;
00491 size_t indices[FiniteElement::numberOfDegreesOfFreedom];
00492
00493 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00494 W[l] = finiteElement.W(l,coordinates);
00495 indices[l] = dofPositions(__mesh.cellNumber(K),l);
00496 }
00497
00498 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00499 const size_t I = __degreeOfFreedomSet(equationNumber,
00500 indices[l]);
00501 b[I] += weight * GValue * W[l];
00502 }
00503 }
00504 }
00505 }
00506
00507 template <typename VectorType,
00508 typename BoundaryMeshType>
00509 void
00510 __variationalBoundaryConditionsAlphaUVTimesX(const ScalarFunctionBase& alpha,
00511 const size_t& equationNumber,
00512 const size_t& unknownNumber,
00513 const VectorType& x,
00514 VectorType& z,
00515 const BoundaryMeshType& boundaryMesh) const
00516 {
00517 typedef typename BoundaryMeshType::CellType BoundaryCellType;
00518
00519 typedef
00520 typename FiniteElementTraits<BoundaryCellType,
00521 TypeOfDiscretization>::Transformation
00522 BoundaryConformTransformation;
00523
00524 typedef
00525 typename FiniteElementTraits<BoundaryCellType,
00526 TypeOfDiscretization>::JacobianTransformation
00527 BoundaryConformTransformationJacobian;
00528
00529 typedef
00530 typename FiniteElementTraits<BoundaryCellType,
00531 TypeOfDiscretization>::Type
00532 BoundaryFiniteElement;
00533
00534 typedef
00535 typename BoundaryFiniteElement::QuadratureType
00536 BoundaryQuadratureType;
00537
00538 const FiniteElement& finiteElement
00539 = FiniteElement::instance();
00540
00541 const BoundaryQuadratureType& referenceBoundaryQuadrature
00542 = BoundaryQuadratureType::instance();
00543
00544 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00545 = this->__degreeOfFreedomSet.positionsSet(0);
00546
00547 AutoPointer<ConformTransformation> pT;
00548
00549 const CellType* currentCell = 0;
00550
00551 for (typename BoundaryMeshType::const_iterator icell(boundaryMesh);
00552 not(icell.end()); ++icell) {
00553 const BoundaryCellType& cell = *icell;
00554 const BoundaryConformTransformation boundaryT(cell);
00555 const BoundaryConformTransformationJacobian boundaryJ(boundaryT);
00556
00557 const CellType& K = static_cast<const CellType&>(cell.mother());
00558
00559 if(currentCell != &K) {
00560 pT = new ConformTransformation(K);
00561 currentCell = &K;
00562 }
00563
00564 const size_t cellNumber = __mesh.cellNumber(K);
00565
00566 const ConformTransformation& T = *pT;
00567
00568 for (size_t k=0; k<BoundaryQuadratureType::numberOfQuadraturePoints;
00569 k++) {
00570
00571 TinyVector<3, real_t> q;
00572 boundaryT.value(referenceBoundaryQuadrature[k], q);
00573
00574 const real_t weight
00575 = referenceBoundaryQuadrature.weight(k)
00576 * boundaryJ.jacobianDet();
00577
00578 TinyVector<3> coordinates;
00579 T.invertT(q, coordinates);
00580
00581 const real_t AlphaValue = alpha(q);
00582
00583 typename FiniteElement::ElementaryVector W;
00584 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00585 W[l] = finiteElement.W(l,coordinates);
00586
00587 typename FiniteElement::ElementaryMatrix WiWj;
00588
00589 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00590 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++)
00591 WiWj(l,m) = W[l] * W[m];
00592
00593 size_t indicesI[FiniteElement::numberOfDegreesOfFreedom];
00594 size_t indicesJ[FiniteElement::numberOfDegreesOfFreedom];
00595 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00596 const size_t variableDOFNumber = dofPositions(cellNumber,l);
00597 indicesI[l] = __degreeOfFreedomSet(unknownNumber,
00598 variableDOFNumber);
00599 indicesJ[l] = __degreeOfFreedomSet(equationNumber,
00600 variableDOFNumber);
00601 }
00602
00603 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00604 const size_t I = indicesI[l];
00605 if (not(__dirichletList[I])) {
00606 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00607 const size_t J = indicesJ[m];
00608 if (not(__dirichletList[J])) {
00609 z[I] += WiWj(l,m) * weight * AlphaValue * x[J];
00610 }
00611 }
00612 }
00613 }
00614 }
00615 }
00616 }
00617
00618 template <typename VectorType,
00619 typename BoundaryMeshType>
00620 void
00621 __variationalBoundaryConditionsAlphaUVTransposedTimesX(const ScalarFunctionBase& alpha,
00622 const size_t& equationNumber,
00623 const size_t& unknownNumber,
00624 const VectorType& x,
00625 VectorType& z,
00626 const BoundaryMeshType& boundaryMesh) const
00627 {
00628 typedef typename BoundaryMeshType::CellType BoundaryCellType;
00629
00630 typedef
00631 typename FiniteElementTraits<BoundaryCellType,
00632 TypeOfDiscretization>::Transformation
00633 BoundaryConformTransformation;
00634
00635 typedef
00636 typename FiniteElementTraits<BoundaryCellType,
00637 TypeOfDiscretization>::JacobianTransformation
00638 BoundaryConformTransformationJacobian;
00639
00640 typedef
00641 typename FiniteElementTraits<BoundaryCellType,
00642 TypeOfDiscretization>::Type
00643 BoundaryFiniteElement;
00644
00645 typedef
00646 typename BoundaryFiniteElement::QuadratureType
00647 BoundaryQuadratureType;
00648
00649 const FiniteElement& finiteElement
00650 = FiniteElement::instance();
00651
00652 const BoundaryQuadratureType& referenceBoundaryQuadrature
00653 = BoundaryQuadratureType::instance();
00654
00655 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00656 = this->__degreeOfFreedomSet.positionsSet(0);
00657
00658 AutoPointer<ConformTransformation> pT;
00659
00660 const CellType* currentCell = 0;
00661
00662 for (typename BoundaryMeshType::const_iterator icell(boundaryMesh);
00663 not(icell.end()); ++icell) {
00664 const BoundaryCellType& cell = *icell;
00665 const BoundaryConformTransformation boundaryT(cell);
00666 const BoundaryConformTransformationJacobian boundaryJ(boundaryT);
00667
00668 const CellType& K = static_cast<const CellType&>(cell.mother());
00669
00670 if(currentCell != &K) {
00671 pT = new ConformTransformation(K);
00672 currentCell = &K;
00673 }
00674
00675 const size_t cellNumber = __mesh.cellNumber(K);
00676
00677 const ConformTransformation& T = *pT;
00678
00679 for (size_t k=0; k<BoundaryQuadratureType::numberOfQuadraturePoints;
00680 k++) {
00681
00682 TinyVector<3, real_t> q;
00683 boundaryT.value(referenceBoundaryQuadrature[k], q);
00684
00685 const real_t weight
00686 = referenceBoundaryQuadrature.weight(k)
00687 * boundaryJ.jacobianDet();
00688
00689 TinyVector<3> coordinates;
00690 T.invertT(q, coordinates);
00691
00692 const real_t AlphaValue = alpha(q);
00693
00694 typename FiniteElement::ElementaryVector W;
00695 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00696 W[l] = finiteElement.W(l,coordinates);
00697
00698 typename FiniteElement::ElementaryMatrix WiWj;
00699
00700 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++)
00701 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++)
00702 WiWj(l,m) = W[l] * W[m];
00703
00704 size_t indicesI[FiniteElement::numberOfDegreesOfFreedom];
00705 size_t indicesJ[FiniteElement::numberOfDegreesOfFreedom];
00706 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00707 const size_t variableDOFNumber = dofPositions(cellNumber,l);
00708 indicesI[l] = __degreeOfFreedomSet(unknownNumber,
00709 variableDOFNumber);
00710 indicesJ[l] = __degreeOfFreedomSet(equationNumber,
00711 variableDOFNumber);
00712 }
00713
00714 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00715 const size_t I = indicesI[l];
00716 if (not(__dirichletList[I])) {
00717 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00718 const size_t J = indicesJ[m];
00719 if (not(__dirichletList[J])) {
00720 z[J] += WiWj(l,m) * weight * AlphaValue * x[I];
00721 }
00722 }
00723 }
00724 }
00725 }
00726 }
00727 }
00728
00729 template <typename FunctionClass>
00730 static void __meshWrapper(const SurfaceMesh& surfmesh, const FunctionClass& F)
00731 {
00732 switch (surfmesh.type()) {
00733 case Mesh::surfaceMeshTriangles: {
00734 const SurfaceMeshOfTriangles& surfTria
00735 = dynamic_cast<const SurfaceMeshOfTriangles&>(surfmesh);
00736 F.eval(surfTria);
00737 break;
00738 }
00739 case Mesh::surfaceMeshQuadrangles: {
00740 const SurfaceMeshOfQuadrangles& surfQuad
00741 = dynamic_cast<const SurfaceMeshOfQuadrangles&>(surfmesh);
00742 F.eval(surfQuad);
00743 break;
00744 }
00745 default: {
00746 throw ErrorHandler(__FILE__,__LINE__,
00747 "unknown surface mesh type",
00748 ErrorHandler::unexpected);
00749 }
00750 }
00751 }
00752
00753
00754
00755 template <typename VectorType>
00756 static void
00757 __StandardGetDiagonalVariationalBorderBilinearOperator(const BoundaryConditionCommonFEMDiscretization<MeshType,
00758 TypeOfDiscretization>& __bc,
00759 VectorType& z)
00760 {
00761 const BoundaryConditionSurfaceMeshAssociation& bcMeshAssociation = *__bc.__bcMeshAssociation;
00762
00763 for (BoundaryConditionSurfaceMeshAssociation
00764 ::BilinearBorderOperatorMeshAssociation
00765 ::const_iterator i = bcMeshAssociation.beginOfBilinear();
00766 i != bcMeshAssociation.endOfBilinear(); ++i) {
00767
00768 switch (i->first->type()) {
00769 case VariationalBilinearBorderOperator::alphaUV: {
00770 const VariationalBorderOperatorAlphaUV& V
00771 = dynamic_cast<const VariationalBorderOperatorAlphaUV&>(*i->first);
00772 const Mesh& boundaryMesh = (*i->second);
00773 switch(boundaryMesh.type()) {
00774 case Mesh::surfaceMeshTriangles: {
00775 __bc.__getDiagonalNaturalBoundaryConditions(V.alpha(),
00776 V.testFunctionNumber(), z,
00777 dynamic_cast<const SurfaceMeshOfTriangles&>(boundaryMesh));
00778 break;
00779 }
00780 case Mesh::surfaceMeshQuadrangles: {
00781 __bc.__getDiagonalNaturalBoundaryConditions(V.alpha(),
00782 V.testFunctionNumber(), z,
00783 dynamic_cast<const SurfaceMeshOfQuadrangles&>(boundaryMesh));
00784 break;
00785 }
00786 default: {
00787 throw ErrorHandler(__FILE__,__LINE__,
00788 "not implemented",
00789 ErrorHandler::unexpected);
00790 }
00791 }
00792 break;
00793 }
00794 default: {
00795 throw ErrorHandler(__FILE__,__LINE__,
00796 "not implemented",
00797 ErrorHandler::unexpected);
00798 }
00799 }
00800 }
00801 }
00802
00803 template <typename VectorType>
00804 static void
00805 __StandardGetDiagonalDirichletBorderBilinearOperator(const BoundaryConditionCommonFEMDiscretization<MeshType,
00806 TypeOfDiscretization>& bc,
00807 VectorType& z)
00808 {
00809 for (size_t i=0; i<bc.__dirichletList.size(); ++i) {
00810 if (bc.__dirichletList[i]) {
00811 z[i] = 1;
00812 }
00813 }
00814 }
00815
00816 template <typename MatrixType>
00817 static void
00818 __StandardVariationalBorderBilinearOperator(const BoundaryConditionCommonFEMDiscretization<MeshType,
00819 TypeOfDiscretization>& __bc,
00820 MatrixType& A)
00821 {
00822 const BoundaryConditionSurfaceMeshAssociation& bcMeshAssociation = *__bc.__bcMeshAssociation;
00823
00824 for (BoundaryConditionSurfaceMeshAssociation
00825 ::BilinearBorderOperatorMeshAssociation
00826 ::const_iterator i = bcMeshAssociation.beginOfBilinear();
00827 i != bcMeshAssociation.endOfBilinear(); ++i) {
00828
00829 switch (i->first->type()) {
00830 case VariationalBilinearBorderOperator::alphaUV: {
00831 const VariationalBorderOperatorAlphaUV& V
00832 = dynamic_cast<const VariationalBorderOperatorAlphaUV&>(*i->first);
00833
00834 const Mesh& boundaryMesh = *i->second;
00835
00836 switch (boundaryMesh.type()) {
00837 case Mesh::surfaceMeshTriangles: {
00838 __bc.__setVariationalBoundaryConditionsAlphaUV<MatrixType> (V.alpha(),
00839 V.testFunctionNumber(),
00840 V.unknownNumber(),
00841 A,
00842 dynamic_cast<const SurfaceMeshOfTriangles&>(boundaryMesh));
00843 break;
00844 }
00845 case Mesh::surfaceMeshQuadrangles: {
00846 __bc.__setVariationalBoundaryConditionsAlphaUV<MatrixType> (V.alpha(),
00847 V.testFunctionNumber(),
00848 V.unknownNumber(),
00849 A,
00850 dynamic_cast<const SurfaceMeshOfQuadrangles&>(boundaryMesh));
00851 break;
00852 }
00853 default: {
00854 throw ErrorHandler(__FILE__,__LINE__,
00855 "not implemented",
00856 ErrorHandler::unexpected);
00857 }
00858 }
00859 break;
00860 }
00861 default: {
00862 throw ErrorHandler(__FILE__,__LINE__,
00863 "not implemented",
00864 ErrorHandler::unexpected);
00865 }
00866 }
00867 }
00868 }
00869
00870 template <typename MatrixType>
00871 static void
00872 __StandardDirichletBorderBilinearOperator(const BoundaryConditionCommonFEMDiscretization<MeshType,
00873 TypeOfDiscretization>& __bc,
00874 MatrixType& A)
00875
00876 {
00877 for (size_t i=0; i<__bc.__dirichletList.size(); ++i) {
00878 if (__bc.__dirichletList[i]) {
00879 for (DoubleHashedMatrix::iterator lineBrowser = A.beginOfLine(i);
00880 lineBrowser != A.endOfLine(i); ++lineBrowser) {
00881 #warning should use a syntax like "M.line(i) = 0;"
00882 lineBrowser.second() = 0;
00883 }
00884
00885 for (DoubleHashedMatrix::iterator columnBrowser = A.beginOfColumn(i);
00886 columnBrowser != A.endOfColumn(i); ++columnBrowser) {
00887 columnBrowser.second() = 0;
00888 }
00889 A(i,i) = 1.;
00890 }
00891 }
00892 }
00893
00894 template <typename VectorType>
00895 static void
00896 __StandardVariationalBorderLinearOperator(const BoundaryConditionCommonFEMDiscretization<MeshType,
00897 TypeOfDiscretization>& __bc,
00898 VectorType& b)
00899 {
00900 const BoundaryConditionSurfaceMeshAssociation& bcMeshAssociation = *__bc.__bcMeshAssociation;
00901
00902 for (BoundaryConditionSurfaceMeshAssociation
00903 ::LinearBorderOperatorMeshAssociation
00904 ::const_iterator i = bcMeshAssociation.beginOfLinear();
00905 i != bcMeshAssociation.endOfLinear(); ++i) {
00906
00907 switch (i->first->type()) {
00908 case VariationalLinearBorderOperator::FV: {
00909 const VariationalBorderOperatorFV& V
00910 = dynamic_cast<const VariationalBorderOperatorFV&>(*i->first);
00911
00912 const Mesh& boundaryMesh = (*i->second);
00913 switch(boundaryMesh.type()) {
00914 case Mesh::surfaceMeshTriangles: {
00915 __bc.__setVariationalBoundaryConditionsFV(V.f(), V.testFunctionNumber(), b,
00916 dynamic_cast<const SurfaceMeshOfTriangles&>(boundaryMesh));
00917 break;
00918 }
00919 case Mesh::surfaceMeshQuadrangles: {
00920 __bc.__setVariationalBoundaryConditionsFV(V.f(), V.testFunctionNumber(), b,
00921 dynamic_cast<const SurfaceMeshOfQuadrangles&>(boundaryMesh));
00922 break;
00923 }
00924 default: {
00925 throw ErrorHandler(__FILE__,__LINE__,
00926 "not implemented",
00927 ErrorHandler::unexpected);
00928 }
00929 }
00930 break;
00931 }
00932 default: {
00933 throw ErrorHandler(__FILE__,__LINE__,
00934 "not implemented",
00935 ErrorHandler::unexpected);
00936 }
00937 }
00938 }
00939 }
00940
00941 template <typename MatrixType,
00942 typename VectorType>
00943 static void
00944 __StandardDirichletBorderLinearOperator(const BoundaryConditionCommonFEMDiscretization<MeshType,
00945 TypeOfDiscretization>& bc,
00946 MatrixType& A,
00947 VectorType& b)
00948 {
00949 bc.__dirichletValues.resize(bc.__degreeOfFreedomSet.size());
00950 bc.__dirichletValues = 0;
00951 const BoundaryConditionSurfaceMeshAssociation& bcMeshAssociation = *bc.__bcMeshAssociation;
00952
00953
00954 for (size_t i=0; i<bc.problem().numberOfUnknown(); ++i) {
00955 for (BoundaryConditionSurfaceMeshAssociation
00956 ::DirichletMeshAssociation
00957 ::const_iterator ibcMesh = bcMeshAssociation.bc(i).begin();
00958 ibcMesh != bcMeshAssociation.bc(i).end();
00959 ++ibcMesh) {
00960 const Dirichlet& D = *ibcMesh->first;
00961 const Mesh& boundaryMesh = *ibcMesh->second;
00962 switch(boundaryMesh.type()) {
00963 case Mesh::surfaceMeshTriangles: {
00964 bc.__setSecondMemberDirichlet(D,i,
00965 dynamic_cast<const SurfaceMeshOfTriangles&>(boundaryMesh));
00966 break;
00967 }
00968 case Mesh::surfaceMeshQuadrangles: {
00969 bc.__setSecondMemberDirichlet(D,i,
00970 dynamic_cast<const SurfaceMeshOfQuadrangles&>(boundaryMesh));
00971 break;
00972 }
00973 default: {
00974 throw ErrorHandler(__FILE__,__LINE__,
00975 "not implemented",
00976 ErrorHandler::unexpected);
00977 }
00978 }
00979 }
00980 }
00981
00982 Vector<bool> temp(bc.__dirichletList);
00983 bc.__dirichletList=false;
00984 Vector<real_t> y (bc.__dirichletValues.size());
00985 A.timesX(bc.__dirichletValues,y);
00986 b -= y;
00987 bc.__dirichletList=temp;
00988
00989 for (size_t i=0; i<b.size(); ++i) {
00990 if (bc.__dirichletList[i]) {
00991 b[i] = bc.__dirichletValues[i];
00992 }
00993 }
00994 }
00995
00996 template <typename VectorType>
00997 static void
00998 __StandardVariationalBorderBilinearOperatorTimesX(const BoundaryConditionCommonFEMDiscretization<MeshType,
00999 TypeOfDiscretization>& __bc,
01000 const VectorType& x,
01001 VectorType& z)
01002 {
01003 const BoundaryConditionSurfaceMeshAssociation& bcMeshAssociation = *__bc.__bcMeshAssociation;
01004 for (BoundaryConditionSurfaceMeshAssociation
01005 ::BilinearBorderOperatorMeshAssociation
01006 ::const_iterator i = bcMeshAssociation.beginOfBilinear();
01007 i != bcMeshAssociation.endOfBilinear(); ++i) {
01008
01009 switch (i->first->type()) {
01010 case VariationalBilinearBorderOperator::alphaUV: {
01011
01012 const VariationalBorderOperatorAlphaUV& V
01013 = dynamic_cast<const VariationalBorderOperatorAlphaUV&>(*i->first);
01014
01015 const Mesh& boundaryMesh = (*i->second);
01016
01017 switch(boundaryMesh.type()) {
01018 case Mesh::surfaceMeshTriangles : {
01019 __bc.__variationalBoundaryConditionsAlphaUVTimesX(V.alpha(),
01020 V.testFunctionNumber(),
01021 V.unknownNumber(),
01022 x,
01023 z,
01024 dynamic_cast<const SurfaceMeshOfTriangles&>(boundaryMesh));
01025 break;
01026 }
01027 case Mesh::surfaceMeshQuadrangles : {
01028 __bc.__variationalBoundaryConditionsAlphaUVTimesX(V.alpha(),
01029 V.testFunctionNumber(),
01030 V.unknownNumber(),
01031 x,
01032 z,
01033 dynamic_cast<const SurfaceMeshOfQuadrangles&>(boundaryMesh));
01034 break;
01035 }
01036 default: {
01037 throw ErrorHandler(__FILE__,__LINE__,
01038 "not implemented",
01039 ErrorHandler::unexpected);
01040 }
01041 }
01042 break;
01043 }
01044 default: {
01045 throw ErrorHandler(__FILE__,__LINE__,
01046 "not implemented",
01047 ErrorHandler::unexpected);
01048 }
01049 }
01050 }
01051 }
01052
01053 template <typename VectorType>
01054 static void
01055 __StandardVariationalBorderBilinearOperatorTransposedTimesX(const BoundaryConditionCommonFEMDiscretization<MeshType,
01056 TypeOfDiscretization>& __bc,
01057 const VectorType& x,
01058 VectorType& z)
01059 {
01060 const BoundaryConditionSurfaceMeshAssociation& bcMeshAssociation = *__bc.__bcMeshAssociation;
01061 for (BoundaryConditionSurfaceMeshAssociation
01062 ::BilinearBorderOperatorMeshAssociation
01063 ::const_iterator i = bcMeshAssociation.beginOfBilinear();
01064 i != bcMeshAssociation.endOfBilinear(); ++i) {
01065
01066 switch (i->first->type()) {
01067 case VariationalBilinearBorderOperator::alphaUV: {
01068
01069 const VariationalBorderOperatorAlphaUV& V
01070 = dynamic_cast<const VariationalBorderOperatorAlphaUV&>(*i->first);
01071
01072 const Mesh& boundaryMesh = *i->second;
01073
01074 switch(boundaryMesh.type()) {
01075 case Mesh::surfaceMeshTriangles: {
01076 __bc.__variationalBoundaryConditionsAlphaUVTransposedTimesX(V.alpha(),
01077 V.testFunctionNumber(),
01078 V.unknownNumber(),
01079 x, z,
01080 dynamic_cast<const SurfaceMeshOfTriangles&>(boundaryMesh));
01081 break;
01082 }
01083 case Mesh::surfaceMeshQuadrangles: {
01084 __bc.__variationalBoundaryConditionsAlphaUVTransposedTimesX(V.alpha(),
01085 V.testFunctionNumber(),
01086 V.unknownNumber(),
01087 x, z,
01088 dynamic_cast<const SurfaceMeshOfQuadrangles&>(boundaryMesh));
01089 break;
01090 }
01091 default: {
01092 throw ErrorHandler(__FILE__,__LINE__,
01093 "not implemented",
01094 ErrorHandler::unexpected);
01095 }
01096 }
01097 break;
01098 }
01099 default: {
01100 throw ErrorHandler(__FILE__,__LINE__,
01101 "not implemented",
01102 ErrorHandler::unexpected);
01103 }
01104 }
01105 }
01106 }
01107
01108 template <typename VectorType>
01109 static void
01110 __StandardDirichletBorderBilinearOperatorTimesX(const BoundaryConditionCommonFEMDiscretization<MeshType,
01111 TypeOfDiscretization>& bc,
01112 const VectorType& x,
01113 VectorType& z)
01114 {
01115 for (size_t i=0; i<bc.__dirichletList.size(); ++i) {
01116 if (bc.__dirichletList[i]) {
01117 z[i] = x[i];
01118 }
01119 }
01120 }
01121
01122 template <typename VectorType>
01123 static void
01124 __StandardDirichletBorderBilinearOperatorTransposedTimesX(const BoundaryConditionCommonFEMDiscretization<MeshType,
01125 TypeOfDiscretization>& bc,
01126 const VectorType& x,
01127 VectorType& z)
01128 {
01129 for (size_t i=0; i<bc.__dirichletList.size(); ++i) {
01130 if (bc.__dirichletList[i]) {
01131 z[i] = x[i];
01132 }
01133 }
01134 }
01135 };
01136
01137 #endif // BOUNDARY_CONDITION_COMMON_FEM_DISCRETIZATION_HPP
01138