1 #include "LinearElasticityModel.hxx"
2 #include "SparseMatrixPetsc.hxx"
11 LinearElasticityModel::LinearElasticityModel(int dim, bool FECalculation, double rho, double lambda, double mu,MPI_Comm comm){
12 /* Initialisation of PETSC */
13 //check if PETSC is already initialised
14 PetscBool petscInitialized;
15 PetscInitialized(&petscInitialized);
17 {//check if MPI is already initialised
19 MPI_Initialized(&mpiInitialized);
21 PETSC_COMM_WORLD = comm;
22 PetscInitialize(NULL,NULL,0,0);//Note this is ok if MPI has been been initialised independently from PETSC
24 MPI_Comm_rank(PETSC_COMM_WORLD,&_rank);
25 MPI_Comm_size(PETSC_COMM_WORLD,&_size);
26 PetscPrintf(PETSC_COMM_WORLD,"Simulation on %d processors\n",_size);//Prints to standard out, only from the first processor in the communicator. Calls from other processes are ignored.
27 PetscSynchronizedPrintf(PETSC_COMM_WORLD,"Processor [%d] ready for action\n",_rank);//Prints synchronized output from several processors. Output of the first processor is followed by that of the second, etc.
28 PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);
32 std::cout<<"First Lamé coefficient="<<lambda<<endl;
33 throw CdmathException("Error : First Lamé coefficient lambda cannot be negative");
35 if(2*mu+dim*lambda < 0.)
37 std::cout<<"First Lamé coefficient="<<lambda<<", second Lamé coefficient="<<mu<<", 2*mu+dim*lambda= "<<2*mu+dim*lambda<<endl;
38 throw CdmathException("Error : 2*mu+dim*lambda cannot be negative");
42 std::cout<<"space dimension="<<dim<<endl;
43 throw CdmathException("Error : parameter dim cannot be negative");
46 _FECalculation=FECalculation;
51 _initializedMemory=false;
59 _boundaryNodeIds=std::vector< int >(0);
60 _dirichletNodeIds=std::vector< int >(0);
64 _dirichletValuesSet=false;
65 _neumannValuesSet=false;
69 _precision_Newton=_precision;
70 _MaxIterLinearSolver=0;//During several newton iterations, stores the max petssc interations
72 int _PetscIts=0;//the number of iterations of the linear solver
73 _ksptype = (char*)&KSPGMRES;
74 _pctype = (char*)&PCLU;
75 _conditionNumber=false;
78 //parameters for monitoring simulation
81 _runLogFile=new ofstream;
83 //result save parameters
84 _fileName = "LinearElasticityProblem";
85 char result[ PATH_MAX ];//extracting current directory
86 getcwd(result, PATH_MAX );
87 _path=string( result );
89 _computationCompletedSuccessfully=false;
91 //heat transfer parameters
95 _densityFieldSet=false;
98 void LinearElasticityModel::initialize()
100 _runLogFile->open((_fileName+".log").c_str(), ios::out | ios::trunc);;//for creation of a log file to save the history of the simulation
103 throw CdmathException("LinearElasticityModel::initialize() set mesh first");
106 cout<<"!!!! Initialisation of the computation of the elastic deformation of a solid using ";
107 *_runLogFile<<"!!!!! Initialisation of the computation of the elastic deformation of a solid using ";
110 cout<< "Finite volumes method"<<endl<<endl;
111 *_runLogFile<< "Finite volumes method"<<endl<<endl;
115 cout<< "Finite elements method"<<endl<<endl;
116 *_runLogFile<< "Finite elements method"<<endl<<endl;
119 /**************** Field creation *********************/
121 if(!_densityFieldSet){
123 _densityField=Field("Density",NODES,_mesh,1);
124 for(int i =0; i<_Nnodes; i++)
125 _densityField(i) = _rho;
128 _densityField=Field("Density",CELLS,_mesh,1);
129 for(int i =0; i<_Nmailles; i++)
130 _densityField(i) = _rho;
132 _densityFieldSet=true;
135 /* Détection des noeuds frontière avec une condition limite de Dirichlet */
138 if(_NboundaryNodes==_Nnodes)
139 cout<<"!!!!! Warning : all nodes are boundary nodes !!!!!"<<endl<<endl;
141 for(int i=0; i<_NboundaryNodes; i++)
143 std::map<int,double>::iterator it=_dirichletBoundaryValues.find(_boundaryNodeIds[i]);
144 if( it != _dirichletBoundaryValues.end() )
145 _dirichletNodeIds.push_back(_boundaryNodeIds[i]);
146 else if( _mesh.getNode(_boundaryNodeIds[i]).getGroupNames().size()==0 )
148 cout<<"!!! No boundary value set for boundary node" << _boundaryNodeIds[i]<< endl;
149 *_runLogFile<< "!!! No boundary value set for boundary node" << _boundaryNodeIds[i]<<endl;
150 _runLogFile->close();
151 throw CdmathException("Missing boundary value");
153 else if(_limitField[_mesh.getNode(_boundaryNodeIds[i]).getGroupName()].bcType==NoneBCLinearElasticity)
155 cout<<"!!! No boundary condition set for boundary node " << _boundaryNodeIds[i]<< endl;
156 *_runLogFile<< "!!!No boundary condition set for boundary node " << _boundaryNodeIds[i]<<endl;
157 _runLogFile->close();
158 throw CdmathException("Missing boundary condition");
160 else if(_limitField[_mesh.getNode(_boundaryNodeIds[i]).getGroupName()].bcType==DirichletLinearElasticity)
161 _dirichletNodeIds.push_back(_boundaryNodeIds[i]);
162 else if(_limitField[_mesh.getNode(_boundaryNodeIds[i]).getGroupName()].bcType!=NeumannLinearElasticity)
164 cout<<"!!! Wrong boundary condition "<< _limitField[_mesh.getNode(_boundaryNodeIds[i]).getGroupName()].bcType<< " set for boundary node " << _boundaryNodeIds[i]<< endl;
165 cout<<"!!! Accepted boundary conditions are Dirichlet "<< DirichletLinearElasticity <<" and Neumann "<< NeumannLinearElasticity << endl;
166 *_runLogFile<< "Wrong boundary condition "<< _limitField[_mesh.getNode(_boundaryNodeIds[i]).getGroupName()].bcType<< " set for boundary node " << _boundaryNodeIds[i]<<endl;
167 *_runLogFile<< "Accepted boundary conditions are Dirichlet "<< DirichletLinearElasticity <<" and Neumann "<< NeumannLinearElasticity <<endl;
168 _runLogFile->close();
169 throw CdmathException("Wrong boundary condition");
172 _NdirichletNodes=_dirichletNodeIds.size();
173 _NunknownNodes=_Nnodes - _NdirichletNodes;
174 cout<<"Number of unknown nodes " << _NunknownNodes <<", Number of boundary nodes " << _NboundaryNodes<< ", Number of Dirichlet boundary nodes " << _NdirichletNodes <<endl<<endl;
175 *_runLogFile<<"Number of unknown nodes " << _NunknownNodes <<", Number of boundary nodes " << _NboundaryNodes<< ", Number of Dirichlet boundary nodes " << _NdirichletNodes <<endl<<endl;
178 //creation de la matrice
180 MatCreateSeqAIJ(PETSC_COMM_SELF, _Nmailles*_nVar, _Nmailles*_nVar, (1+_neibMaxNbCells), PETSC_NULL, &_A);
182 MatCreateSeqAIJ(PETSC_COMM_SELF, _NunknownNodes*_nVar, _NunknownNodes*_nVar, (1+_neibMaxNbNodes), PETSC_NULL, &_A);
184 VecCreate(PETSC_COMM_SELF, &_displacements);
186 VecDuplicate(_displacements, &_b);//RHS of the linear system
189 KSPCreate(PETSC_COMM_SELF, &_ksp);
190 KSPSetType(_ksp, _ksptype);
191 // if(_ksptype == KSPGMRES) KSPGMRESSetRestart(_ksp,10000);
192 KSPSetTolerances(_ksp,_precision,_precision,PETSC_DEFAULT,_maxPetscIts);
193 KSPGetPC(_ksp, &_pc);
194 PCSetType(_pc, _pctype);
196 //Checking whether all boundary conditions are Neumann boundary condition
197 if(!_neumannValuesSet)//Boundary conditions set via LimitField structure
199 map<string, LimitFieldLinearElasticity>::iterator it = _limitField.begin();
200 while(it != _limitField.end() and (it->second).bcType == NeumannLinearElasticity)
202 _onlyNeumannBC = (it == _limitField.end() && _limitField.size()>0);//what if _limitField.size()==0 ???
206 _onlyNeumannBC = _neumannBoundaryValues.size()==_NboundaryNodes;
208 _onlyNeumannBC = _neumannBoundaryValues.size()==_mesh.getBoundaryFaceIds().size();
210 //If only Neumann BC, then matrix is singular and solution should be sought in space of mean zero vectors
213 std::cout<<"## Warning all boundary conditions are Neumann. System matrix is not invertible since constant vectors are in the kernel."<<std::endl;
214 std::cout<<"## As a consequence we seek a zero sum solution, and exact (LU and CHOLESKY) and incomplete factorisations (ILU and ICC) may fail."<<std::endl<<endl;
215 *_runLogFile<<"## Warning all boundary condition are Neumann. System matrix is not invertible since constant vectors are in the kernel."<<std::endl;
216 *_runLogFile<<"## As a consequence we seek a zero sum solution, and exact (LU and CHOLESKY) and incomplete factorisations (ILU and ICC) may fail."<<std::endl<<endl;
218 //Check that the matrix is symmetric
219 PetscBool isSymetric;
220 MatIsSymmetric(_A,_precision,&isSymetric);
223 cout<<"Singular matrix is not symmetric, tolerance= "<< _precision<<endl;
224 throw CdmathException("Singular matrix should be symmetric with kernel composed of constant vectors");
227 MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0, PETSC_NULL, &nullsp);
228 MatSetNullSpace(_A, nullsp);
229 MatSetTransposeNullSpace(_A, nullsp);
230 MatNullSpaceDestroy(&nullsp);
231 //PCFactorSetShiftType(_pc,MAT_SHIFT_NONZERO);
232 //PCFactorSetShiftAmount(_pc,1e-10);
235 _initializedMemory=true;
239 double LinearElasticityModel::computeStiffnessMatrix(bool & stop)
244 result=computeStiffnessMatrixFE(stop);
246 result=computeStiffnessMatrixFV(stop);
248 if(_verbose or _system)
249 MatView(_A,PETSC_VIEWER_STDOUT_SELF);
254 double LinearElasticityModel::computeStiffnessMatrixFE(bool & stop){
261 Matrix M(_Ndim+1,_Ndim+1);//cell geometry matrix
262 std::vector< Vector > GradShapeFuncs(_Ndim+1);//shape functions of cell nodes
263 std::vector< int > nodeIds(_Ndim+1);//cell node Ids
264 std::vector< Node > nodes(_Ndim+1);//cell nodes
265 int i_int, j_int; //index of nodes j and k considered as unknown nodes
266 bool dirichletCell_treated;
268 std::vector< vector< double > > values(_Ndim+1,vector< double >(_Ndim+1,0));//values of shape functions on cell node
269 for (int idim=0; idim<_Ndim+1;idim++)
270 values[idim][idim]=1;
272 /* parameters for boundary treatment */
273 vector< Vector > valuesBorder(_Ndim+1);
274 Vector GradShapeFuncBorder(_Ndim+1);
276 for (int j=0; j<_Nmailles;j++)
278 Cj = _mesh.getCell(j);
280 for (int idim=0; idim<_Ndim+1;idim++){
281 nodeIds[idim]=Cj.getNodeId(idim);
282 nodes[idim]=_mesh.getNode(nodeIds[idim]);
283 for (int jdim=0; jdim<_Ndim;jdim++)
284 M(idim,jdim)=nodes[idim].getPoint()[jdim];
287 for (int idim=0; idim<_Ndim+1;idim++)
288 GradShapeFuncs[idim]=DiffusionEquation::gradientNodal(M,values[idim])/DiffusionEquation::fact(_Ndim);
290 /* Loop on the edges of the cell */
291 for (int idim=0; idim<_Ndim+1;idim++)
293 if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[idim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[idim])
294 {//First node of the edge is not Dirichlet node
295 i_int=DiffusionEquation::unknownNodeIndex(nodeIds[idim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
296 dirichletCell_treated=false;
297 for (int jdim=0; jdim<_Ndim+1;jdim++)
299 if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[jdim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[jdim])
300 {//Second node of the edge is not Dirichlet node
301 j_int= DiffusionEquation::unknownNodeIndex(nodeIds[jdim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
302 MatSetValue(_A,i_int,j_int,_conductivity*(_DiffusionTensor*GradShapeFuncs[idim])*GradShapeFuncs[jdim]/Cj.getMeasure(), ADD_VALUES);
304 else if (!dirichletCell_treated)
305 {//Second node of the edge is a Dirichlet node
306 dirichletCell_treated=true;
307 for (int kdim=0; kdim<_Ndim+1;kdim++)
309 std::map<int,double>::iterator it=_dirichletBoundaryValues.find(nodeIds[kdim]);
310 if( it != _dirichletBoundaryValues.end() )
312 if( _dirichletValuesSet )//New way of storing BC
313 valuesBorder[kdim]=_dirichletBoundaryValues[it->second];
314 else //old way of storing BC
315 valuesBorder[kdim]=_limitField[_mesh.getNode(nodeIds[kdim]).getGroupName()].displacement;
318 valuesBorder[kdim]=Vector(_Ndim);
320 GradShapeFuncBorder=DiffusionEquation::gradientNodal(M,valuesBorder)/DiffusionEquation::fact(_Ndim);
321 double coeff =-_conductivity*(_DiffusionTensor*GradShapeFuncBorder)*GradShapeFuncs[idim]/Cj.getMeasure();
322 VecSetValue(_b,i_int,coeff, ADD_VALUES);
329 //Calcul de la contribution de la condition limite de Neumann au second membre
330 if( _NdirichletNodes !=_NboundaryNodes)
332 vector< int > boundaryFaces = _mesh.getBoundaryFaceIds();
333 int NboundaryFaces=boundaryFaces.size();
334 for(int i = 0; i< NboundaryFaces ; i++)//On parcourt les faces du bord
336 Face Fi = _mesh.getFace(boundaryFaces[i]);
337 for(int j = 0 ; j<_Ndim ; j++)//On parcourt les noeuds de la face
339 if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Fi.getNodeId(j))==_dirichletNodeIds.end())//node j is an Neumann BC node (not a Dirichlet BC node)
341 j_int=DiffusionEquation::unknownNodeIndex(Fi.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
342 if( _neumannValuesSet )
343 coeff =Fi.getMeasure()/(_Ndim+1)*_neumannBoundaryValues[Fi.getNodeId(j)];
345 coeff =Fi.getMeasure()/(_Ndim+1)*_limitField[_mesh.getNode(Fi.getNodeId(j)).getGroupName()].normalForce;
346 VecSetValue(_b, j_int, coeff, ADD_VALUES);
352 MatAssemblyBegin(_A, MAT_FINAL_ASSEMBLY);
353 MatAssemblyEnd(_A, MAT_FINAL_ASSEMBLY);
354 VecAssemblyBegin(_b);
362 double LinearElasticityModel::computeStiffnessMatrixFV(bool & stop){
363 long nbFaces = _mesh.getNumberOfFaces();
367 double inv_dxi, inv_dxj;
368 double barycenterDistance,coeff;
369 Vector normale(_Ndim);
372 std::vector< int > idCells;
376 for (int j=0; j<nbFaces;j++){
377 Fj = _mesh.getFace(j);
379 // compute the normal vector corresponding to face j : from idCells[0] to idCells[1]
380 idCells = Fj.getCellsId();
381 Cell1 = _mesh.getCell(idCells[0]);
383 for(int l=0; l<Cell1.getNumberOfFaces(); l++){
384 if (j == Cell1.getFacesId()[l]){
385 for (int idim = 0; idim < _Ndim; ++idim)
386 normale[idim] = Cell1.getNormalVector(l,idim);
391 //Compute velocity at the face Fj
392 dn=_conductivity*(_DiffusionTensor*normale)*normale;
394 // compute 1/dxi = volume of Ci/area of Fj
395 inv_dxi = Fj.getMeasure()/Cell1.getMeasure();
397 // If Fj is on the boundary
398 if (Fj.getNumberOfCells()==1) {
401 cout << "face numero " << j << " cellule frontiere " << idCells[0] << " ; vecteur normal=(";
402 for(int p=0; p<_Ndim; p++)
403 cout << normale[p] << ",";
407 std::map<int,double>::iterator it=_dirichletBoundaryValues.find(j);
408 if( it != _dirichletBoundaryValues.end() )
410 barycenterDistance=Cell1.getBarryCenter().distance(Fj.getBarryCenter());
411 MatSetValue(_A,idm,idm,dn*inv_dxi/barycenterDistance , ADD_VALUES);
412 VecSetValue(_b,idm, dn*inv_dxi/barycenterDistance*it->second, ADD_VALUES);
416 nameOfGroup = Fj.getGroupName();
418 if (_limitField[nameOfGroup].bcType==NeumannLinearElasticity){
419 if( _neumannValuesSet )
420 coeff =Fi.getMeasure()*_neumannBoundaryValues[j];
422 coeff =Fi.getMeasure()*_limitField[nameOfGroup].normalForce;
423 VecSetValue(_b,idm, coeff, ADD_VALUES);
425 else if(_limitField[nameOfGroup].bcType==DirichletLinearElasticity){
426 barycenterDistance=Cell1.getBarryCenter().distance(Fj.getBarryCenter());
427 MatSetValue(_A,idm,idm,dn*inv_dxi/barycenterDistance , ADD_VALUES);
428 VecSetValue(_b,idm, dn*inv_dxi/barycenterDistance*_limitField[nameOfGroup].displacement, ADD_VALUES);
432 cout<<"!!!!!!!!!!!!!!! Error LinearElasticityModel::computeStiffnessMatrixFV !!!!!!!!!!"<<endl;
433 cout<<"!!!!!! Boundary condition not accepted for boundary named !!!!!!!!!!"<<nameOfGroup<< ", _limitField[nameOfGroup].bcType= "<<_limitField[nameOfGroup].bcType<<endl;
434 cout<<"Accepted boundary conditions are Neumann "<<NeumannLinearElasticity<< " and Dirichlet "<<DirichletLinearElasticity<<endl;
435 *_runLogFile<<"!!!!!! Boundary condition not accepted for boundary named !!!!!!!!!!"<<nameOfGroup<< ", _limitField[nameOfGroup].bcType= "<<_limitField[nameOfGroup].bcType<<endl;
436 _runLogFile->close();
437 throw CdmathException("Boundary condition not accepted");
440 // if Fj is inside the domain
441 } else if (Fj.getNumberOfCells()==2 ){
444 cout << "face numero " << j << " cellule gauche " << idCells[0] << " cellule droite " << idCells[1];
445 cout << " ; vecteur normal=(";
446 for(int p=0; p<_Ndim; p++)
447 cout << normale[p] << ",";
450 Cell2 = _mesh.getCell(idCells[1]);
453 inv_dxj = Fj.getMeasure()/Cell2.getMeasure();
455 inv_dxj = 1/Cell2.getMeasure();
457 barycenterDistance=Cell1.getBarryCenter().distance(Cell2.getBarryCenter());
459 MatSetValue(_A,idm,idm, dn*inv_dxi/barycenterDistance, ADD_VALUES);
460 MatSetValue(_A,idm,idn,-dn*inv_dxi/barycenterDistance, ADD_VALUES);
461 MatSetValue(_A,idn,idn, dn*inv_dxj/barycenterDistance, ADD_VALUES);
462 MatSetValue(_A,idn,idm,-dn*inv_dxj/barycenterDistance, ADD_VALUES);
466 *_runLogFile<<"LinearElasticityModel::computeStiffnessMatrixFV(): incompatible number of cells around a face"<<endl;
467 throw CdmathException("LinearElasticityModel::computeStiffnessMatrixFV(): incompatible number of cells around a face");
471 MatAssemblyBegin(_A, MAT_FINAL_ASSEMBLY);
472 MatAssemblyEnd(_A, MAT_FINAL_ASSEMBLY);
473 VecAssemblyBegin(_b);
481 double LinearElasticityModel::computeRHS(bool & stop)//Contribution of the PDE RHS to the linear systemm RHS (boundary conditions do contribute to the system RHS via the function computeStiffnessMatrix)
483 VecAssemblyBegin(_b);
486 for (int i=0; i<_Nmailles;i++)
487 for (int j=0; j<_Ndim;j++)
488 VecSetValue(_b,i*nVar+j,_gravity(j)*_densityField(i),ADD_VALUES);
492 std::vector< int > nodesId;
493 for (int i=0; i<_Nmailles;i++)
496 nodesId=Ci.getNodesId();
497 for (int j=0; j<nodesId.size();j++)
498 if(!_mesh.isBorderNode(nodesId[j]))
499 for (int k=0; k<_Ndim; k++)
500 VecSetValue(_b,DiffusionEquation::unknownNodeIndex(nodesId[j], _dirichletNodeIds)*nVar+k, _gravity(k)*_densityField(j)*Ci.getMeasure()/(_Ndim+1),ADD_VALUES);
506 if(_verbose or _system)
507 VecView(_b,PETSC_VIEWER_STDOUT_SELF);
513 bool LinearElasticityModel::solveLinearSystem()
517 //Only implicit scheme considered
518 MatAssemblyBegin(_A, MAT_FINAL_ASSEMBLY);
519 MatAssemblyEnd( _A, MAT_FINAL_ASSEMBLY);
521 #if PETSC_VERSION_GREATER_3_5
522 KSPSetOperators(_ksp, _A, _A);
524 KSPSetOperators(_ksp, _A, _A,SAME_NONZERO_PATTERN);
528 KSPSetComputeEigenvalues(_ksp,PETSC_TRUE);
529 KSPSolve(_ksp, _b, _displacements);
531 KSPConvergedReason reason;
532 KSPGetConvergedReason(_ksp,&reason);
533 KSPGetIterationNumber(_ksp, &_PetscIts);
535 KSPGetResidualNorm(_ksp,&residu);
536 if (reason!=2 and reason!=3)
538 cout<<"!!!!!!!!!!!!! Erreur système linéaire : pas de convergence de Petsc."<<endl;
539 cout<<"!!!!!!!!!!!!! Itérations maximales "<<_maxPetscIts<<" atteintes, résidu="<<residu<<", précision demandée= "<<_precision<<endl;
540 cout<<"Solver used "<< _ksptype<<", preconditioner "<<_pctype<<", Final number of iteration= "<<_PetscIts<<endl;
541 *_runLogFile<<"!!!!!!!!!!!!! Erreur système linéaire : pas de convergence de Petsc."<<endl;
542 *_runLogFile<<"!!!!!!!!!!!!! Itérations maximales "<<_maxPetscIts<<" atteintes, résidu="<<residu<<", précision demandée= "<<_precision<<endl;
543 *_runLogFile<<"Solver used "<< _ksptype<<", preconditioner "<<_pctype<<", Final number of iteration= "<<_PetscIts<<endl;
544 _runLogFile->close();
546 resolutionOK = false;
549 if( _MaxIterLinearSolver < _PetscIts)
550 _MaxIterLinearSolver = _PetscIts;
551 cout<<"## Système linéaire résolu en "<<_PetscIts<<" itérations par le solveur "<< _ksptype<<" et le preconditioneur "<<_pctype<<", précision demandée= "<<_precision<<endl<<endl;
552 *_runLogFile<<"## Système linéaire résolu en "<<_PetscIts<<" itérations par le solveur "<< _ksptype<<" et le preconditioneur "<<_pctype<<", précision demandée= "<<_precision<<endl<<endl;
560 void LinearElasticityModel::setMesh(const Mesh &M)
562 if(_Ndim != M.getSpaceDimension() or _Ndim!=M.getMeshDimension())//for the moment we must have space dim=mesh dim
564 cout<< "Problem : dimension defined is "<<_Ndim<< " but mesh dimension= "<<M.getMeshDimension()<<", and space dimension is "<<M.getSpaceDimension()<<endl;
565 *_runLogFile<< "Problem : dim = "<<_Ndim<< " but mesh dim= "<<M.getMeshDimension()<<", mesh space dim= "<<M.getSpaceDimension()<<endl;
566 *_runLogFile<<"LinearElasticityModel::setMesh: mesh has incorrect dimension"<<endl;
567 _runLogFile->close();
568 throw CdmathException("LinearElasticityModel::setMesh: mesh has incorrect dimension");
572 _Nmailles = _mesh.getNumberOfCells();
573 _Nnodes = _mesh.getNumberOfNodes();
575 cout<<"Mesh has "<< _Nmailles << " cells and " << _Nnodes << " nodes"<<endl<<endl;;
576 *_runLogFile<<"Mesh has "<< _Nmailles << " cells and " << _Nnodes << " nodes"<<endl<<endl;
578 // find maximum nb of neibourghs
581 _VV=Field ("Displacements", CELLS, _mesh, _Ndim);
582 _neibMaxNbCells=_mesh.getMaxNbNeighbours(CELLS);
586 if(_Ndim==1 )//The 1D cdmath mesh is necessarily made of segments
587 cout<<"1D Finite element method on segments"<<endl;
590 if( _mesh.isTriangular() )//Mesh dim=2
591 cout<<"2D Finite element method on triangles"<<endl;
592 else if (_mesh.getMeshDimension()==1)//Mesh dim=1
593 cout<<"1D Finite element method on a 2D network : space dimension is "<<_Ndim<< ", mesh dimension is "<<_mesh.getMeshDimension()<<endl;
596 cout<<"Error Finite element with Space dimension "<<_Ndim<< ", and mesh dimension "<<_mesh.getMeshDimension()<< ", mesh should be either triangular either 1D network"<<endl;
597 *_runLogFile<<"LinearElasticityModel::setMesh: mesh has incorrect dimension"<<endl;
598 _runLogFile->close();
599 throw CdmathException("LinearElasticityModel::setMesh: mesh has incorrect cell types");
604 if( _mesh.isTetrahedral() )//Mesh dim=3
605 cout<<"3D Finite element method on tetrahedra"<<endl;
606 else if (_mesh.getMeshDimension()==2 and _mesh.isTriangular())//Mesh dim=2
607 cout<<"2D Finite element method on a 3D surface : space dimension is "<<_Ndim<< ", mesh dimension is "<<_mesh.getMeshDimension()<<endl;
608 else if (_mesh.getMeshDimension()==1)//Mesh dim=1
609 cout<<"1D Finite element method on a 3D network : space dimension is "<<_Ndim<< ", mesh dimension is "<<_mesh.getMeshDimension()<<endl;
612 cout<<"Error Finite element with Space dimension "<<_Ndim<< ", and mesh dimension "<<_mesh.getMeshDimension()<< ", mesh should be either tetrahedral, either a triangularised surface or 1D network"<<endl;
613 *_runLogFile<<"LinearElasticityModel::setMesh: mesh has incorrect dimension"<<endl;
614 _runLogFile->close();
615 throw CdmathException("LinearElasticityModel::setMesh: mesh has incorrect cell types");
619 _VV=Field ("Temperature", NODES, _mesh, _Ndim);
621 _neibMaxNbNodes=_mesh.getMaxNbNeighbours(NODES);
622 _boundaryNodeIds = _mesh.getBoundaryNodeIds();
623 _NboundaryNodes=_boundaryNodeIds.size();
629 void LinearElasticityModel::setLinearSolver(linearSolver kspType, preconditioner pcType)
631 //_maxPetscIts=maxIterationsPetsc;
632 // set linear solver algorithm
634 _ksptype = (char*)&KSPGMRES;
635 else if (kspType==CG)
636 _ksptype = (char*)&KSPCG;
637 else if (kspType==BCGS)
638 _ksptype = (char*)&KSPBCGS;
640 cout << "!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!" << endl;
641 *_runLogFile << "!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!" << endl;
642 _runLogFile->close();
643 throw CdmathException("!!! Error : only 'GMRES', 'CG' or 'BCGS' algorithm is acceptable !!!");
645 // set preconditioner
647 _pctype = (char*)&PCNONE;
648 else if (pcType ==LU)
649 _pctype = (char*)&PCLU;
650 else if (pcType == ILU)
651 _pctype = (char*)&PCILU;
652 else if (pcType ==CHOLESKY)
653 _pctype = (char*)&PCCHOLESKY;
654 else if (pcType == ICC)
655 _pctype = (char*)&PCICC;
657 cout << "!!! Error : only 'NONE', 'LU', 'ILU', 'CHOLESKY' or 'ICC' preconditioners are acceptable !!!" << endl;
658 *_runLogFile << "!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" << endl;
659 _runLogFile->close();
660 throw CdmathException("!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" );
664 bool LinearElasticityModel::solveStationaryProblem()
666 if(!_initializedMemory)
668 *_runLogFile<< "ProblemCoreFlows::run() call initialize() first"<< _fileName<<endl;
669 _runLogFile->close();
670 throw CdmathException("ProblemCoreFlows::run() call initialize() first");
672 bool stop=false; // Does the Problem want to stop (error) ?
674 cout<< "!!! Running test case "<< _fileName << " using ";
675 *_runLogFile<< "!!! Running test case "<< _fileName<< " using ";
679 cout<< "Finite volumes method"<<endl<<endl;
680 *_runLogFile<< "Finite volumes method"<<endl<<endl;
684 cout<< "Finite elements method"<<endl<<endl;
685 *_runLogFile<< "Finite elements method"<< endl<<endl;
688 computeStiffnessMatrix( stop);
690 cout << "Error : failed computing diffusion matrix, stopping calculation"<< endl;
691 *_runLogFile << "Error : failed computing diffusion matrix, stopping calculation"<< endl;
692 _runLogFile->close();
693 throw CdmathException("Failed computing diffusion matrix");
697 cout << "Error : failed computing right hand side, stopping calculation"<< endl;
698 *_runLogFile << "Error : failed computing right hand side, stopping calculation"<< endl;
699 throw CdmathException("Failed computing right hand side");
701 stop = !solveLinearSystem();
703 cout << "Error : failed solving linear system, stopping calculation"<< endl;
704 *_runLogFile << "Error : failed linear system, stopping calculation"<< endl;
705 _runLogFile->close();
706 throw CdmathException("Failed solving linear system");
709 _computationCompletedSuccessfully=true;
712 *_runLogFile<< "!!!!!! Computation successful"<< endl;
713 _runLogFile->close();
718 void LinearElasticityModel::save(){
719 cout<< "Saving numerical results"<<endl<<endl;
720 *_runLogFile<< "Saving numerical results"<< endl<<endl;
722 string resultFile(_path+"/LinearElasticityModel");//Results
725 resultFile+=_fileName;
727 // create mesh and component info
728 string suppress ="rm -rf "+resultFile+"_*";
729 system(suppress.c_str());//Nettoyage des précédents calculs identiques
731 if(_verbose or _system)
732 VecView(_displacements,PETSC_VIEWER_STDOUT_SELF);
736 for(int i=0; i<_Nmailles; i++)
738 for(int j=0; j<_nVar; j++)
741 VecGetValues(_displacements, 1, &k, &uk);
748 for(int i=0; i<_NunknownNodes; i++)
750 globalIndex = DiffusionEquation::globalNodeIndex(i, _dirichletNodeIds);
751 for(int j=0; j<_nVar; j++)
754 VecGetValues(_displacements, 1, &k, &uk);
755 _VV(globalIndex,j)=uk;
761 for(int i=0; i<_NdirichletNodes; i++)
763 Ni=_mesh.getNode(_dirichletNodeIds[i]);
764 nameOfGroup = Ni.getGroupName();
765 for(int j=0; j<_nVar; j++)
766 _VV(_dirichletNodeIds[i])=_limitField[nameOfGroup].displacement[i];
773 _VV.writeVTK(resultFile);
776 _VV.writeMED(resultFile);
779 _VV.writeCSV(resultFile);
784 LinearElasticityModel::getOutputDisplacementField()
786 if(!_computationCompletedSuccessfully)
787 throw("Computation not performed yet or failed. No displacement field available");
792 void LinearElasticityModel::terminate()
794 VecDestroy(&_displacements);
799 LinearElasticityModel::setDirichletValues(map< int, double> dirichletBoundaryValues)
801 _dirichletValuesSet=true;
802 _dirichletBoundaryValues=dirichletBoundaryValues;
805 LinearElasticityModel::setNeumannValues(map< int, double> neumannBoundaryValues)
807 _neumannValuesSet=true;
808 _neumannBoundaryValues=neumannBoundaryValues;
812 LinearElasticityModel::getConditionNumber(bool isSingular, double tol) const
814 SparseMatrixPetsc A = SparseMatrixPetsc(_A);
815 return A.getConditionNumber( isSingular, tol);