00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SPECTRAL_LEGENDRE_DISCRETIZATION_NON_CONFORM_HPP
00021 #define SPECTRAL_LEGENDRE_DISCRETIZATION_NON_CONFORM_HPP
00022
00023 #include <Problem.hpp>
00024
00025 #include <DegreeOfFreedomSet.hpp>
00026 #include <OctreeMesh.hpp>
00027
00028 #include <DoubleHashedMatrix.hpp>
00029 #include <UnAssembledMatrix.hpp>
00030
00031 #include <Discretization.hpp>
00032 #include <ScalarDiscretizationTypeSpectral.hpp>
00033
00034 #include <Mesh.hpp>
00035
00036 #include <SpectralLegendreDiscretizer.hpp>
00037
00038 #include <ErrorHandler.hpp>
00039 #include <Timer.hpp>
00040
00041 class SpectralLegendreDiscretizationNonConform
00042 : public Discretization
00043 {
00044 private:
00045
00046 const DegreeOfFreedomSet& __degreeOfFreedomSet;
00047
00048 const OctreeMesh& __mesh;
00049 const DiscretizationType& __discretizationType;
00050 const TinyVector<3,size_t> __quadratureDegree;
00051
00052 static TinyVector<3,size_t>
00053 _getQuadratureDegree(const DiscretizationType& discretizationType)
00054 {
00055 #ifndef NDEBUG
00056 for (size_t i=0; i<discretizationType.number(); ++i) {
00057 ASSERT(discretizationType[i].type() == ScalarDiscretizationTypeBase::spectralLegendre);
00058 }
00059 #endif // NDEBUG
00060
00061 TinyVector<3,size_t> quadratureDegree
00062 = dynamic_cast <const ScalarDiscretizationTypeSpectral&> (discretizationType[0]).degrees();
00063
00064 for (size_t i=1; i<discretizationType.number(); ++i) {
00065 TinyVector<3,size_t> degree
00066 = dynamic_cast <const ScalarDiscretizationTypeSpectral&>(discretizationType[i]).degrees();
00067 for (size_t j=0; j<3; ++j) {
00068 quadratureDegree[j] = std::max(quadratureDegree[j], degree[j]);
00069 }
00070 }
00071
00072 return quadratureDegree;
00073 }
00074
00075 ReferenceCounting<SpectralLegendreDiscretizer>
00076 _getLocalDiscretizer(const CartesianHexahedron& h) const
00077 {
00078 const TinyVector<3,real_t>& a = h(0);
00079 const TinyVector<3,real_t>& b = h(6);
00080
00081 Structured3DMeshShape s3dM(__quadratureDegree,a,b);
00082 ReferenceCounting<VerticesCorrespondance> correspondance
00083 = new VerticesCorrespondance((__quadratureDegree[0]+1)*
00084 (__quadratureDegree[1]+1)*
00085 (__quadratureDegree[2]+1));
00086
00087 SpectralMesh quadratureMesh(s3dM,correspondance);
00088
00089 return new SpectralLegendreDiscretizer(this->problem(),
00090 quadratureMesh,
00091 __A,
00092 __b,
00093 __degreeOfFreedomSet,
00094 __discretizationType);
00095 }
00096
00097 public:
00103 void assembleMatrix()
00104 {
00105 switch ((this->__A).type()) {
00106 case BaseMatrix::doubleHashedMatrix: {
00107 throw ErrorHandler(__FILE__,__LINE__,
00108 "Spectral Method cannot be used with assembled matrices",
00109 ErrorHandler::unexpected);
00110 }
00111 case BaseMatrix::unAssembled: {
00112 UnAssembledMatrix& A = dynamic_cast<UnAssembledMatrix&>(this->__A);
00113 A.setDiscretization(this);
00114 break;
00115 }
00116 default: {
00117 throw ErrorHandler(__FILE__,__LINE__,
00118 "unexpected matrix type",
00119 ErrorHandler::unexpected);
00120 }
00121 }
00122 }
00123
00130 void timesX(const BaseVector& u, BaseVector& v) const
00131 {
00132 dynamic_cast<Vector<real_t>&>(v)=0;
00133 for (OctreeMesh::const_iterator icell(__mesh);
00134 not icell.end(); ++icell) {
00135 const CartesianHexahedron& h = *icell;
00136
00137 this->_getLocalDiscretizer(h)->timesX(u,v);
00138 }
00139 }
00140
00147 void transposedTimesX(const BaseVector& u, BaseVector& v) const
00148 {
00149 dynamic_cast<Vector<real_t>&>(v) = 0;
00150 for (OctreeMesh::const_iterator icell(__mesh);
00151 not icell.end(); ++icell) {
00152 const CartesianHexahedron& h = *icell;
00153
00154 this->_getLocalDiscretizer(h)->transposedTimesX(u,v);
00155 }
00156 }
00157
00163 void getDiagonal(BaseVector& z) const
00164 {
00165 dynamic_cast<Vector<real_t>&>(z)=0;
00166 for (OctreeMesh::const_iterator icell(__mesh);
00167 not icell.end(); ++icell) {
00168 const CartesianHexahedron& h = *icell;
00169
00170 this->_getLocalDiscretizer(h)->getDiagonal(z);
00171 }
00172 }
00173
00178 void assembleSecondMember()
00179 {
00180 Timer t;
00181 t.start();
00182
00183 ffout(2) << "- assembling second member\n";
00184
00186 Vector<real_t>& b = (static_cast<Vector<real_t>&>(this->__b));
00187 b = 0;
00188
00189 for (OctreeMesh::const_iterator icell(__mesh);
00190 not icell.end(); ++icell) {
00191 const CartesianHexahedron& h = *icell;
00192
00193 this->_getLocalDiscretizer(h)->assembleSecondMember();
00194 }
00195
00196 ffout(2) << "- assembling second member: done";
00197 t.stop();
00198 ffout(3) << " [cost: " << t << ']';
00199 ffout(2) << '\n';
00200 }
00201
00202 public:
00203
00214 SpectralLegendreDiscretizationNonConform(const Problem& p,
00215 const OctreeMesh& m,
00216 BaseMatrix& a,
00217 BaseVector& bb,
00218 const DegreeOfFreedomSet& dof,
00219 const DiscretizationType& discretizationType)
00220 : Discretization(discretizationType,
00221 p, a, bb),
00222 __degreeOfFreedomSet(dof),
00223 __mesh(m),
00224 __discretizationType(discretizationType),
00225 __quadratureDegree(SpectralLegendreDiscretizationNonConform::_getQuadratureDegree(discretizationType))
00226 {
00227 ;
00228 }
00229
00234 ~SpectralLegendreDiscretizationNonConform()
00235 {
00236 ;
00237 }
00238 };
00239
00240
00241 #endif // SPECTRAL_LEGENDRE_DISCRETIZATION_NON_CONFORM_HPP