00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <FiniteElementMethod.hpp>
00021
00022 #include <PDESolution.hpp>
00023
00024 #include <PDEProblem.hpp>
00025
00026 #include <Structured3DMesh.hpp>
00027 #include <MeshOfHexahedra.hpp>
00028 #include <MeshOfTetrahedra.hpp>
00029
00030 #include <SpectralMesh.hpp>
00031
00032 #include <FEMDiscretization.hpp>
00033
00034 #include <BoundaryConditionDiscretizationFEM.hpp>
00035
00036 #include <map>
00037 #include <list>
00038
00039 #include <KrylovSolver.hpp>
00040
00041 #include <MatrixManagement.hpp>
00042
00043 #include <SparseMatrix.hpp>
00044 #include <PETScMatrix.hpp>
00045
00046 #include <Timer.hpp>
00047
00048 #include <ErrorHandler.hpp>
00049
00050 template <typename MeshType,
00051 ScalarDiscretizationTypeBase::Type TypeOfDiscretization>
00052 void FiniteElementMethod::__discretizeOnMesh()
00053 {
00054 MemoryManager MM;
00055
00056 bool performAssembling =MM.ReserveMatrix(__A,
00057 problem().numberOfUnknown(),
00058 __degreeOfFreedomSet.size());
00059
00060 MM.ReserveVector(__b,
00061 problem().numberOfUnknown(),
00062 __degreeOfFreedomSet.size());
00063
00064 ffout(2) << "Finite element method: disretization...\n";
00065
00066 ReferenceCounting<FEMDiscretization<MeshType,
00067 TypeOfDiscretization> > FEM
00068 = new FEMDiscretization<MeshType,
00069 TypeOfDiscretization>(problem(),
00070 dynamic_cast<const MeshType&>(mesh()),
00071 __discretizationType,
00072 *__A,*__b, __degreeOfFreedomSet);
00073
00074 if (performAssembling) {
00075 FEM->assembleMatrix();
00076 } else {
00077 ffout(2) << "- keeping previous operator discretization\n";
00078 }
00079
00080 FEM->assembleSecondMember();
00081
00082
00083 ffout(2) << "- discretizing boundary conditions\n";
00084
00085 BoundaryConditionDiscretizationFEM<MeshType,
00086 TypeOfDiscretization>* bcd
00087 = new BoundaryConditionDiscretizationFEM<MeshType,
00088 TypeOfDiscretization>(problem(),
00089 dynamic_cast<const MeshType&>(mesh()),
00090 __degreeOfFreedomSet);
00091 bcd->associatesMeshesToBoundaryConditions();
00092 ReferenceCounting<BoundaryConditionDiscretization> bcDiscretization = bcd;
00093
00094
00095 FEM->setDirichletList(bcDiscretization->getDirichletList());
00096
00097 ffout(2) << "- second member modification\n";
00098 bcDiscretization->setSecondMember(__A,__b);
00099
00100 ffout(2) << "- matrix modification\n";
00101 bcDiscretization->setMatrix(__A,__b);
00102
00103 ffout(2) << "Finite element method: disretization done\n";
00104
00105 if (__A->type() == BaseMatrix::doubleHashedMatrix) {
00106 Timer t;
00107 t.start();
00108
00109 #warning temporary implementation
00110 #ifdef HAVE_PETSC
00111 PETScMatrix* aa
00112 = new PETScMatrix(static_cast<DoubleHashedMatrix&>(*__A));
00113 __A = aa;
00114 #else // HAVE_PETSC
00115 SparseMatrix* aa
00116 = new SparseMatrix(static_cast<DoubleHashedMatrix&>(*__A));
00117
00118 __A = aa;
00119 #endif // HAVE_PETSC
00120
00121 t.stop();
00122 ffout(2) << "Matrix copy: " << t << '\n';
00123 }
00124 }
00125
00126 template <ScalarDiscretizationTypeBase::Type TypeOfDiscretization>
00127 void FiniteElementMethod::__discretize()
00128 {
00129 switch (mesh().type()) {
00130 case Mesh::cartesianHexahedraMesh: {
00131 this->__discretizeOnMesh<Structured3DMesh, TypeOfDiscretization>();
00132 break;
00133 }
00134 case Mesh::hexahedraMesh: {
00135 this->__discretizeOnMesh<MeshOfHexahedra, TypeOfDiscretization>();
00136 break;
00137 }
00138 case Mesh::tetrahedraMesh: {
00139 this->__discretizeOnMesh<MeshOfTetrahedra, TypeOfDiscretization>();
00140 break;
00141 }
00142 case Mesh::spectralMesh: {
00143 this->__discretizeOnMesh<SpectralMesh, TypeOfDiscretization>();
00144 break;
00145 }
00146 default: {
00147 throw ErrorHandler(__FILE__, __LINE__,
00148 "Cannot use '"+mesh().typeName()+"' for finite element computations",
00149 ErrorHandler::normal);
00150 }
00151 }
00152 }
00153
00154 void FiniteElementMethod::Discretize (ConstReferenceCounting<Problem> Pb)
00155 {
00156 __problem = Pb;
00157
00158 switch(__discretizationType[0].type()) {
00159 case ScalarDiscretizationTypeBase::lagrangianFEM0: {
00160 this->__discretize<ScalarDiscretizationTypeBase::lagrangianFEM0>();
00161 return;
00162 }
00163 case ScalarDiscretizationTypeBase::lagrangianFEM1: {
00164 this->__discretize<ScalarDiscretizationTypeBase::lagrangianFEM1>();
00165 return;
00166 }
00167 case ScalarDiscretizationTypeBase::lagrangianFEM2: {
00168 this->__discretize<ScalarDiscretizationTypeBase::lagrangianFEM2>();
00169 return;
00170 }
00171 default: {
00172 throw ErrorHandler(__FILE__,__LINE__,
00173 "Discretization type not implemented",
00174 ErrorHandler::normal);
00175 }
00176 }
00177 }
00178
00179 void FiniteElementMethod::Compute(Solution& U)
00180 {
00181 PDESolution& u = static_cast<PDESolution&>(U);
00182 KrylovSolver K(*__A, *__b, __degreeOfFreedomSet);
00183 K.solve(problem(), u.values());
00184 }
00185
00186 FiniteElementMethod::
00187 FiniteElementMethod(const DiscretizationType& discretizationType,
00188 ConstReferenceCounting<Mesh> mesh,
00189 const DegreeOfFreedomSet& dOfFreedom)
00190 : Method(discretizationType),
00191 __mesh(mesh),
00192 __degreeOfFreedomSet(dOfFreedom)
00193 {
00194 SolverInformationCenter::instance().pushMesh(mesh);
00195 SolverInformationCenter::instance().pushDiscretizationType(&discretizationType);
00196 }
00197
00198 FiniteElementMethod::
00199 ~FiniteElementMethod()
00200 {
00201 SolverInformationCenter::instance().pop();
00202 }