1 //============================================================================
2 // Name : Problème CoreFlows
5 // Copyright : CEA Saclay 2014
6 // Description : Classe générique des problèmes de Thermohydraulique
7 // Il s'agit d'une classe virtuelle pure (non instanciable qui regroupe
8 // les fonctionalités communes à tous les codes thermohydraulique.
9 // Le but est d'avoir une interface commune rendant
10 // plus lisibles et plus evolutifs les codes dévelopés avec CDMATH
11 //============================================================================
13 #include "ProblemCoreFlows.hxx"
19 ProblemCoreFlows::ProblemCoreFlows()
21 PetscBool petscInitialized;
22 PetscInitialized(&petscInitialized);
24 PetscInitialize(NULL,NULL,0,0);
32 _precision_Newton=_precision;
38 _fileName = "myCoreFlowsProblem";
40 _initialDataSet=false;
41 _initializedMemory=false;
44 _wellBalancedCorrection=false;
46 _MaxIterLinearSolver=0;//During several newton iterations, stores the max petssc interations
49 int _PetscIts=0;//the number of iterations of the linear solver
50 _ksptype = (char*)&KSPGMRES;
51 _pctype = (char*)&PCLU;
52 _heatPowerFieldSet=false;
53 _heatTransfertCoeff=0;
54 _rodTemperatureFieldSet=false;
58 _conditionNumber=false;
60 _runLogFile=new ofstream;
62 //extracting current directory
63 char result[ PATH_MAX ];
64 getcwd(result, PATH_MAX );
65 _path=string( result );
69 bool ProblemCoreFlows::isStationary() const
74 double ProblemCoreFlows::presentTime() const
78 void ProblemCoreFlows::setTimeMax(double timeMax){
81 void ProblemCoreFlows::setPresentTime (double time)
85 void ProblemCoreFlows::setMaxNbOfTimeStep(int maxNbOfTimeStep){
86 _maxNbOfTimeStep = maxNbOfTimeStep;
88 void ProblemCoreFlows::setCFL(double cfl)
92 void ProblemCoreFlows::setPrecision(double precision)
96 void ProblemCoreFlows::setNumericalScheme(SpaceScheme spaceScheme, TimeScheme timeScheme){
97 _timeScheme = timeScheme;
98 _spaceScheme = spaceScheme;
101 void ProblemCoreFlows::setInitialField(const Field &VV)
104 if(_Ndim != VV.getSpaceDimension()){
105 *_runLogFile<<"ProblemCoreFlows::setInitialField: mesh has incorrect space dimension"<<endl;
106 _runLogFile->close();
107 throw CdmathException("ProblemCoreFlows::setInitialField: mesh has incorrect space dimension");
109 if(_nVar!=VV.getNumberOfComponents())
111 *_runLogFile<<"ProblemCoreFlows::setInitialField: Initial field has incorrect number of components"<<endl;
112 _runLogFile->close();
113 throw CdmathException("ProblemCoreFlows::setInitialField: Initial field has incorrect number of components");
119 _Nmailles = _mesh.getNumberOfCells();
120 _Nnodes = _mesh.getNumberOfNodes();
121 _Nfaces = _mesh.getNumberOfFaces();
122 _perimeters=Field("Perimeters", CELLS, _mesh,1);
124 // find _minl and maximum nb of neibourghs
126 int nbNeib,indexFace;
131 cout<<"Computing cell perimeters and mesh minimal diameter"<<endl;
133 if(VV.getTypeOfField()==NODES)
135 _minl = _mesh.getMaxNbNeighbours(NODES);
136 _neibMaxNbNodes=_mesh.getMaxNbNeighbours(NODES);
139 for (int i=0; i<_mesh.getNumberOfCells(); i++){
140 Ci = _mesh.getCell(i);
141 //Detect mesh with junction
143 for(int j=0; j<Ci.getNumberOfFaces(); j++){
144 Fk=_mesh.getFace(Ci.getFacesId()[j]);
145 nbNeib+=Fk.getNumberOfCells()-1;
147 if(nbNeib>_neibMaxNb)
152 for (int k=0 ; k<Ci.getNumberOfFaces() ; k++){
153 indexFace=Ci.getFacesId()[k];
154 Fk = _mesh.getFace(indexFace);
155 _minl = min(_minl,Ci.getMeasure()/Fk.getMeasure());
156 _perimeters(i)+=Fk.getMeasure();
159 _minl = min(_minl,Ci.getMeasure());
160 _perimeters(i)=Ci.getNumberOfFaces();
163 _initialDataSet=true;
166 cout<<_perimeters<<endl;
168 void ProblemCoreFlows::setInitialField(string fileName, string fieldName, int timeStepNumber)
170 Field VV(fileName,CELLS,fieldName,timeStepNumber,0);
173 void ProblemCoreFlows::setInitialFieldConstant(string fileName, const vector<double> Vconstant)
176 Field VV("Primitive", CELLS, M, Vconstant.size());
178 for (int j = 0; j < M.getNumberOfCells(); j++) {
179 for (int i=0; i< VV.getNumberOfComponents(); i++)
180 VV(j,i) = Vconstant[i];
185 void ProblemCoreFlows:: setInitialFieldConstant(const Mesh& M, const Vector Vconstant)
187 Field VV("Primitive", CELLS, M, Vconstant.getNumberOfRows());
189 for (int j = 0; j < M.getNumberOfCells(); j++) {
190 for (int i=0; i< VV.getNumberOfComponents(); i++)
191 VV(j,i) = Vconstant(i);
195 void ProblemCoreFlows:: setInitialFieldConstant(const Mesh& M, const vector<double> Vconstant)
197 Field VV("Primitive", CELLS, M, Vconstant.size());
199 for (int j = 0; j < M.getNumberOfCells(); j++) {
200 for (int i=0; i< VV.getNumberOfComponents(); i++)
201 VV(j,i) = Vconstant[i];
205 void ProblemCoreFlows::setInitialFieldConstant( int nDim, const vector<double> Vconstant, double xmin, double xmax, int nx, string leftSide, string rightSide,
206 double ymin, double ymax, int ny, string backSide, string frontSide,
207 double zmin, double zmax, int nz, string bottomSide, string topSide)
211 //cout<<"coucou1 xmin="<<xmin<<", xmax= "<<xmax<< ", nx= "<<nx<<endl;
212 M=Mesh(xmin,xmax,nx);
213 //cout<<"coucou2"<<endl;
216 M=Mesh(xmin,xmax,nx,ymin,ymax,ny);
218 M=Mesh(xmin,xmax,nx,ymin,ymax,ny,zmin,zmax,nz);
220 cout<<"ProblemCoreFlows::setInitialFieldConstant: Space dimension nDim should be between 1 and 3"<<endl;
221 *_runLogFile<<"ProblemCoreFlows::setInitialFieldConstant: Space dimension nDim should be between 1 and 3"<<endl;
222 _runLogFile->close();
223 throw CdmathException("Space dimension nDim should be between 1 and 3");
226 M.setGroupAtPlan(xmax,0,_precision,rightSide);
227 M.setGroupAtPlan(xmin,0,_precision,leftSide);
229 M.setGroupAtPlan(ymax,1,_precision,frontSide);
230 M.setGroupAtPlan(ymin,1,_precision,backSide);
233 M.setGroupAtPlan(zmax,2,_precision,topSide);
234 M.setGroupAtPlan(zmin,2,_precision,bottomSide);
237 setInitialFieldConstant(M, Vconstant);
239 void ProblemCoreFlows::setInitialFieldStepFunction(const Mesh M, const Vector VV_Left, const Vector VV_Right, double disc_pos, int direction)
241 if (VV_Right.getNumberOfRows()!=VV_Left.getNumberOfRows())
243 *_runLogFile<<"ProblemCoreFlows::setStepFunctionInitialField: Vectors VV_Left and VV_Right have different sizes"<<endl;
244 _runLogFile->close();
245 throw CdmathException( "ProblemCoreFlows::setStepFunctionInitialField: Vectors VV_Left and VV_Right have different sizes");
247 Field VV("Primitive", CELLS, M, VV_Left.getNumberOfRows());
249 double component_value;
251 for (int j = 0; j < M.getNumberOfCells(); j++) {
253 component_value=M.getCell(j).x();
254 else if(direction==1)
255 component_value=M.getCell(j).y();
256 else if(direction==2)
257 component_value=M.getCell(j).z();
259 _runLogFile->close();
260 throw CdmathException( "ProblemCoreFlows::setStepFunctionInitialField: direction should be an integer between 0 and 2");
263 for (int i=0; i< VV.getNumberOfComponents(); i++)
264 if (component_value< disc_pos )
265 VV(j,i) = VV_Left[i];
267 VV(j,i) = VV_Right[i];
271 void ProblemCoreFlows::setInitialFieldStepFunction( int nDim, const vector<double> VV_Left, vector<double> VV_Right, double xstep,
272 double xmin, double xmax, int nx, string leftSide, string rightSide,
273 double ymin, double ymax, int ny, string backSide, string frontSide,
274 double zmin, double zmax, int nz, string bottomSide, string topSide)
278 M=Mesh(xmin,xmax,nx);
280 M=Mesh(xmin,xmax,nx,ymin,ymax,ny);
282 M=Mesh(xmin,xmax,nx,ymin,ymax,ny,zmin,zmax,nz);
285 _runLogFile->close();
286 throw CdmathException("Space dimension nDim should be between 1 and 3");
289 M.setGroupAtPlan(xmax,0,_precision,rightSide);
290 M.setGroupAtPlan(xmin,0,_precision,leftSide);
292 M.setGroupAtPlan(ymax,1,_precision,frontSide);
293 M.setGroupAtPlan(ymin,1,_precision,backSide);
296 M.setGroupAtPlan(zmax,2,_precision,topSide);
297 M.setGroupAtPlan(zmin,2,_precision,bottomSide);
299 Vector V_Left(VV_Left.size()), V_Right(VV_Right.size());
300 for(int i=0;i<VV_Left.size(); i++){
301 V_Left(i)=VV_Left[i];
302 V_Right(i)=VV_Right[i];
304 setInitialFieldStepFunction(M, V_Left, V_Right, xstep);
307 void ProblemCoreFlows::setInitialFieldSphericalStepFunction(const Mesh M, const Vector Vin, const Vector Vout, double radius, const Vector Center)
309 if((Center.size()!=M.getSpaceDimension()) || (Vout.size() != Vin.size()) )
311 cout<< "Vout.size()= "<<Vout.size() << ", Vin.size()= "<<Vin.size()<<", Center.size()="<<Center.size()<<", M.getSpaceDim= "<< M.getSpaceDimension()<<endl;
312 throw CdmathException("ProblemCoreFlows::setInitialFieldSphericalStepFunction : Vector size error");
314 int nVar=Vout.size();
315 int spaceDim=M.getSpaceDimension();
316 Field VV("Primitive variables for spherical step function", CELLS, M, nVar);
318 Vector currentPoint(spaceDim);
319 for(int i=0;i<M.getNumberOfCells();i++)
321 currentPoint(0)=M.getCell(i).x();
324 currentPoint(1)=M.getCell(i).y();
326 currentPoint(2)=M.getCell(i).z();
328 if((currentPoint-Center).norm()<radius)
329 for(int j=0;j<nVar;j++)
332 for(int j=0;j<nVar;j++)
338 double ProblemCoreFlows::getTime()
342 unsigned ProblemCoreFlows::getNbTimeStep()
346 double ProblemCoreFlows::getCFL()
350 double ProblemCoreFlows::getPrecision()
354 SpaceScheme ProblemCoreFlows::getSpaceScheme()
358 TimeScheme ProblemCoreFlows::getTimeScheme()
362 Mesh ProblemCoreFlows::getMesh()
367 void ProblemCoreFlows::setLinearSolver(linearSolver kspType, preconditioner pcType)
369 //_maxPetscIts=maxIterationsPetsc;
370 // set linear solver algorithm
372 _ksptype = (char*)&KSPGMRES;
373 else if (kspType==CG)
374 _ksptype = (char*)&KSPCG;
375 else if (kspType==BCGS)
376 _ksptype = (char*)&KSPBCGS;
378 cout << "!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!" << endl;
379 *_runLogFile << "!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!" << endl;
380 _runLogFile->close();
381 throw CdmathException("!!! Error : only 'GMRES', 'CG' or 'BCGS' algorithm is acceptable !!!");
383 // set preconditioner
385 _pctype = (char*)&PCNONE;
386 else if (pcType ==LU)
387 _pctype = (char*)&PCLU;
388 else if (pcType == ILU)
389 _pctype = (char*)&PCILU;
390 else if (pcType ==CHOLESKY)
391 _pctype = (char*)&PCCHOLESKY;
392 else if (pcType == ICC)
393 _pctype = (char*)&PCICC;
395 cout << "!!! Error : only 'NONE', 'LU', 'ILU', 'CHOLESKY' or 'ICC' preconditioners are acceptable !!!" << endl;
396 *_runLogFile << "!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" << endl;
397 _runLogFile->close();
398 throw CdmathException("!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" );
403 // Cette methode lance une execution du ProblemCoreFlows
404 // Elle peut etre utilisee si le probleme n'est couple a aucun autre.
405 // (s'il n'a besoin d'aucun champ d'entree).
406 // Precondition: initialize
407 // Seule la methode terminate peut etre appelee apres
408 bool ProblemCoreFlows::run()
410 if(!_initializedMemory)
412 _runLogFile->close();
413 throw CdmathException("ProblemCoreFlows::run() call initialize() first");
415 bool stop=false; // Does the Problem want to stop (error) ?
416 bool ok; // Is the time interval successfully solved ?
417 _isStationary=false;//in case of a second run with a different physics or cfl
419 cout<< "Running test case "<< _fileName<<endl;
421 _runLogFile->open((_fileName+".log").c_str(), ios::out | ios::trunc);;//for creation of a log file to save the history of the simulation
422 *_runLogFile<< "Running test case "<< _fileName<<endl;
425 while(!stop && !_isStationary &&_time<_timeMax && _nbTimeStep<_maxNbOfTimeStep)
427 ok=false; // Is the time interval successfully solved ?
429 // Guess the next time step length
430 _dt=computeTimeStep(stop);
432 cout << "Failed computing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
433 *_runLogFile << "Failed computing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
436 // Loop on the time interval tries
437 while (!ok && !stop )
439 stop=!initTimeStep(_dt);
440 // Prepare the next time step
442 cout << "Failed initializing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
443 *_runLogFile << "Failed initializing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
446 // Solve the next time step
449 if (!ok) // The resolution failed, try with a new time interval.
453 cout << "Failed solving time step "<<_nbTimeStep<<", time = " << _time <<" _dt= "<<_dt<<", cfl= "<<_cfl<<", trying again with cfl/2"<< endl;
454 *_runLogFile << "Failed solving time step "<<_nbTimeStep<<", time = " << _time <<" _dt= "<<_dt<<", cfl= "<<_cfl<<", trying again with cfl/2"<< endl;
459 cout << "Failed solving time step "<<_nbTimeStep<<", _time = " << _time<<" _dt= "<<_dt<<", cfl= "<<_cfl <<", stopping calculation"<< endl;
460 *_runLogFile << "Failed solving time step "<<_nbTimeStep<<", _time = " << _time<<" _dt= "<<_dt<<", cfl= "<<_cfl <<", stopping calculation"<< endl;
461 stop=true; // Impossible to solve the next time step, the Problem has given up
465 else // The resolution was successful, validate and go to the next time step.
468 if (_nbTimeStep%_freqSave ==0){
469 cout << "Time step = "<< _nbTimeStep << ", dt = "<< _dt <<", time = "<<_time << ", ||Un+1-Un||= "<<_erreur_rel<<endl;
470 *_runLogFile << "Time step = "<< _nbTimeStep << ", dt = "<< _dt <<", time = "<<_time << ", ||Un+1-Un||= "<<_erreur_rel<<endl;
476 cout << "Stationary state reached" <<endl;
477 *_runLogFile << "Stationary state reached" <<endl;
479 else if(_time>=_timeMax){
480 cout<<"Maximum time "<<_timeMax<<" reached"<<endl;
481 *_runLogFile<<"Maximum time "<<_timeMax<<" reached"<<endl;
483 else if(_nbTimeStep>=_maxNbOfTimeStep){
484 cout<<"Maximum number of time steps "<<_maxNbOfTimeStep<<" reached"<<endl;
485 *_runLogFile<<"Maximum number of time steps "<<_maxNbOfTimeStep<<" reached"<<endl;
488 cout<<"Error problem wants to stop!"<<endl;
489 *_runLogFile<<"Error problem wants to stop!"<<endl;
491 cout << "End of calculation time t= " << _time << " at time step number "<< _nbTimeStep << endl;
492 *_runLogFile << "End of calculation time t= " << _time << " at time step number "<< _nbTimeStep << endl;
494 _runLogFile->close();
498 void ProblemCoreFlows::displayMatrix(double *matrix, int size, string name)
501 for(int p=0; p<size; p++)
503 for(int q=0; q<size; q++)
505 cout << matrix[p*size+q] << "\t";
512 void ProblemCoreFlows::displayVector(double *vector, int size, string name)
515 for(int q=0; q<size; q++)
517 cout << vector[q] << "\t";
521 void ProblemCoreFlows::setFileName(string fileName){
522 _fileName = fileName;
525 void ProblemCoreFlows::setFreqSave(int freqSave){
526 _freqSave = freqSave;
528 bool ProblemCoreFlows::solveTimeStep(){
530 bool converged=false, ok=true;
531 while(!converged && ok && _NEWTON_its < _maxNewtonIts){
532 ok=iterateTimeStep(converged);//resolution du systeme lineaire si schema implicite
534 if(_timeScheme == Implicit && _nbTimeStep%_freqSave ==0)//To monitor the convergence of the newton scheme
536 cout << "\n Newton iteration " << _NEWTON_its<< ", "<< _ksptype << " iterations : " << " : " << _PetscIts<< " maximum variation ||Uk+1-Uk||: " << _erreur_rel << endl;
537 *_runLogFile<< "\n Newton iteration " << _NEWTON_its<< ", "<< _ksptype << " iterations : " << " : " << _PetscIts<< " maximum variation ||Uk+1-Uk||: " << _erreur_rel << endl;
541 PetscReal sv_max, sv_min;
542 KSPComputeExtremeSingularValues(_ksp, &sv_max, &sv_min);
543 cout<<" singular value max = " << sv_max <<" singular value min = " << sv_min <<" condition number = " << sv_max/sv_min <<endl;
544 *_runLogFile<<" singular value max = " << sv_max <<" singular value min = " << sv_min <<" condition number = " << sv_max/sv_min <<endl;
550 if(_NEWTON_its >= _maxNewtonIts){
551 cout << "Maximum number of Newton iterations "<<_maxNewtonIts<<" reached"<< endl;
552 *_runLogFile << "Maximum number of Newton iterations "<<_maxNewtonIts<<" reached"<< endl;
555 cout<<"iterateTimeStep: solving Newton iteration "<<_NEWTON_its<<" Failed"<<endl;
556 *_runLogFile<<"iterateTimeStep: solving Newton iteration "<<_NEWTON_its<<" Failed"<<endl;
559 else if(_timeScheme == Implicit && _nbTimeStep%_freqSave ==0)
562 cout << "Nombre d'iterations de Newton "<< _NEWTON_its << ", Nombre max d'iterations "<< _ksptype << " : " << _MaxIterLinearSolver << endl;
564 *_runLogFile << "Nombre d'iterations de Newton "<< _NEWTON_its << " Variation ||Un+1-Un||= "<< _erreur_rel<<endl;
565 *_runLogFile << "Nombre max d'iterations "<< _ksptype << " : " << _MaxIterLinearSolver << endl;
566 _MaxIterLinearSolver = 0;
571 ProblemCoreFlows::~ProblemCoreFlows()
574 PetscBool petscInitialized;
575 PetscInitialized(&petscInitialized);