00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef FEM_DISCRETIZATION_HPP
00021 #define FEM_DISCRETIZATION_HPP
00022
00023 #include <ElementaryMatrixSet.hpp>
00024
00025 #include <BaseFEMDiscretization.hpp>
00026
00027 #include <Mesh.hpp>
00028 #include <Structured3DMesh.hpp>
00029
00030 #include <Timer.hpp>
00031
00032 #include <DoubleHashedMatrix.hpp>
00033 #include <UnAssembledMatrix.hpp>
00034
00035 #include <ErrorHandler.hpp>
00036
00037 #include <FEMFunctionBase.hpp>
00038
00039 #include <SolverInformationCenter.hpp>
00040
00057 template <typename GivenMeshType,
00058 ScalarDiscretizationTypeBase::Type TypeOfDiscretization>
00059 class FEMDiscretization
00060 : public BaseFEMDiscretization<GivenMeshType,
00061 TypeOfDiscretization>
00062 {
00063 private:
00065 typedef GivenMeshType MeshType;
00066
00068 typedef typename MeshType::CellType CellType;
00069
00071 typedef typename FiniteElementTraits<CellType,
00072 TypeOfDiscretization>::Type FiniteElement;
00073
00075 typedef typename FiniteElement::QuadratureType QuadratureType;
00076
00078 typedef typename FiniteElement::ElementaryMatrix ElementaryMatrixType;
00079
00081 typedef typename FiniteElement::ElementaryVector ElementaryVectorType;
00082
00084 typedef typename FiniteElementTraits<CellType,
00085 TypeOfDiscretization>::Transformation ConformTransformation;
00086
00088 typedef typename FiniteElementTraits<CellType,
00089 TypeOfDiscretization>::JacobianTransformation JacobianTransformation;
00090
00091 public:
00097 void assembleMatrix()
00098 {
00099 const ScalarDegreeOfFreedomPositionsSet& dofPositions = this->__degreeOfFreedomSet.positionsSet(0);
00100
00101 switch ((this->__A).type()) {
00102 case BaseMatrix::doubleHashedMatrix: {
00103 Timer t;
00104 t.start();
00105
00106 ffout(2) << "- assembling matrix\n";
00107
00108 DoubleHashedMatrix& A = dynamic_cast<DoubleHashedMatrix&>(this->__A);
00109
00110 for(typename MeshType::const_iterator icell(this->__mesh);
00111 not(icell.end()); ++icell) {
00112 const CellType& K = *icell;
00113
00114 const size_t cellNumber = icell.number();
00115 TinyVector<FiniteElement::numberOfDegreesOfFreedom,
00116 size_t> index;
00117
00118 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00119 index[l] = dofPositions(cellNumber,l);
00120 }
00121
00122 ConformTransformation T(K);
00123 JacobianTransformation J(T);
00124 generatesElementaryMatrix(this->__eSet,J);
00125
00126 TinyVector<3> massCenter;
00127 T.value(FiniteElement::massCenter(), massCenter);
00128
00129 for(typename DiscretizedOperators<ElementaryMatrixType>
00130 ::iterator iOperator = this->__discretizedOperators.begin();
00131 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00132 const real_t coef = ((*iOperator).second)(massCenter);
00133
00134 const ElementaryMatrixType& elementaryMatrix
00135 = (*(*iOperator).first);
00136
00137 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00138 const size_t I
00139 = __degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00140 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00141 const size_t J
00142 = __degreeOfFreedomSet(((*iOperator).second).j(), index[m]);
00143 A(I,J) += coef*elementaryMatrix(l,m);
00144 }
00145 }
00146 }
00147 }
00148
00149 ffout(2) << "- assembling matrix: done";
00150 t.stop();
00151 ffout(3) << " [cost: " << t << ']';
00152 ffout(2) << '\n';
00153 break;
00154 }
00155 case BaseMatrix::unAssembled: {
00156 UnAssembledMatrix& A = dynamic_cast<UnAssembledMatrix&>(this->__A);
00157 A.setDiscretization(this);
00158 break;
00159 }
00160
00161 default: {
00162 throw ErrorHandler(__FILE__,__LINE__,
00163 "unexpected matrix type",
00164 ErrorHandler::unexpected);
00165 }
00166 }
00167 }
00168
00175 void timesX(const BaseVector& X, BaseVector& Z) const
00176 {
00177 const Vector<real_t>& x = dynamic_cast<const Vector<real_t>&>(X);
00178 Vector<real_t>& z = dynamic_cast<Vector<real_t>&>(Z);
00179 z=0;
00180
00181 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00182 = this->__degreeOfFreedomSet.positionsSet(0);
00183
00184 for(typename MeshType::const_iterator icell(this->__mesh);
00185 not(icell.end()); ++icell) {
00186 const CellType& K = *icell;
00187
00188 ConformTransformation T(K);
00189 JacobianTransformation J(T);
00190 generatesElementaryMatrix(this->__eSet,J);
00191
00192 const size_t cellNumber = icell.number();
00193
00194 TinyVector<FiniteElement::numberOfDegreesOfFreedom,size_t> index;
00195 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00196 index[l] = dofPositions(cellNumber,l);
00197 }
00198
00199 TinyVector<3> massCenter;
00200 T.value(FiniteElement::massCenter(), massCenter);
00201
00202 for(typename DiscretizedOperators<ElementaryMatrixType>
00203 ::iterator iOperator = this->__discretizedOperators.begin();
00204 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00205 const real_t coef = ((*iOperator).second)(massCenter);
00206 const ElementaryMatrixType& elementaryMatrix
00207 = (*(*iOperator).first);
00208
00209 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00210 const size_t I1
00211 = __degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00212 if (not((*this->__dirichletList)[I1])) {
00213 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00214 const size_t I2
00215 = __degreeOfFreedomSet(((*iOperator).second).j(), index[m]);
00216 if (not((*this->__dirichletList)[I2])) {
00217 z[I1] += coef*elementaryMatrix(l,m)*x[I2];
00218 }
00219 }
00220 }
00221 }
00222 }
00223 }
00224 }
00225
00232 void transposedTimesX(const BaseVector& X, BaseVector& Z) const
00233 {
00234 const Vector<real_t>& x = dynamic_cast<const Vector<real_t>&>(X);
00235 Vector<real_t>& z = dynamic_cast<Vector<real_t>&>(Z);
00236 z=0;
00237
00238 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00239 = this->__degreeOfFreedomSet.positionsSet(0);
00240
00241 for(typename MeshType::const_iterator icell(this->__mesh);
00242 not(icell.end()); ++icell) {
00243 const CellType& K = *icell;
00244
00245 ConformTransformation T(K);
00246 JacobianTransformation J(T);
00247 generatesElementaryMatrix(this->__eSet,J);
00248
00249 const size_t cellNumber = icell.number();
00250
00251 TinyVector<FiniteElement::numberOfDegreesOfFreedom,size_t> index;
00252 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00253 index[l] = dofPositions(cellNumber,l);
00254 }
00255
00256 TinyVector<3> massCenter;
00257 T.value(FiniteElement::massCenter(), massCenter);
00258
00259 for(typename DiscretizedOperators<ElementaryMatrixType>
00260 ::iterator iOperator = this->__discretizedOperators.begin();
00261 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00262 const real_t coef = ((*iOperator).second)(massCenter);
00263 const ElementaryMatrixType& elementaryMatrix
00264 = (*(*iOperator).first);
00265
00266 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00267 const size_t I1
00268 = __degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00269 if (not((*this->__dirichletList)[I1])) {
00270 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00271 const size_t I2
00272 = __degreeOfFreedomSet(((*iOperator).second).j(), index[m]);
00273 if (not((*this->__dirichletList)[I2])) {
00274 z[I2] += coef*elementaryMatrix(l,m)*x[I1];
00275 }
00276 }
00277 }
00278 }
00279 }
00280 }
00281 }
00282
00288 void getDiagonal(BaseVector& Z) const
00289 {
00290 Vector<real_t>& z = dynamic_cast<Vector<real_t>&>(Z);
00291
00292 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00293 = this->__degreeOfFreedomSet.positionsSet(0);
00294
00295 for(typename MeshType::const_iterator icell(this->__mesh);
00296 not(icell.end()); ++icell) {
00297 const CellType& K = *icell;
00298 const size_t cellNumber = icell.number();
00299
00300 ConformTransformation T(K);
00301 JacobianTransformation J(T);
00302 generatesElementaryMatrix(this->__eSet,J);
00303
00304 size_t index[FiniteElement::numberOfDegreesOfFreedom];
00305 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00306 index[l] = dofPositions(cellNumber,l);
00307 }
00308
00309 TinyVector<3> massCenter;
00310 T.value(FiniteElement::massCenter(), massCenter);
00311
00312 for(typename DiscretizedOperators<ElementaryMatrixType>
00313 ::iterator iOperator = this->__discretizedOperators.begin();
00314 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00315
00316 if (((*iOperator).second).i() == ((*iOperator).second).j()) {
00317 const real_t coef = ((*iOperator).second)(massCenter);
00318
00319 const ElementaryMatrixType& elementaryMatrix
00320 = (*(*iOperator).first);
00321
00322 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00323 const size_t I
00324 = this->__degreeOfFreedomSet(((*iOperator).second).i(),
00325 index[l]);
00326 z[I] += coef*elementaryMatrix(l,l);
00327 }
00328 }
00329 }
00330 }
00331 }
00332
00337 void assembleSecondMember()
00338 {
00339 Timer t;
00340 t.start();
00341
00342 ffout(2) << "- assembling second member\n";
00344 ElementaryVectorType eVect;
00345 Vector<real_t>& b = (static_cast<Vector<real_t>&>(this->__b));
00346 b = 0;
00347
00348 const QuadratureType& referenceQuadrature = QuadratureType::instance();
00349
00350 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00351 = this->__degreeOfFreedomSet.positionsSet(0);
00352
00353 switch(this->problem().type()) {
00354 case Problem::pde: {
00355 const PDESystem& pdeSystem
00356 = static_cast<const PDESystem&>(this->problem());
00357
00358 for(typename MeshType::const_iterator icell(this->__mesh);
00359 not(icell.end()); ++icell) {
00360 const CellType& K = *icell;
00361 eVect = 0;
00362 ConformTransformation T(K);
00363 JacobianTransformation J(T);
00364
00365 TinyVector<QuadratureType::numberOfQuadraturePoints,
00366 TinyVector<3> > quadrature;
00367 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
00368 T.value(referenceQuadrature[l], quadrature[l]);
00369 }
00370
00371 const size_t cellNumber = icell.number();
00372
00373 TinyVector<FiniteElement::numberOfDegreesOfFreedom, int> index;
00374 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00375 index[l] = dofPositions(cellNumber,l);
00376 }
00377
00378 for (size_t i=0; i<this->problem().numberOfUnknown(); ++i) {
00379 TinyVector<FiniteElement::numberOfQuadraturePoints, real_t> f;
00380 const ScalarFunctionBase& F = pdeSystem.secondMember(i);
00381
00382 for (size_t l=0; l<FiniteElement::numberOfQuadraturePoints; ++l)
00383 f[l] = F(quadrature[l]);
00384
00385 generatesElementaryVector(eVect,J,f);
00386
00387 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00388 const size_t dof = __degreeOfFreedomSet(i,index[l]);
00389 b[dof] += eVect[l]*J.jacobianDet();
00390 }
00391 }
00392 }
00393 break;
00394 }
00395 case Problem::variational: {
00396 const VariationalProblem& variationalProblem
00397 = dynamic_cast<const VariationalProblem&>(this->problem());
00398
00399 if (variationalProblem.hasJumpOrMean()) {
00400 throw ErrorHandler(__FILE__,__LINE__,
00401 "cannot discretize problems with jumps or means in FEM !",
00402 ErrorHandler::normal);
00403 }
00404
00405 for (VariationalProblem::linearOperatorConst_iterator i
00406 = variationalProblem.beginLinearOperator();
00407 i != variationalProblem.endLinearOperator(); ++i) {
00408 switch ((*(*i)).type()) {
00409 case VariationalLinearOperator::FV: {
00410 const VariationalOperatorFV& fv
00411 = dynamic_cast<const VariationalOperatorFV&>(*(*i));
00412
00413 const ScalarFunctionBase& F = fv.f();
00414 const size_t testFunctionNumber = fv.testFunctionNumber();
00415
00416 for(typename MeshType::const_iterator icell(this->__mesh);
00417 not(icell.end()); ++icell) {
00418 const CellType& K = *icell;
00419 eVect = 0;
00420 ConformTransformation T(K);
00421 JacobianTransformation J(T);
00422
00423 TinyVector<QuadratureType::numberOfQuadraturePoints,
00424 TinyVector<3> > quadrature;
00425 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
00426 T.value(referenceQuadrature[l], quadrature[l]);
00427 }
00428
00429 const size_t cellNumber = icell.number();
00430
00431 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00432 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00433 index[l] = dofPositions(cellNumber,l);
00434 }
00435
00436 TinyVector<FiniteElement::numberOfQuadraturePoints,real_t> f;
00437
00438 for (size_t l=0; l<FiniteElement::numberOfQuadraturePoints; ++l)
00439 f[l] = F(quadrature[l]);
00440
00441 generatesElementaryVector(eVect,J,f);
00442
00443 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00444 const size_t dof = __degreeOfFreedomSet(testFunctionNumber,index[l]);
00445 b[dof] += eVect[l]*J.jacobianDet();
00446 }
00447 }
00448 break;
00449 }
00450 case VariationalLinearOperator::FdxGV: {
00451 const VariationalOperatorFdxGV& fv
00452 = dynamic_cast<const VariationalOperatorFdxGV&>(*(*i));
00453
00454 const ScalarFunctionBase& F = fv.f();
00455 const ScalarFunctionBase& G = fv.g();
00456 const size_t testFunctionNumber = fv.testFunctionNumber();
00457
00458 Vector<real_t> gValues (dofPositions.number());
00459
00460 for (size_t i=0; i<dofPositions.number(); ++i) {
00461 gValues[i] = G(dofPositions.vertex(i));
00462 }
00463
00464
00465 for (typename MeshType::const_iterator icell(this->__mesh);
00466 not(icell.end()); ++icell) {
00467 const CellType& K = *icell;
00468
00469 ConformTransformation T(K);
00470 JacobianTransformation J(T);
00471
00472 ElementaryMatrixType edxUV = 0;
00473 generatesElementaryMatrix(PDEOperator::firstorderop,
00474 J, edxUV, fv.number());
00475
00476 TinyVector<3> massCenter;
00477 T.value(FiniteElement::massCenter(), massCenter);
00478
00479 const real_t fValue = F(massCenter);
00480
00481 const size_t cellNumber = icell.number();
00482
00483 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00484 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00485 index[l] = dofPositions(cellNumber,l);
00486 }
00487
00488 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00489 const size_t dof
00490 = __degreeOfFreedomSet(testFunctionNumber,index[l]);
00491
00492 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
00493 b[dof] += edxUV(l,m)*gValues[index[m]]*fValue;
00494 }
00495 }
00496 }
00497 break;
00498 }
00499 case VariationalLinearOperator::FdxV: {
00500 const VariationalOperatorFdxV& fv
00501 = dynamic_cast<const VariationalOperatorFdxV&>(*(*i));
00502
00503 const ScalarFunctionBase& F = fv.f();
00504 const size_t testFunctionNumber = fv.testFunctionNumber();
00505
00506 Vector<real_t> fValues (dofPositions.number());
00507
00508 for (size_t i=0; i<dofPositions.number(); ++i) {
00509 fValues[i] = F(dofPositions.vertex(i));
00510 }
00511
00512 for(typename MeshType::const_iterator icell(this->__mesh);
00513 not(icell.end()); ++icell) {
00514 const CellType& K = *icell;
00515
00516 ConformTransformation T(K);
00517 JacobianTransformation J(T);
00518
00519 ElementaryMatrixType eUdxV = 0;
00520 generatesElementaryMatrix(PDEOperator::firstorderopTransposed,
00521 J, eUdxV, fv.number());
00522
00523 const size_t cellNumber = icell.number();
00524
00525 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00526 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00527 index[l] = dofPositions(cellNumber,l);
00528 }
00529
00530 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00531 const size_t dof
00532 = this->__degreeOfFreedomSet(testFunctionNumber,index[l]);
00533
00534 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
00535 b[dof] += eUdxV(l,m)*fValues[index[m]];
00536 }
00537 }
00538 }
00539 break;
00540 }
00541 case VariationalLinearOperator::FgradGgradV: {
00542 const VariationalOperatorFgradGgradV& fv
00543 = dynamic_cast<const VariationalOperatorFgradGgradV&>(*(*i));
00544
00545 const ScalarFunctionBase& F = fv.f();
00546 const ScalarFunctionBase& G = fv.g();
00547 const size_t testFunctionNumber = fv.testFunctionNumber();
00548
00549 Vector<real_t> gValues (dofPositions.number());
00550
00551 for (size_t i=0; i<dofPositions.number(); ++i) {
00552 gValues[i] = G(dofPositions.vertex(i));
00553 }
00554
00555 for(typename MeshType::const_iterator icell(this->__mesh);
00556 not(icell.end()); ++icell) {
00557 const CellType& K = *icell;
00558
00559 ConformTransformation T(K);
00560 JacobianTransformation J(T);
00561
00562 ElementaryMatrixType e = 0;
00563 generatesElementaryMatrix(PDEOperator::divmugrad,
00564 J, e);
00565
00566 TinyVector<3> massCenter;
00567 T.value(FiniteElement::massCenter(), massCenter);
00568
00569 const real_t fValue = F(massCenter);
00570
00571 const size_t cellNumber = icell.number();
00572
00573 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00574 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00575 index[l] = dofPositions(cellNumber,l);
00576 }
00577
00578 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00579 const size_t dof
00580 = __degreeOfFreedomSet(testFunctionNumber,index[l]);
00581
00582 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
00583 b[dof] += e(l,m)*gValues[index[m]]*fValue;
00584 }
00585 }
00586 }
00587 break;
00588 }
00589 default: {
00590 throw ErrorHandler(__FILE__,__LINE__,
00591 "unknown variational operator",
00592 ErrorHandler::unexpected);
00593 }
00594 }
00595 }
00596 break;
00597 }
00598 default: {
00599 throw ErrorHandler(__FILE__,__LINE__,
00600 "unknown problem type",
00601 ErrorHandler::unexpected);
00602 }
00603 }
00604 ffout(2) << "- assembling second member: done";
00605 t.stop();
00606 ffout(3) << " [cost: " << t << ']';
00607 ffout(2) << '\n';
00608 }
00609
00610 public:
00611
00623 FEMDiscretization(const Problem& p,
00624 const MeshType& m,
00625 const DiscretizationType& discretizationType,
00626 BaseMatrix& a,
00627 BaseVector& bb,
00628 const DegreeOfFreedomSet& dof)
00629 : BaseFEMDiscretization<MeshType,
00630 TypeOfDiscretization>(p, m, discretizationType, a, bb, dof)
00631 {
00632 SolverInformationCenter::instance().pushMesh(&m);
00633 SolverInformationCenter::instance().pushDiscretizationType(&(this->__discretizationType));
00634 }
00635
00640 ~FEMDiscretization()
00641 {
00642 SolverInformationCenter::instance().pop();
00643 }
00644 };
00645
00646
00652 template <>
00653 template <ScalarDiscretizationTypeBase::Type TypeOfDiscretization>
00654 class FEMDiscretization<Structured3DMesh,TypeOfDiscretization>
00655 : public BaseFEMDiscretization<Structured3DMesh,
00656 TypeOfDiscretization>
00657 {
00658 public:
00660 typedef Structured3DMesh MeshType;
00661
00663 typedef MeshType::CellType CellType;
00664
00666 typedef typename FiniteElementTraits<CellType,
00667 TypeOfDiscretization>::Type FiniteElement;
00668
00670 typedef typename FiniteElement::QuadratureType QuadratureType;
00671
00673 typedef typename FiniteElement::ElementaryMatrix ElementaryMatrixType;
00674
00676 typedef typename FiniteElement::ElementaryVector ElementaryVectorType;
00677
00679 typedef typename FiniteElementTraits<CellType,
00680 TypeOfDiscretization>::Transformation ConformTransformation;
00681
00683 typedef typename FiniteElementTraits<CellType,
00684 TypeOfDiscretization>::JacobianTransformation JacobianTransformation;
00685
00686 public:
00692 void assembleMatrix()
00693 {
00694 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00695 = this->__degreeOfFreedomSet.positionsSet(0);
00696
00697 switch (this->__A.type()) {
00698 case BaseMatrix::doubleHashedMatrix: {
00699 Timer t;
00700 t.start();
00701
00702 ffout(2) << "- assembling matrix\n";
00703
00704 DoubleHashedMatrix& A = dynamic_cast<DoubleHashedMatrix&>(this->__A);
00705
00706 MeshType::const_iterator icell0(this->__mesh);
00707 ConformTransformation T0(*icell0);
00708 JacobianTransformation J(T0);
00709 generatesElementaryMatrix(this->__eSet,J);
00710
00711 for(MeshType::const_iterator icell(this->__mesh);
00712 not(icell.end()); ++icell) {
00713 const CellType& K = *icell;
00714 ConformTransformation T(K);
00715 TinyVector<3> massCenter;
00716 T.value(FiniteElement::massCenter(), massCenter);
00717
00718 TinyVector<FiniteElement::numberOfDegreesOfFreedom,
00719 size_t> index;
00720 const size_t cellNumber = icell.number();
00721
00722 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00723 index[l] = dofPositions(cellNumber,l);
00724 }
00725 for(typename DiscretizedOperators<ElementaryMatrixType>
00726 ::iterator iOperator = this->__discretizedOperators.begin();
00727 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00728
00729 const real_t coef = ((*iOperator).second)(massCenter);
00730
00731 const ElementaryMatrixType& elementaryMatrix
00732 = (*(*iOperator).first);
00733
00734 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00735 const size_t I1
00736 = this->__degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00737 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00738 const size_t I2
00739 = this->__degreeOfFreedomSet(((*iOperator).second).j(), index[m]);
00740
00741 A(I1,I2) += coef*elementaryMatrix(l,m);
00742 }
00743 }
00744 }
00745 }
00746 ffout(2) << "- assembling matrix: done";
00747 t.stop();
00748 ffout(3) << " [cost: " << t << ']';
00749 ffout(2) << '\n';
00750
00751 break;
00752 }
00753 case BaseMatrix::unAssembled: {
00754 UnAssembledMatrix& A = dynamic_cast<UnAssembledMatrix&>(this->__A);
00755 A.setDiscretization(this);
00756 break;
00757 }
00758
00759 default: {
00760 throw ErrorHandler(__FILE__,__LINE__,
00761 "unexpected matrix type",
00762 ErrorHandler::unexpected);
00763 }
00764 }
00765 }
00766
00773 void timesX(const BaseVector& X, BaseVector& Z) const
00774 {
00775 const Vector<real_t>& x = dynamic_cast<const Vector<real_t>&>(X);
00776
00777 Vector<real_t>& z = dynamic_cast<Vector<real_t>&>(Z);
00778 z=0;
00779
00780 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00781 = this->__degreeOfFreedomSet.positionsSet(0);
00782
00783 MeshType::const_iterator icell(this->__mesh);
00784 ConformTransformation T0(*icell);
00785 JacobianTransformation J(T0);
00786 generatesElementaryMatrix(this->__eSet,J);
00787
00788 for(MeshType::const_iterator icell(this->__mesh);
00789 not(icell.end()); ++icell) {
00790 const CellType& K = *icell;
00791 ConformTransformation T(K);
00792
00793 const size_t cellNumber = icell.number();
00794
00795 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00796 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00797 index[l] = dofPositions(cellNumber,l);
00798 }
00799
00800 TinyVector<3> massCenter;
00801 T.value(FiniteElement::massCenter(), massCenter);
00802
00803 for(typename DiscretizedOperators<ElementaryMatrixType>
00804 ::iterator iOperator = this->__discretizedOperators.begin();
00805 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00806 const real_t coef = ((*iOperator).second)(massCenter);
00807
00808 const ElementaryMatrixType& elementaryMatrix = (*(*iOperator).first);
00809
00810 #warning can optimize this loops by precomputing (i and) j
00811 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00812
00813 const size_t I1 = this->__degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00814 if (not((*this->__dirichletList)[I1])) {
00815 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00816
00817 const size_t I2 = this->__degreeOfFreedomSet(((*iOperator).second).j(), index[m]);
00818 if (not((*this->__dirichletList)[I2])) {
00819 z[I1] += coef*elementaryMatrix(l,m)*x[I2];
00820 }
00821 }
00822 }
00823 }
00824 }
00825 }
00826 }
00827
00834 void transposedTimesX(const BaseVector& X, BaseVector& Z) const
00835 {
00836 const Vector<real_t>& x = dynamic_cast<const Vector<real_t>&>(X);
00837
00838 Vector<real_t>& z = dynamic_cast<Vector<real_t>&>(Z);
00839 z=0;
00840
00841 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00842 = this->__degreeOfFreedomSet.positionsSet(0);
00843
00844 MeshType::const_iterator icell(this->__mesh);
00845 ConformTransformation T0(*icell);
00846 JacobianTransformation J(T0);
00847 generatesElementaryMatrix(this->__eSet,J);
00848
00849 for(MeshType::const_iterator icell(this->__mesh);
00850 not(icell.end()); ++icell) {
00851 const CellType& K = *icell;
00852 ConformTransformation T(K);
00853
00854 const size_t cellNumber = icell.number();
00855
00856 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00857 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00858 index[l] = dofPositions(cellNumber,l);
00859 }
00860
00861 TinyVector<3> massCenter;
00862 T.value(FiniteElement::massCenter(), massCenter);
00863
00864 for(typename DiscretizedOperators<ElementaryMatrixType>
00865 ::iterator iOperator = this->__discretizedOperators.begin();
00866 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00867 const real_t coef = ((*iOperator).second)(massCenter);
00868
00869 const ElementaryMatrixType& elementaryMatrix = (*(*iOperator).first);
00870
00871 #warning can optimize this loops by precomputing (i and) j
00872 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00873
00874 const size_t I1 = this->__degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00875 if (not((*this->__dirichletList)[I1])) {
00876 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; m++) {
00877
00878 const size_t I2 = this->__degreeOfFreedomSet(((*iOperator).second).j(), index[m]);
00879 if (not((*this->__dirichletList)[I2])) {
00880 z[I2] += coef*elementaryMatrix(l,m)*x[I1];
00881 }
00882 }
00883 }
00884 }
00885 }
00886 }
00887 }
00888
00894 void getDiagonal(BaseVector& Z) const
00895 {
00896 Vector<real_t>& z = dynamic_cast<Vector<real_t>&>(Z);
00897
00898 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00899 = this->__degreeOfFreedomSet.positionsSet(0);
00900
00901 MeshType::const_iterator icell0(this->__mesh);
00902 ConformTransformation T0(*icell0);
00903 JacobianTransformation J(T0);
00904 generatesElementaryMatrix(this->__eSet,J);
00905
00906 for(MeshType::const_iterator icell(this->__mesh);
00907 not(icell.end()); ++icell) {
00908 const CellType& K = *icell;
00909 ConformTransformation T(K);
00910
00911 const size_t cellNumber = icell.number();
00912
00913 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00914 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00915 index[l] = dofPositions(cellNumber,l);
00916 }
00917
00918 TinyVector<3> massCenter;
00919 T.value(FiniteElement::massCenter(), massCenter);
00920
00921 for(typename DiscretizedOperators<ElementaryMatrixType>
00922 ::iterator iOperator = this->__discretizedOperators.begin();
00923 iOperator != this->__discretizedOperators.end(); ++iOperator) {
00924
00925 if (((*iOperator).second).i() == ((*iOperator).second).j()) {
00926 const real_t coef = ((*iOperator).second)(massCenter);
00927
00928 const ElementaryMatrixType& elementaryMatrix = (*(*iOperator).first);
00929 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; l++) {
00930 const size_t I =
00931 this->__degreeOfFreedomSet(((*iOperator).second).i(), index[l]);
00932 z[I] += coef*elementaryMatrix(l,l);
00933 }
00934 }
00935 }
00936 }
00937 }
00938
00943 void assembleSecondMember()
00944 {
00945 Timer t;
00946 t.start();
00947
00948 ffout(2) << "- assembling second member\n";
00949
00950 const ScalarDegreeOfFreedomPositionsSet& dofPositions
00951 = this->__degreeOfFreedomSet.positionsSet(0);
00952
00954 ElementaryVectorType eVect;
00955 Vector<real_t>& b = (static_cast<Vector<real_t>&>(this->__b));
00956 b = 0;
00957
00958 const QuadratureType& referenceQuadrature = QuadratureType::instance();
00959
00960 switch (this->problem().type()) {
00961 case Problem::pde: {
00962 const PDESystem& pdeSystem
00963 = static_cast<const PDESystem&>(this->problem());
00964
00965 for(MeshType::const_iterator icell(this->__mesh);
00966 not(icell.end()); ++icell) {
00967 const CellType& K = *icell;
00968 eVect = 0;
00969 ConformTransformation T(K);
00970 JacobianTransformation J(T);
00971 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
00972 TinyVector<QuadratureType::numberOfQuadraturePoints,
00973 TinyVector<3> > quadrature;
00974
00975 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
00976 T.value(referenceQuadrature[l], quadrature[l]);
00977 }
00978
00979 const size_t cellNumber = icell.number();
00980 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00981 index[l] = this->__degreeOfFreedomSet.positionsSet(0)(cellNumber,l);
00982 }
00983
00984 for (size_t i=0; i<pdeSystem.numberOfUnknown(); ++i) {
00985 const ScalarFunctionBase& F = pdeSystem.secondMember(i);
00986
00987 TinyVector<QuadratureType::numberOfQuadraturePoints> f;
00988
00989 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
00990 f[l] = F(quadrature[l]);
00991 }
00992
00993 generatesElementaryVector(eVect,J,f);
00994
00995 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
00996 const size_t dof = this->__degreeOfFreedomSet(i,index[l]);
00997 b[dof] += eVect[l]*J.jacobianDet();
00998 }
00999 }
01000 }
01001 break;
01002 }
01003 case Problem::variational: {
01004 const VariationalProblem& variationalProblem
01005 = dynamic_cast<const VariationalProblem&>(this->problem());
01006
01007 if (variationalProblem.hasJumpOrMean()) {
01008 throw ErrorHandler(__FILE__,__LINE__,
01009 "cannot discretize problems with jumps or means in FEM !",
01010 ErrorHandler::normal);
01011 }
01012
01013 for (VariationalProblem::linearOperatorConst_iterator i
01014 = variationalProblem.beginLinearOperator();
01015 i != variationalProblem.endLinearOperator(); ++i) {
01016 switch ((*(*i)).type()) {
01017 case VariationalLinearOperator::FV: {
01018 const VariationalOperatorFV& fv
01019 = dynamic_cast<const VariationalOperatorFV&>(*(*i));
01020
01021 const ScalarFunctionBase& F = fv.f();
01022 const size_t testFunctionNumber = fv.testFunctionNumber();
01023
01024 for(MeshType::const_iterator icell(this->__mesh);
01025 not(icell.end()); ++icell) {
01026 const CellType& K = *icell;
01027 eVect = 0;
01028 ConformTransformation T(K);
01029 JacobianTransformation J(T);
01030
01031
01032 TinyVector<QuadratureType::numberOfQuadraturePoints,
01033 TinyVector<3, real_t> > quadrature;
01034 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
01035 T.value(referenceQuadrature[l], quadrature[l]);
01036 }
01037
01038 const size_t cellNumber = icell.number();
01039
01040 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
01041 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01042 index[l] = dofPositions(cellNumber,l);
01043 }
01044
01045 ElementaryVectorType f;
01046
01047 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
01048 f[l] = F(quadrature[l]);
01049 }
01050
01051 generatesElementaryVector(eVect,J,f);
01052
01053 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01054 const size_t dof = this->__degreeOfFreedomSet(testFunctionNumber,index[l]);
01055 b[dof] += eVect[l]*J.jacobianDet();
01056 }
01057 }
01058 break;
01059 }
01060 case VariationalLinearOperator::FdxGV: {
01061 const VariationalOperatorFdxGV& fv
01062 = dynamic_cast<const VariationalOperatorFdxGV&>(*(*i));
01063
01064 const ScalarFunctionBase& F = fv.f();
01065 const ScalarFunctionBase& G = fv.g();
01066 const size_t testFunctionNumber = fv.testFunctionNumber();
01067
01068 Vector<real_t> gValues (dofPositions.number());
01069
01070 for (size_t i=0; i<dofPositions.number(); ++i) {
01071 gValues[i] = G(dofPositions.vertex(i));
01072 }
01073
01074 MeshType::const_iterator icell0(this->__mesh);
01075 ConformTransformation T0(*icell0);
01076 JacobianTransformation J(T0);
01077
01078 ElementaryMatrixType edxUV = 0;
01079 generatesElementaryMatrix(PDEOperator::firstorderop,
01080 J, edxUV, fv.number());
01081
01082 for(MeshType::const_iterator icell(this->__mesh);
01083 not(icell.end()); ++icell) {
01084 const CellType& K = *icell;
01085
01086 ConformTransformation T(K);
01087
01088 TinyVector<3> massCenter;
01089 T.value(FiniteElement::massCenter(), massCenter);
01090 const real_t fValue = F(massCenter);
01091
01092 const size_t cellNumber = icell.number();
01093
01094 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
01095 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01096 index[l] = dofPositions(cellNumber,l);
01097 }
01098
01099 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01100 const size_t dof
01101 = this->__degreeOfFreedomSet(testFunctionNumber,index[l]);
01102
01103 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
01104 b[dof] += edxUV(l,m)*gValues[index[m]]*fValue;
01105 }
01106 }
01107 }
01108 break;
01109 }
01110 case VariationalLinearOperator::FdxV: {
01111 const VariationalOperatorFdxV& fv
01112 = dynamic_cast<const VariationalOperatorFdxV&>(*(*i));
01113
01114 const ScalarFunctionBase& F = fv.f();
01115 const size_t testFunctionNumber = fv.testFunctionNumber();
01116
01117 Vector<real_t> fValues (dofPositions.number());
01118
01119 for (size_t i=0; i<dofPositions.number(); ++i) {
01120 fValues[i] = F(dofPositions.vertex(i));
01121 }
01122
01123 MeshType::const_iterator icell0(this->__mesh);
01124 ConformTransformation T0(*icell0);
01125 JacobianTransformation J(T0);
01126
01127 ElementaryMatrixType eUdxV = 0;
01128 generatesElementaryMatrix(PDEOperator::firstorderopTransposed,
01129 J, eUdxV, fv.number());
01130
01131 for(MeshType::const_iterator icell(this->__mesh);
01132 not(icell.end()); ++icell) {
01133 const CellType& K = *icell;
01134
01135 ConformTransformation T(K);
01136
01137 const size_t cellNumber = icell.number();
01138
01139 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
01140 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01141 index[l] = dofPositions(cellNumber,l);
01142 }
01143
01144 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01145 const size_t dof
01146 = this->__degreeOfFreedomSet(testFunctionNumber,index[l]);
01147
01148 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
01149 b[dof] += eUdxV(l,m)*fValues[index[m]];
01150 }
01151 }
01152 }
01153 break;
01154 }
01155 case VariationalLinearOperator::FgradGgradV: {
01156 const VariationalOperatorFgradGgradV& fv
01157 = dynamic_cast<const VariationalOperatorFgradGgradV&>(*(*i));
01158
01159 const ScalarFunctionBase& F = fv.f();
01160 const ScalarFunctionBase& G = fv.g();
01161
01162 const size_t testFunctionNumber = fv.testFunctionNumber();
01163
01164 if (G.type() == ScalarFunctionBase::femfunction) {
01165 const FEMFunctionBase& gFEM = dynamic_cast<const FEMFunctionBase&>(G);
01166 if (gFEM.baseMesh() != & this->__mesh) {
01167 if (gFEM.baseMesh()->type() == Mesh::cartesianHexahedraMesh) {
01168 const MeshType& quadratureMesh
01169 = dynamic_cast<const MeshType&>(*gFEM.baseMesh());
01170 for (MeshType::const_iterator iQuadratureCell(quadratureMesh);
01171 not(iQuadratureCell.end()); ++iQuadratureCell) {
01172 const CellType& KQuadrature = *iQuadratureCell;
01173 ConformTransformation TQuadrature(KQuadrature);
01174
01175 for (size_t l=0; l<QuadratureType::numberOfQuadraturePoints; ++l) {
01176 TinyVector<3, real_t> quadrature;
01177 TQuadrature.value(referenceQuadrature[l], quadrature);
01178
01179 MeshType::const_iterator icell = this->__mesh.find(quadrature);
01180 if (icell.end()) continue;
01181
01182 const CellType& K = *icell;
01183 if (not K.isFictitious()) {
01184 const TinyVector<3,real_t> gradGValue = gFEM.gradient(quadrature);
01185 const real_t fValue = F(quadrature);
01186
01187 ConformTransformation T(K);
01188 JacobianTransformation J(T);
01189
01190 TinyVector<3,real_t> Xhat;
01191 T.invertT(quadrature,Xhat);
01192
01193 const size_t cellNumber = icell.number();
01194
01195 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
01196 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
01197 index[m] = dofPositions(cellNumber,m);
01198 }
01199
01200 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
01201 TinyVector<3,real_t> gradV;
01202
01203 gradV[0] = FiniteElement::instance().dxW(m,Xhat)
01204 * J.invJacobian(0,0);
01205 gradV[1] = FiniteElement::instance().dyW(m,Xhat)
01206 * J.invJacobian(1,1);
01207 gradV[2] = FiniteElement::instance().dzW(m,Xhat)
01208 * J.invJacobian(2,2);
01209
01210 const size_t dof
01211 = this->__degreeOfFreedomSet(testFunctionNumber,index[m]);
01212
01213 b[dof] += KQuadrature.volume()*QuadratureType::instance().weight(l)*fValue*(gradGValue*gradV);
01214 }
01215 }
01216 }
01217 }
01218 break;
01219 }
01220 }
01221 }
01222
01223 Vector<real_t> gValues (dofPositions.number());
01224
01225 for (size_t i=0; i<dofPositions.number(); ++i) {
01226 gValues[i] = G(dofPositions.vertex(i));
01227 }
01228
01229 MeshType::const_iterator icell0(this->__mesh);
01230 ConformTransformation T0(*icell0);
01231 JacobianTransformation J(T0);
01232
01233 ElementaryMatrixType e = 0;
01234 generatesElementaryMatrix(PDEOperator::divmugrad,
01235 J, e);
01236
01237 for(MeshType::const_iterator icell(this->__mesh);
01238 not(icell.end()); ++icell) {
01239 const CellType& K = *icell;
01240 ConformTransformation T(K);
01241
01242 TinyVector<3> massCenter;
01243 T.value(FiniteElement::massCenter(), massCenter);
01244
01245 const real_t fValue = F(massCenter);
01246
01247 const size_t cellNumber = icell.number();
01248
01249 TinyVector<FiniteElement::numberOfDegreesOfFreedom,int> index;
01250 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01251 index[l] = dofPositions(cellNumber,l);
01252 }
01253
01254 for (size_t l=0; l<FiniteElement::numberOfDegreesOfFreedom; ++l) {
01255 const size_t dof
01256 = __degreeOfFreedomSet(testFunctionNumber,index[l]);
01257
01258 for (size_t m=0; m<FiniteElement::numberOfDegreesOfFreedom; ++m) {
01259 b[dof] += e(l,m)*gValues[index[m]]*fValue;
01260 }
01261 }
01262 }
01263 break;
01264 }
01265 default: {
01266 throw ErrorHandler(__FILE__,__LINE__,
01267 "unknown variational operator type",
01268 ErrorHandler::unexpected);
01269 }
01270 }
01271 }
01272 break;
01273 }
01274 default: {
01275 throw ErrorHandler(__FILE__,__LINE__,
01276 "unknown problem type",
01277 ErrorHandler::unexpected);
01278 }
01279 }
01280 ffout(2) << "- assembling second member: done";
01281 t.stop();
01282 ffout(3) << " [cost: " << t << ']';
01283 ffout(2) << '\n';
01284 }
01285
01286 public:
01298 FEMDiscretization(const Problem& p,
01299 const Structured3DMesh& m,
01300 const DiscretizationType& discretisationType,
01301 BaseMatrix& a,
01302 BaseVector& bb,
01303 const DegreeOfFreedomSet& dof)
01304 : BaseFEMDiscretization<Structured3DMesh,
01305 TypeOfDiscretization>(p, m, discretisationType, a, bb, dof)
01306 {
01307 SolverInformationCenter::instance().pushMesh(&m);
01308 SolverInformationCenter::instance().pushDiscretizationType(&(this->__discretizationType));
01309 }
01310
01315 ~FEMDiscretization()
01316 {
01317 SolverInformationCenter::instance().pop();
01318 }
01319 };
01320
01321
01322 #endif // FEM_DISCRETIZATION_HPP