1 #include "ProblemFluid.hxx"
7 ProblemFluid::ProblemFluid(MPI_Comm comm):ProblemCoreFlows(comm)
13 _porosityFieldSet=false;
14 _pressureLossFieldSet=false;
15 _sectionFieldSet=false;
16 _GravityField3d=vector<double>(3,0);
17 _gravityReferencePoint=vector<double>(3,0);
18 _Uroe=NULL;_Udiff=NULL;_temp=NULL;_l=NULL;_vec_normal=NULL;;
21 _saveConservativeField=false;
22 _usePrimitiveVarsInNewton=false;
23 _saveInterfacialField=false;
24 _err_press_max=0; _part_imag_max=0; _nbMaillesNeg=0; _nbVpCplx=0;_minm1=1e30;_minm2=1e30;//Pour affichage paramètres diphasiques dans IterateTimeStep
26 _entropicCorrection=false;
27 _pressureCorrectionOrder=2;
28 _nonLinearFormulation=Roe;
33 SpaceScheme ProblemFluid::getSpaceScheme() const
37 void ProblemFluid::setNumericalScheme(SpaceScheme spaceScheme, TimeScheme timeScheme)
39 if( _nbTimeStep>0 && timeScheme!=_timeScheme)//This is a change of time scheme during a simulation
40 _restartWithNewTimeScheme=true;
41 _timeScheme = timeScheme;
42 _spaceScheme = spaceScheme;
45 void ProblemFluid::initialize()
49 *_runLogFile<<"!!!!!!!!ProblemFluid::initialize() set initial data first"<<endl;
51 throw CdmathException("!!!!!!!!ProblemFluid::initialize() set initial data first");
53 else if (_VV.getTypeOfField() != CELLS)
55 *_runLogFile<<"!!!!!!!!Initial data should be a field on CELLS, not NODES, neither FACES"<<endl;
57 throw CdmathException("!!!!!!!!ProblemFluid::initialize() Initial data should be a field on CELLS, not NODES, neither FACES");
59 cout << "Number of Phases = " << _nbPhases << " mesh dimension = "<<_Ndim<<" number of variables = "<<_nVar<<endl;
60 *_runLogFile << "Number of Phases = " << _nbPhases << " spaceDim= "<<_Ndim<<" number of variables= "<<_nVar<<endl;
62 /********* local arrays ****************/
63 _AroePlus = new PetscScalar[_nVar*_nVar];
64 _Diffusion = new PetscScalar[_nVar*_nVar];
65 _AroeMinus = new PetscScalar[_nVar*_nVar];
66 _Aroe = new PetscScalar[_nVar*_nVar];
67 _absAroe = new PetscScalar[_nVar*_nVar];
68 _signAroe = new PetscScalar[_nVar*_nVar];
69 _invAroe = new PetscScalar[_nVar*_nVar];
70 _AroeImplicit = new PetscScalar[_nVar*_nVar];
71 _AroeMinusImplicit = new PetscScalar[_nVar*_nVar];
72 _AroePlusImplicit = new PetscScalar[_nVar*_nVar];
73 _absAroeImplicit = new PetscScalar[_nVar*_nVar];
74 _primToConsJacoMat = new PetscScalar[_nVar*_nVar];
75 _phi = new PetscScalar[_nVar];
76 _Jcb = new PetscScalar[_nVar*_nVar];
77 _JcbDiff = new PetscScalar[_nVar*_nVar];
78 _a = new PetscScalar[_nVar*_nVar];
79 _externalStates = new PetscScalar[_nVar];
80 _Ui = new PetscScalar[_nVar];
81 _Uj = new PetscScalar[_nVar];
82 _Vi = new PetscScalar[_nVar];
83 _Vj = new PetscScalar[_nVar];
84 _Uij = new PetscScalar[_nVar];//used for VFRoe scheme
85 _Vij = new PetscScalar[_nVar];//used for VFRoe scheme
86 _Si = new PetscScalar[_nVar];
87 _Sj = new PetscScalar[_nVar];
88 _pressureLossVector= new PetscScalar[_nVar];
89 _porosityGradientSourceVector= new PetscScalar[_nVar];
91 _l = new double[_nVar];
92 _r = new double[_nVar];
93 _Udiff = new double[_nVar];
94 _temp = new double[_nVar*_nVar];
96 _idm = new int[_nVar];
97 _idn = new int[_nVar];
98 _vec_normal = new double[_Ndim];
100 for(int k=0;k<_nVar*_nVar;k++)
105 for(int k=0; k<_nVar; k++){
110 /**************** Field creation *********************/
111 if(!_heatPowerFieldSet){
112 _heatPowerField=Field("Heat Power",CELLS,_mesh,1);
113 for(int i =0; i<_Nmailles; i++)
114 _heatPowerField(i) = _heatSource;
117 _dp_over_dt=Field("dP/dt",CELLS,_mesh,1);
118 if(!_porosityFieldSet){
119 _porosityField=Field("Porosity field",CELLS,_mesh,1);
120 for(int i =0; i<_Nmailles; i++)
121 _porosityField(i) = 1;
122 _porosityFieldSet=true;
125 //conservative field used only for saving results
126 _UU=Field ("Conservative vec", CELLS, _mesh, _nVar);
127 if(_saveInterfacialField && _nonLinearFormulation==VFRoe)
129 _UUstar=Field ("Interfacial U", CELLS, _mesh, _nVar);
130 _VVstar=Field ("Interfacial V", CELLS, _mesh, _nVar);
133 //Construction des champs primitifs et conservatifs initiaux comme avant dans ParaFlow
134 double * initialFieldPrim = new double[_nVar*_Nmailles];
135 for(int i =0; i<_Nmailles;i++)
136 for(int j =0; j<_nVar;j++)
137 initialFieldPrim[i*_nVar+j]=_VV(i,j);
138 double *initialFieldCons = new double[_nVar*_Nmailles];
139 for(int i=0; i<_Nmailles; i++)
140 primToCons(initialFieldPrim, i, initialFieldCons, i);
141 for(int i =0; i<_Nmailles;i++)
142 for(int j =0; j<_nVar;j++)
143 _UU(i,j)=initialFieldCons[i*_nVar+j];
145 /**********Petsc structures: ****************/
147 //creation de la matrice
148 if(_timeScheme == Implicit)
149 MatCreateSeqBAIJ(PETSC_COMM_SELF, _nVar, _nVar*_Nmailles, _nVar*_Nmailles, (1+_neibMaxNbCells), PETSC_NULL, &_A);
151 //creation des vecteurs
152 VecCreateSeq(PETSC_COMM_SELF, _nVar, &_Uext);
153 VecCreateSeq(PETSC_COMM_SELF, _nVar, &_Vext);
154 VecCreateSeq(PETSC_COMM_SELF, _nVar, &_Uextdiff);
155 // VecCreateSeq(PETSC_COMM_SELF, _nVar*_Nmailles, &_conservativeVars);
156 VecCreate(PETSC_COMM_SELF, &_conservativeVars);//Current conservative variables at Newton iteration k between time steps n and n+1
157 VecSetSizes(_conservativeVars,PETSC_DECIDE,_nVar*_Nmailles);
158 VecSetBlockSize(_conservativeVars,_nVar);
159 VecSetFromOptions(_conservativeVars);
160 VecDuplicate(_conservativeVars, &_old);//Old conservative variables at time step n
161 VecDuplicate(_conservativeVars, &_newtonVariation);//Newton variation Uk+1-Uk to be computed between time steps n and n+1
162 VecDuplicate(_conservativeVars, &_b);//Right hand side of Newton method at iteration k between time steps n and n+1
163 VecDuplicate(_conservativeVars, &_primitiveVars);//Current primitive variables at Newton iteration k between time steps n and n+1
167 VecDuplicate(_conservativeVars, &_vecScaling);
168 VecDuplicate(_conservativeVars, &_invVecScaling);
169 VecDuplicate(_conservativeVars, &_bScaling);
171 _blockDiag = new PetscScalar[_nVar];
172 _invBlockDiag = new PetscScalar[_nVar];
176 int *indices = new int[_Nmailles];
177 std::iota(indices, indices +_Nmailles, 0);
178 VecSetValuesBlocked(_conservativeVars, _Nmailles, indices, initialFieldCons, INSERT_VALUES);
179 VecAssemblyBegin(_conservativeVars);
180 VecAssemblyEnd(_conservativeVars);
181 VecCopy(_conservativeVars, _old);
182 VecAssemblyBegin(_old);
183 VecAssemblyEnd(_old);
184 VecSetValuesBlocked(_primitiveVars, _Nmailles, indices, initialFieldPrim, INSERT_VALUES);
185 VecAssemblyBegin(_primitiveVars);
186 VecAssemblyEnd(_primitiveVars);
189 cout << "Variables primitives initiales : " << endl;
190 VecView(_primitiveVars, PETSC_VIEWER_STDOUT_WORLD);
192 cout<<"Variables conservatives initiales : "<<endl;
193 VecView(_conservativeVars, PETSC_VIEWER_STDOUT_SELF);
196 delete[] initialFieldPrim;
197 delete[] initialFieldCons;
202 // Creation du solveur de Newton de PETSc
203 if( _timeScheme == Implicit && _nonLinearSolver != Newton_SOLVERLAB)
207 // set nonlinear solver
208 if (_nonLinearSolver == Newton_PETSC_LINESEARCH || _nonLinearSolver == Newton_PETSC_LINESEARCH_BASIC || _nonLinearSolver == Newton_PETSC_LINESEARCH_BT || _nonLinearSolver == Newton_PETSC_LINESEARCH_SECANT || _nonLinearSolver == Newton_PETSC_LINESEARCH_NLEQERR)
209 snestype = (char*)&SNESNEWTONLS;
210 else if (_nonLinearSolver == Newton_PETSC_TRUSTREGION)
211 snestype = (char*)&SNESNEWTONTR;
212 else if (_nonLinearSolver == Newton_PETSC_NGMRES)
213 snestype = (char*)&SNESNGMRES;
214 else if (_nonLinearSolver ==Newton_PETSC_ASPIN)
215 snestype = (char*)&SNESASPIN;
216 else if(_nonLinearSolver != Newton_SOLVERLAB)
218 cout << "!!! Error : only 'Newton_PETSC_LINESEARCH', 'Newton_PETSC_TRUSTREGION', 'Newton_PETSC_NGMRES', 'Newton_PETSC_ASPIN' or 'Newton_SOLVERLAB' nonlinear solvers are acceptable !!!" << endl;
219 *_runLogFile << "!!! Error : only 'Newton_PETSC_LINESEARCH', 'Newton_PETSC_TRUSTREGION', 'Newton_PETSC_NGMRES', 'Newton_PETSC_ASPIN' or 'Newton_SOLVERLAB' nonlinear solvers are acceptable !!!" << endl;
220 _runLogFile->close();
221 throw CdmathException("!!! Error : only 'Newton_PETSC_LINESEARCH', 'Newton_PETSC_TRUSTREGION', 'Newton_PETSC_NGMRES', 'Newton_PETSC_ASPIN' or 'Newton_SOLVERLAB' nonlinear solvers are acceptable !!!" );
224 SNESCreate(PETSC_COMM_WORLD, &_snes);
225 SNESSetType( _snes, snestype);
226 SNESGetLineSearch( _snes, &_linesearch);
227 if(_nonLinearSolver == Newton_PETSC_LINESEARCH_BASIC)
228 SNESLineSearchSetType( _linesearch, SNESLINESEARCHBASIC );
229 else if(_nonLinearSolver == Newton_PETSC_LINESEARCH_BT)
230 SNESLineSearchSetType( _linesearch, SNESLINESEARCHBT );
231 else if(_nonLinearSolver == Newton_PETSC_LINESEARCH_SECANT)
232 SNESLineSearchSetType( _linesearch, SNESLINESEARCHL2 );
233 else if(_nonLinearSolver == Newton_PETSC_LINESEARCH_NLEQERR)
234 SNESLineSearchSetType( _linesearch, SNESLINESEARCHNLEQERR );
236 PetscViewerCreate(PETSC_COMM_WORLD,&_monitorLineSearch);
237 PetscViewerSetType(_monitorLineSearch, PETSCVIEWERASCII);
239 SNESSetTolerances(_snes,_precision_Newton,_precision_Newton,_precision_Newton,_maxNewtonIts,-1);
241 SNESSetFunction(_snes,_newtonVariation,computeSnesRHS,this);
242 SNESSetJacobian(_snes,_A,_A,computeSnesJacobian,this);
245 _initializedMemory=true;
246 save();//save initial data
249 bool ProblemFluid::initTimeStep(double dt){
251 return _dt>0;//No need to call MatShift as the linear system matrix is filled at each Newton iteration (unlike linear problem)
254 bool ProblemFluid::solveTimeStep(){
255 if(_timeScheme == Implicit && _nonLinearSolver != Newton_SOLVERLAB)
256 return solveNewtonPETSc();
258 return ProblemCoreFlows::solveTimeStep();
261 bool ProblemFluid::solveNewtonPETSc()
263 if( (_nbTimeStep-1)%_freqSave ==0)
264 SNESLineSearchSetDefaultMonitor(_linesearch, _monitorLineSearch);
266 SNESLineSearchSetDefaultMonitor(_linesearch, NULL);
268 SNESSolve(_snes,NULL,_conservativeVars);
270 SNESConvergedReason reason;
271 SNESGetConvergedReason(_snes,&reason);
273 if( (_nbTimeStep-1)%_freqSave ==0)
275 if(reason == SNES_CONVERGED_FNORM_ABS )
276 cout<<"Converged with absolute norm (absolute tolerance) less than "<<_precision_Newton<<", (||F|| < atol)"<<endl;
277 else if(reason == SNES_CONVERGED_FNORM_RELATIVE )
278 cout<<"Converged because residual has decreased by a factor less than "<<_precision_Newton<<", (||F|| < rtol*||F_initial||)"<<endl;
279 else if(reason == SNES_CONVERGED_SNORM_RELATIVE )
280 cout<<"Converged with relative norm (relative tolerance) less than "<<_precision_Newton<<", (|| delta x || < stol || x ||)"<<endl;
281 else if(reason == SNES_CONVERGED_ITS )
282 cout<<"SNESConvergedSkip() was chosen as the convergence test; thus the usual convergence criteria have not been checked and may or may not be satisfied"<<endl;
283 else if(reason == SNES_DIVERGED_LINEAR_SOLVE )
284 cout<<"Solving linear system failed"<<endl;
285 else if(reason == SNES_DIVERGED_LINE_SEARCH )
286 cout<<"Line search failed"<<endl;
287 else if(reason == SNES_DIVERGED_MAX_IT )
288 cout<<"Reached the maximum number of iterations"<<endl;
290 SNESGetIterationNumber(_snes, &_NEWTON_its);
291 PetscPrintf(PETSC_COMM_WORLD,"Number of SNES iterations = %D\n\n", _NEWTON_its);
293 *_runLogFile << "Nombre d'iterations de Newton "<< _NEWTON_its <<endl;
299 bool ProblemFluid::iterateTimeStep(bool &converged)
303 if(_NEWTON_its>0){//Pas besoin de computeTimeStep à la première iteration de Newton
305 computeTimeStep(stop);//This compute timestep is just to update the linear system. The time step was imposed before starting the Newton iterations
307 if(stop){//Le compute time step ne s'est pas bien passé
308 cout<<"ComputeTimeStep failed"<<endl;
313 computeNewtonVariation();
315 //converged=convergence des iterations
316 if(_timeScheme == Explicit)
318 else{//Implicit scheme
320 KSPGetIterationNumber(_ksp, &_PetscIts);
321 if( _MaxIterLinearSolver < _PetscIts)//save the maximum number of iterations needed during the newton scheme
322 _MaxIterLinearSolver = _PetscIts;
324 KSPConvergedReason reason;
325 KSPGetConvergedReason(_ksp,&reason);
327 if(reason<0)//solving the linear system failed
329 cout<<"Systeme lineaire : pas de convergence de Petsc. Raison PETSC numéro "<<reason<<endl;
330 cout<<"Nombre d'itérations effectuées "<< _PetscIts<<" nombre maximal Itérations autorisées "<<_maxPetscIts<<endl;
331 *_runLogFile<<"Systeme lineaire : pas de convergence de Petsc. Raison PETSC numéro "<<reason<<endl;
332 *_runLogFile<<"Nombre d'itérations effectuées "<< _PetscIts<<" nombre maximal Itérations autorisées "<<_maxPetscIts<<endl;
336 else{//solving the linear system succeeded
337 //Calcul de la variation relative Uk+1-Uk
341 for(int j=1; j<=_Nmailles; j++)
343 for(int k=0; k<_nVar; k++)
346 VecGetValues(_newtonVariation, 1, &I, &dx);
347 VecGetValues(_conservativeVars, 1, &I, &x);
348 if (fabs(x)*fabs(x)< _precision)
350 if(_erreur_rel < fabs(dx))
351 _erreur_rel = fabs(dx);
353 else if(_erreur_rel < fabs(dx/x))
354 _erreur_rel = fabs(dx/x);
358 converged = _erreur_rel <= _precision_Newton;
361 double relaxation=1;//Uk+1=Uk+relaxation*deltaU
363 VecAXPY(_conservativeVars, relaxation, _newtonVariation);
365 //mise a jour du champ primitif
368 if(_nbPhases==2 && fabs(_err_press_max) > _precision)//la pression n'a pu être calculée en diphasique à partir des variables conservatives
370 cout<<"Warning consToPrim: nbiter max atteint, erreur relative pression= "<<_err_press_max<<" precision= " <<_precision<<endl;
371 *_runLogFile<<"Warning consToPrim: nbiter max atteint, erreur relative pression= "<<_err_press_max<<" precision= " <<_precision<<endl;
377 cout<<"Vecteur Ukp1-Uk "<<endl;
378 VecView(_newtonVariation, PETSC_VIEWER_STDOUT_SELF);
379 cout << "Nouvel etat courant Uk de l'iteration Newton: " << endl;
380 VecView(_conservativeVars, PETSC_VIEWER_STDOUT_SELF);
383 if(_nbPhases==2 && (_nbTimeStep-1)%_freqSave ==0){
384 if(_minm1<-_precision || _minm2<-_precision)
386 cout<<"!!!!!!!!! WARNING masse partielle negative sur " << _nbMaillesNeg << " faces, min m1= "<< _minm1 << " , minm2= "<< _minm2<< " precision "<<_precision<<endl;
387 *_runLogFile<<"!!!!!!!!! WARNING masse partielle negative sur " << _nbMaillesNeg << " faces, min m1= "<< _minm1 << " , minm2= "<< _minm2<< " precision "<<_precision<<endl;
391 cout << "!!!!!!!!!!!!!!!!!!!!!!!! Complex eigenvalues on " << _nbVpCplx << " cells, max imag= " << _part_imag_max << endl;
392 *_runLogFile << "!!!!!!!!!!!!!!!!!!!!!!!! Complex eigenvalues on " << _nbVpCplx << " cells, max imag= " << _part_imag_max << endl;
399 double ProblemFluid::computeTimeStep(bool & stop){//dt is not known and will not contribute to the Newton scheme
401 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
403 cout << "ProblemFluid::computeTimeStep : Début calcul matrice implicite et second membre"<<endl;
406 if(_restartWithNewTimeScheme)//This is a change of time scheme during a simulation
408 if(_timeScheme == Implicit)
409 MatCreateSeqBAIJ(PETSC_COMM_SELF, _nVar, _nVar*_Nmailles, _nVar*_Nmailles, (1+_neibMaxNbCells), PETSC_NULL, &_A);
412 _restartWithNewTimeScheme=false;
414 if(_timeScheme == Implicit)
417 VecAssemblyBegin(_b);
420 std::vector< int > idCells(2);
421 PetscInt idm, idn, size = 1;
423 long nbFaces = _mesh.getNumberOfFaces();
428 for (int j=0; j<nbFaces;j++){
429 Fj = _mesh.getFace(j);
430 _isBoundary=Fj.isBorder();
431 idCells = Fj.getCellsId();
433 // If Fj is on the boundary
436 for(int k=0;k<Fj.getNumberOfCells();k++)//there will be at most two neighours in the case of an inner wall
438 // compute the normal vector corresponding to face j : from Ctemp1 outward
439 Ctemp1 = _mesh.getCell(idCells[k]);//origin of the normal vector
441 for(int l=0; l<Ctemp1.getNumberOfFaces(); l++)
442 {//we look for l the index of the face Fj for the cell Ctemp1
443 if (j == Ctemp1.getFacesId()[l])
445 for (int idim = 0; idim < _Ndim; ++idim)
446 _vec_normal[idim] = Ctemp1.getNormalVector(l,idim);
450 }else{ // _Ndim = 1, build normal vector (bug cdmath)
451 if(!_sectionFieldSet)
453 if (Fj.x()<Ctemp1.x())
466 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
468 cout << "face numero " << j << " cellule frontiere " << idCells[k] << " ; vecteur normal=(";
469 for(int p=0; p<_Ndim; p++)
470 cout << _vec_normal[p] << ",";
473 nameOfGroup = Fj.getGroupName();
474 _porosityi=_porosityField(idCells[k]);
475 _porosityj=_porosityi;
476 setBoundaryState(nameOfGroup,idCells[k],_vec_normal);
477 convectionState(idCells[k],0,true);
478 convectionMatrices();
479 diffusionStateAndMatrices(idCells[k], 0, true);
482 _inv_dxi = Fj.getMeasure()/Ctemp1.getMeasure();
484 _inv_dxi = 1/Ctemp1.getMeasure();
486 addConvectionToSecondMember(idCells[k],-1,true,nameOfGroup);
487 addDiffusionToSecondMember(idCells[k],-1,true);
488 addSourceTermToSecondMember(idCells[k],(_mesh.getCell(idCells[k])).getNumberOfFaces(),-1, -1,true,j,_inv_dxi*Ctemp1.getMeasure());
490 if(_timeScheme == Implicit){
491 for(int l=0; l<_nVar*_nVar;l++){
492 _AroeMinusImplicit[l] *= _inv_dxi;
493 _Diffusion[l] *=_inv_dxi*_inv_dxi;
496 jacobian(idCells[k],nameOfGroup,_vec_normal);
497 jacobianDiff(idCells[k],nameOfGroup);
498 if(_verbose && (_nbTimeStep-1)%_freqSave ==0){
499 cout << "Matrice Jacobienne CL convection:" << endl;
500 for(int p=0; p<_nVar; p++){
501 for(int q=0; q<_nVar; q++)
502 cout << _Jcb[p*_nVar+q] << "\t";
506 cout << "Matrice Jacobienne CL diffusion:" << endl;
507 for(int p=0; p<_nVar; p++){
508 for(int q=0; q<_nVar; q++)
509 cout << _JcbDiff[p*_nVar+q] << "\t";
515 //calcul et insertion de A^-*Jcb
516 Polynoms::matrixProduct(_AroeMinusImplicit, _nVar, _nVar, _Jcb, _nVar, _nVar, _a);
517 MatSetValuesBlocked(_A, size, &idm, size, &idm, _a, ADD_VALUES);
520 displayMatrix(_a, _nVar, "produit A^-*Jcb pour CL");
523 for(int k=0; k<_nVar*_nVar;k++){
524 _AroeMinusImplicit[k] *= -1;
526 MatSetValuesBlocked(_A, size, &idm, size, &idm, _AroeMinusImplicit, ADD_VALUES);
528 displayMatrix(_AroeMinusImplicit, _nVar,"-_AroeMinusImplicit: ");
530 //calcul et insertion de D*JcbDiff
531 Polynoms::matrixProduct(_Diffusion, _nVar, _nVar, _JcbDiff, _nVar, _nVar, _a);
532 MatSetValuesBlocked(_A, size, &idm, size, &idm, _a, ADD_VALUES);
533 for(int k=0; k<_nVar*_nVar;k++)
535 MatSetValuesBlocked(_A, size, &idm, size, &idm, _Diffusion, ADD_VALUES);
538 } else if (Fj.getNumberOfCells()==2 ){ // Fj is inside the domain and has two neighours (no junction)
539 // compute the normal vector corresponding to face j : from Ctemp1 to Ctemp2
540 Ctemp1 = _mesh.getCell(idCells[0]);//origin of the normal vector
541 Ctemp2 = _mesh.getCell(idCells[1]);
543 for(int l=0; l<Ctemp1.getNumberOfFaces(); l++){//we look for l the index of the face Fj for the cell Ctemp1
544 if (j == Ctemp1.getFacesId()[l]){
545 for (int idim = 0; idim < _Ndim; ++idim)
546 _vec_normal[idim] = Ctemp1.getNormalVector(l,idim);
550 }else{ // _Ndim = 1, build normal vector (bug cdmath)
551 if(!_sectionFieldSet)
553 if (Fj.x()<Ctemp1.x())
560 if(idCells[0]>idCells[1])
566 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
568 cout << "face numero " << j << " cellule gauche " << idCells[0] << " cellule droite " << idCells[1];
569 cout<<" Normal vector= ";
570 for (int idim = 0; idim < _Ndim; ++idim)
571 cout<<_vec_normal[idim]<<", ";
574 _porosityi=_porosityField(idCells[0]);
575 _porosityj=_porosityField(idCells[1]);
576 convectionState(idCells[0],idCells[1],false);
577 convectionMatrices();
578 diffusionStateAndMatrices(idCells[0], idCells[1], false);
580 // compute 1/dxi and 1/dxj
583 _inv_dxi = Fj.getMeasure()/Ctemp1.getMeasure();
584 _inv_dxj = Fj.getMeasure()/Ctemp2.getMeasure();
588 _inv_dxi = 1/Ctemp1.getMeasure();
589 _inv_dxj = 1/Ctemp2.getMeasure();
592 addConvectionToSecondMember(idCells[0],idCells[1], false);
593 addDiffusionToSecondMember( idCells[0],idCells[1], false);
594 addSourceTermToSecondMember(idCells[0], Ctemp1.getNumberOfFaces(),idCells[1], _mesh.getCell(idCells[1]).getNumberOfFaces(),false,j,_inv_dxi*Ctemp1.getMeasure());
596 if(_timeScheme == Implicit){
597 for(int k=0; k<_nVar*_nVar;k++)
599 _AroeMinusImplicit[k] *= _inv_dxi;
600 _Diffusion[k] *=_inv_dxi*2/(1/_inv_dxi+1/_inv_dxj);
604 //cout<<"idm= "<<idm<<"idn= "<<idn<<"nbvoismax= "<<_neibMaxNbCells<<endl;
605 MatSetValuesBlocked(_A, size, &idm, size, &idn, _AroeMinusImplicit, ADD_VALUES);
606 MatSetValuesBlocked(_A, size, &idm, size, &idn, _Diffusion, ADD_VALUES);
609 displayMatrix(_AroeMinusImplicit, _nVar, "+_AroeMinusImplicit: ");
610 displayMatrix(_Diffusion, _nVar, "+_Diffusion: ");
612 for(int k=0;k<_nVar*_nVar;k++){
613 _AroeMinusImplicit[k] *= -1;
616 MatSetValuesBlocked(_A, size, &idm, size, &idm, _AroeMinusImplicit, ADD_VALUES);
617 MatSetValuesBlocked(_A, size, &idm, size, &idm, _Diffusion, ADD_VALUES);
619 displayMatrix(_AroeMinusImplicit, _nVar, "-_AroeMinusImplicit: ");
620 displayMatrix(_Diffusion, _nVar, "-_Diffusion: ");
622 for(int k=0; k<_nVar*_nVar;k++)
624 _AroePlusImplicit[k] *= _inv_dxj;
625 _Diffusion[k] *=_inv_dxj/_inv_dxi;
627 MatSetValuesBlocked(_A, size, &idn, size, &idn, _AroePlusImplicit, ADD_VALUES);
628 MatSetValuesBlocked(_A, size, &idn, size, &idn, _Diffusion, ADD_VALUES);
630 displayMatrix(_AroePlusImplicit, _nVar, "+_AroePlusImplicit: ");
632 for(int k=0;k<_nVar*_nVar;k++){
633 _AroePlusImplicit[k] *= -1;
636 MatSetValuesBlocked(_A, size, &idn, size, &idm, _AroePlusImplicit, ADD_VALUES);
637 MatSetValuesBlocked(_A, size, &idn, size, &idm, _Diffusion, ADD_VALUES);
640 displayMatrix(_AroePlusImplicit, _nVar, "-_AroePlusImplicit: ");
643 else if( Fj.getNumberOfCells()>2 && _Ndim==1 ){//inner face with more than two neighbours
644 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
645 cout<<"lattice mesh junction at face "<<j<<" nbvoismax= "<<_neibMaxNbCells<<endl;
646 *_runLogFile<<"Warning: treatment of a junction node"<<endl;
648 if(!_sectionFieldSet)
650 _runLogFile->close();
651 throw CdmathException("ProblemFluid::ComputeTimeStep(): pipe network requires section field");
653 int largestSectionCellIndex=0;
654 for(int i=1;i<Fj.getNumberOfCells();i++){
655 if(_sectionField(idCells[i])>_sectionField(idCells[largestSectionCellIndex]))
656 largestSectionCellIndex=i;
658 idm = idCells[largestSectionCellIndex];
659 Ctemp1 = _mesh.getCell(idm);//origin of the normal vector
660 _porosityi=_porosityField(idm);
662 if (j==15)// bug cdmath (Fj.x() > _mesh.getCell(idm).x())
666 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
668 cout<<"Cell with largest section has index "<< largestSectionCellIndex <<" and number "<<idm<<endl;
669 cout << " ; vecteur normal=(";
670 for(int p=0; p<_Ndim; p++)
671 cout << _vec_normal[p] << ",";
674 for(int i=0;i<Fj.getNumberOfCells();i++){
675 if(i != largestSectionCellIndex){
677 Ctemp2 = _mesh.getCell(idn);
678 _porosityj=_porosityField(idn);
679 convectionState(idm,idn,false);
680 convectionMatrices();
681 diffusionStateAndMatrices(idm, idn,false);
683 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
684 cout<<"Neighbour index "<<i<<" cell number "<< idn<<endl;
686 _inv_dxi = _sectionField(idn)/_sectionField(idm)/Ctemp1.getMeasure();
687 _inv_dxj = 1/Ctemp2.getMeasure();
689 addConvectionToSecondMember(idm,idn, false);
690 _inv_dxi = sqrt(_sectionField(idn)/_sectionField(idm))/Ctemp1.getMeasure();
691 addDiffusionToSecondMember(idm,idn, false);
692 _inv_dxi = _sectionField(idn)/_sectionField(idm)/Ctemp1.getMeasure();
693 addSourceTermToSecondMember(idm, Ctemp1.getNumberOfFaces()*(Fj.getNumberOfCells()-1),idn, Ctemp2.getNumberOfFaces(),false,j,_inv_dxi*Ctemp1.getMeasure());
695 if(_timeScheme == Implicit){
696 for(int k=0; k<_nVar*_nVar;k++)
698 _AroeMinusImplicit[k] *= _inv_dxi;
699 _Diffusion[k] *=_inv_dxi*2/(1/_inv_dxi+1/_inv_dxj);//use sqrt as above
701 MatSetValuesBlocked(_A, size, &idm, size, &idn, _AroeMinusImplicit, ADD_VALUES);
702 MatSetValuesBlocked(_A, size, &idm, size, &idn, _Diffusion, ADD_VALUES);
705 displayMatrix(_AroeMinusImplicit, _nVar, "+_AroeMinusImplicit: ");
706 displayMatrix(_Diffusion, _nVar, "+_Diffusion: ");
708 for(int k=0;k<_nVar*_nVar;k++){
709 _AroeMinusImplicit[k] *= -1;
712 MatSetValuesBlocked(_A, size, &idm, size, &idm, _AroeMinusImplicit, ADD_VALUES);
713 MatSetValuesBlocked(_A, size, &idm, size, &idm, _Diffusion, ADD_VALUES);
715 displayMatrix(_AroeMinusImplicit, _nVar, "-_AroeMinusImplicit: ");
716 displayMatrix(_Diffusion, _nVar, "-_Diffusion: ");
718 for(int k=0; k<_nVar*_nVar;k++)
720 _AroePlusImplicit[k] *= _inv_dxj;
721 _Diffusion[k] *=_inv_dxj/_inv_dxi;//use sqrt as above
723 MatSetValuesBlocked(_A, size, &idn, size, &idn, _AroePlusImplicit, ADD_VALUES);
724 MatSetValuesBlocked(_A, size, &idn, size, &idn, _Diffusion, ADD_VALUES);
726 displayMatrix(_AroePlusImplicit, _nVar, "+_AroePlusImplicit: ");
728 for(int k=0;k<_nVar*_nVar;k++){
729 _AroePlusImplicit[k] *= -1;
732 MatSetValuesBlocked(_A, size, &idn, size, &idm, _AroePlusImplicit, ADD_VALUES);
733 MatSetValuesBlocked(_A, size, &idn, size, &idm, _Diffusion, ADD_VALUES);
736 displayMatrix(_AroePlusImplicit, _nVar, "-_AroePlusImplicit: ");
743 cout<< "Face j="<<j<< " is not a boundary face and has "<<Fj.getNumberOfCells()<< " neighbour cells"<<endl;
744 _runLogFile->close();
745 throw CdmathException("ProblemFluid::ComputeTimeStep(): incompatible number of cells around a face");
751 if(_timeScheme == Implicit){
752 for(int imaille = 0; imaille<_Nmailles; imaille++)
753 MatSetValuesBlocked(_A, size, &imaille, size, &imaille, _GravityImplicitationMatrix, ADD_VALUES);
755 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
756 displayMatrix(_GravityImplicitationMatrix,_nVar,"Gravity matrix:");
758 MatAssemblyBegin(_A, MAT_FINAL_ASSEMBLY);
759 MatAssemblyEnd(_A, MAT_FINAL_ASSEMBLY);
760 if(_verbose && (_nbTimeStep-1)%_freqSave ==0){
761 cout << "ProblemFluid::computeTimeStep : Fin calcul matrice implicite et second membre"<<endl;
762 cout << "ProblemFluid::computeTimeStep : Matrice implicite :"<<endl;
763 MatView(_A,PETSC_VIEWER_STDOUT_SELF);
764 cout << "ProblemFluid::computeTimeStep : Second membre :"<<endl;
765 VecView(_b, PETSC_VIEWER_STDOUT_WORLD);
773 if(_nbTimeStep+1<_cfl)
774 return (_nbTimeStep+1)*_minl/_maxvp;
777 return _cfl*_minl/_maxvp;
780 void ProblemFluid::computeNewtonVariation()
784 cout<<"Vecteur courant Uk "<<endl;
785 VecView(_conservativeVars,PETSC_VIEWER_STDOUT_SELF);
788 if(_timeScheme == Explicit)
790 VecCopy(_b,_newtonVariation);
791 VecScale(_newtonVariation, _dt);
792 if(_system && (_nbTimeStep-1)%_freqSave ==0)
794 cout<<"Vecteur _newtonVariation =_b*dt"<<endl;
795 VecView(_newtonVariation,PETSC_VIEWER_STDOUT_SELF);
803 cout << "Matrice du système linéaire avant contribution delta t" << endl;
804 MatView(_A,PETSC_VIEWER_STDOUT_SELF);
806 cout << "Second membre du système linéaire avant contribution delta t" << endl;
807 VecView(_b, PETSC_VIEWER_STDOUT_SELF);
810 MatAssemblyBegin(_A, MAT_FINAL_ASSEMBLY);
811 MatAssemblyEnd(_A, MAT_FINAL_ASSEMBLY);
813 VecAXPY(_b, 1/_dt, _old);
814 VecAXPY(_b, -1/_dt, _conservativeVars);
817 #if PETSC_VERSION_GREATER_3_5
818 KSPSetOperators(_ksp, _A, _A);
820 KSPSetOperators(_ksp, _A, _A,SAME_NONZERO_PATTERN);
825 cout << "Matrice du système linéaire après contribution delta t" << endl;
826 MatView(_A,PETSC_VIEWER_STDOUT_SELF);
828 cout << "Second membre du système linéaire après contribution delta t" << endl;
829 VecView(_b, PETSC_VIEWER_STDOUT_SELF);
834 KSPSetComputeEigenvalues(_ksp,PETSC_TRUE);
837 KSPSolve(_ksp, _b, _newtonVariation);
841 computeScaling(_maxvp);
843 VecAssemblyBegin(_vecScaling);
844 VecAssemblyBegin(_invVecScaling);
845 for(int imaille = 0; imaille<_Nmailles; imaille++)
848 VecSetValuesBlocked(_vecScaling,1 , &indice, _blockDiag, INSERT_VALUES);
849 VecSetValuesBlocked(_invVecScaling,1,&indice,_invBlockDiag, INSERT_VALUES);
851 VecAssemblyEnd(_vecScaling);
852 VecAssemblyEnd(_invVecScaling);
856 cout << "Matrice avant le preconditionneur des vecteurs propres " << endl;
857 MatView(_A,PETSC_VIEWER_STDOUT_SELF);
859 cout << "Second membre avant le preconditionneur des vecteurs propres " << endl;
860 VecView(_b, PETSC_VIEWER_STDOUT_SELF);
863 MatDiagonalScale(_A,_vecScaling,_invVecScaling);
866 cout << "Matrice apres le preconditionneur des vecteurs propres " << endl;
867 MatView(_A,PETSC_VIEWER_STDOUT_SELF);
870 VecCopy(_b,_bScaling);
871 VecPointwiseMult(_b,_vecScaling,_bScaling);
874 cout << "Produit du second membre par le preconditionneur bloc diagonal a gauche" << endl;
875 VecView(_b, PETSC_VIEWER_STDOUT_SELF);
879 KSPSolve(_ksp,_b, _bScaling);
880 VecPointwiseMult(_newtonVariation,_invVecScaling,_bScaling);
884 cout << "solution du systeme lineaire local:" << endl;
885 VecView(_newtonVariation, PETSC_VIEWER_STDOUT_SELF);
891 void ProblemFluid::computeNewtonRHS( Vec X, Vec F_X){//dt is known and will contribute to the right hand side of the Newton scheme
893 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
895 cout << "ProblemFluid::computeNewtonRHS : Début calcul second membre pour PETSc, _dt="<<_dt<<endl;
897 cout<<"Vecteur courant Uk "<<endl;
898 VecView(X,PETSC_VIEWER_STDOUT_SELF);
902 VecCopy(X,_conservativeVars);
905 VecAssemblyBegin(_b);
908 std::vector< int > idCells(2);
909 PetscInt idm, idn, size = 1;
911 long nbFaces = _mesh.getNumberOfFaces();
916 for (int j=0; j<nbFaces;j++){
917 Fj = _mesh.getFace(j);
918 _isBoundary=Fj.isBorder();
919 idCells = Fj.getCellsId();
921 // If Fj is on the boundary
924 for(int k=0;k<Fj.getNumberOfCells();k++)//there will be at most two neighours in the case of an inner wall
926 // compute the normal vector corresponding to face j : from Ctemp1 outward
927 Ctemp1 = _mesh.getCell(idCells[k]);//origin of the normal vector
929 for(int l=0; l<Ctemp1.getNumberOfFaces(); l++)
930 {//we look for l the index of the face Fj for the cell Ctemp1
931 if (j == Ctemp1.getFacesId()[l])
933 for (int idim = 0; idim < _Ndim; ++idim)
934 _vec_normal[idim] = Ctemp1.getNormalVector(l,idim);
938 }else{ // _Ndim = 1, build normal vector (bug cdmath)
939 if(!_sectionFieldSet)
941 if (Fj.x()<Ctemp1.x())
954 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
956 cout << "face numero " << j << " cellule frontiere " << idCells[k] << " ; vecteur normal=(";
957 for(int p=0; p<_Ndim; p++)
958 cout << _vec_normal[p] << ",";
961 nameOfGroup = Fj.getGroupName();
962 _porosityi=_porosityField(idCells[k]);
963 _porosityj=_porosityi;
964 setBoundaryState(nameOfGroup,idCells[k],_vec_normal);
965 convectionState(idCells[k],0,true);
966 convectionMatrices();
967 diffusionStateAndMatrices(idCells[k], 0, true);
970 _inv_dxi = Fj.getMeasure()/Ctemp1.getMeasure();
972 _inv_dxi = 1/Ctemp1.getMeasure();
974 addConvectionToSecondMember(idCells[k],-1,true,nameOfGroup);
975 addDiffusionToSecondMember(idCells[k],-1,true);
976 addSourceTermToSecondMember(idCells[k],(_mesh.getCell(idCells[k])).getNumberOfFaces(),-1, -1,true,j,_inv_dxi*Ctemp1.getMeasure());
978 } else if (Fj.getNumberOfCells()==2 ){ // Fj is inside the domain and has two neighours (no junction)
979 // compute the normal vector corresponding to face j : from Ctemp1 to Ctemp2
980 Ctemp1 = _mesh.getCell(idCells[0]);//origin of the normal vector
981 Ctemp2 = _mesh.getCell(idCells[1]);
983 for(int l=0; l<Ctemp1.getNumberOfFaces(); l++){//we look for l the index of the face Fj for the cell Ctemp1
984 if (j == Ctemp1.getFacesId()[l]){
985 for (int idim = 0; idim < _Ndim; ++idim)
986 _vec_normal[idim] = Ctemp1.getNormalVector(l,idim);
990 }else{ // _Ndim = 1, build normal vector (bug cdmath)
991 if(!_sectionFieldSet)
993 if (Fj.x()<Ctemp1.x())
1000 if(idCells[0]>idCells[1])
1001 _vec_normal[0] = -1;
1006 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1008 cout << "face numero " << j << " cellule gauche " << idCells[0] << " cellule droite " << idCells[1];
1009 cout<<" Normal vector= ";
1010 for (int idim = 0; idim < _Ndim; ++idim)
1011 cout<<_vec_normal[idim]<<", ";
1014 _porosityi=_porosityField(idCells[0]);
1015 _porosityj=_porosityField(idCells[1]);
1016 convectionState(idCells[0],idCells[1],false);
1017 convectionMatrices();
1018 diffusionStateAndMatrices(idCells[0], idCells[1], false);
1020 // compute 1/dxi and 1/dxj
1023 _inv_dxi = Fj.getMeasure()/Ctemp1.getMeasure();
1024 _inv_dxj = Fj.getMeasure()/Ctemp2.getMeasure();
1028 _inv_dxi = 1/Ctemp1.getMeasure();
1029 _inv_dxj = 1/Ctemp2.getMeasure();
1032 addConvectionToSecondMember(idCells[0],idCells[1], false);
1033 addDiffusionToSecondMember( idCells[0],idCells[1], false);
1034 addSourceTermToSecondMember(idCells[0], Ctemp1.getNumberOfFaces(),idCells[1], _mesh.getCell(idCells[1]).getNumberOfFaces(),false,j,_inv_dxi*Ctemp1.getMeasure());
1037 else if( Fj.getNumberOfCells()>2 && _Ndim==1 ){//inner face with more than two neighbours
1038 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1039 cout<<"lattice mesh junction at face "<<j<<" nbvoismax= "<<_neibMaxNbCells<<endl;
1040 *_runLogFile<<"Warning: treatment of a junction node"<<endl;
1042 if(!_sectionFieldSet)
1044 _runLogFile->close();
1045 throw CdmathException("ProblemFluid::ComputeTimeStep(): pipe network requires section field");
1047 int largestSectionCellIndex=0;
1048 for(int i=1;i<Fj.getNumberOfCells();i++){
1049 if(_sectionField(idCells[i])>_sectionField(idCells[largestSectionCellIndex]))
1050 largestSectionCellIndex=i;
1052 idm = idCells[largestSectionCellIndex];
1053 Ctemp1 = _mesh.getCell(idm);//origin of the normal vector
1054 _porosityi=_porosityField(idm);
1056 if (j==15)// bug cdmath (Fj.x() > _mesh.getCell(idm).x())
1059 _vec_normal[0] = -1;
1060 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1062 cout<<"Cell with largest section has index "<< largestSectionCellIndex <<" and number "<<idm<<endl;
1063 cout << " ; vecteur normal=(";
1064 for(int p=0; p<_Ndim; p++)
1065 cout << _vec_normal[p] << ",";
1066 cout << "). "<<endl;
1068 for(int i=0;i<Fj.getNumberOfCells();i++){
1069 if(i != largestSectionCellIndex){
1071 Ctemp2 = _mesh.getCell(idn);
1072 _porosityj=_porosityField(idn);
1073 convectionState(idm,idn,false);
1074 convectionMatrices();
1075 diffusionStateAndMatrices(idm, idn,false);
1077 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1078 cout<<"Neighbour index "<<i<<" cell number "<< idn<<endl;
1080 _inv_dxi = _sectionField(idn)/_sectionField(idm)/Ctemp1.getMeasure();
1081 _inv_dxj = 1/Ctemp2.getMeasure();
1083 addConvectionToSecondMember(idm,idn, false);
1084 _inv_dxi = sqrt(_sectionField(idn)/_sectionField(idm))/Ctemp1.getMeasure();
1085 addDiffusionToSecondMember(idm,idn, false);
1086 _inv_dxi = _sectionField(idn)/_sectionField(idm)/Ctemp1.getMeasure();
1087 addSourceTermToSecondMember(idm, Ctemp1.getNumberOfFaces()*(Fj.getNumberOfCells()-1),idn, Ctemp2.getNumberOfFaces(),false,j,_inv_dxi*Ctemp1.getMeasure());
1093 cout<< "Face j="<<j<< " is not a boundary face and has "<<Fj.getNumberOfCells()<< " neighbour cells"<<endl;
1094 _runLogFile->close();
1095 throw CdmathException("ProblemFluid::ComputeTimeStep(): incompatible number of cells around a face");
1100 //Contribution from delta t
1101 VecAXPY(_b, 1/_dt, _old);
1102 VecAXPY(_b, -1/_dt, _conservativeVars);
1108 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1110 cout << "ProblemFluid::computeNewtonRHS : Fin calcul second membre pour PETSc"<<endl;
1111 VecView(F_X, PETSC_VIEWER_STDOUT_WORLD);
1116 int ProblemFluid::computeSnesRHS(SNES snes, Vec X, Vec F_X, void *ctx)//Prototype imposé par PETSc
1118 ProblemFluid * myProblem = (ProblemFluid *) ctx;
1119 myProblem->computeNewtonRHS( X, F_X);
1124 void ProblemFluid::computeNewtonJacobian( Vec X, Mat A){//dt is known and will contribute to the jacobian matrix of the Newton scheme
1126 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1128 cout << "ProblemFluid::computeNewtonJacobian : Début calcul Jacobienne schéma Newton pour PETSc, _dt="<<_dt<<endl;
1132 if(_timeScheme == Explicit){
1133 MatCreateConstantDiagonal(PETSC_COMM_SELF, _nVar, _nVar, _nVar*_Nmailles, _nVar*_Nmailles,1./_dt, &A);
1138 VecCopy(X,_conservativeVars);
1140 std::vector< int > idCells(2);
1141 PetscInt idm, idn, size = 1;
1143 long nbFaces = _mesh.getNumberOfFaces();
1148 for (int j=0; j<nbFaces;j++){
1149 Fj = _mesh.getFace(j);
1150 _isBoundary=Fj.isBorder();
1151 idCells = Fj.getCellsId();
1153 // If Fj is on the boundary
1156 for(int k=0;k<Fj.getNumberOfCells();k++)//there will be at most two neighours in the case of an inner wall
1158 // compute the normal vector corresponding to face j : from Ctemp1 outward
1159 Ctemp1 = _mesh.getCell(idCells[k]);//origin of the normal vector
1161 for(int l=0; l<Ctemp1.getNumberOfFaces(); l++)
1162 {//we look for l the index of the face Fj for the cell Ctemp1
1163 if (j == Ctemp1.getFacesId()[l])
1165 for (int idim = 0; idim < _Ndim; ++idim)
1166 _vec_normal[idim] = Ctemp1.getNormalVector(l,idim);
1170 }else{ // _Ndim = 1, build normal vector (bug cdmath)
1171 if(!_sectionFieldSet)
1173 if (Fj.x()<Ctemp1.x())
1174 _vec_normal[0] = -1;
1181 _vec_normal[0] = -1;
1182 else//idCells[0]==31
1186 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1188 cout << "face numero " << j << " cellule frontiere " << idCells[k] << " ; vecteur normal=(";
1189 for(int p=0; p<_Ndim; p++)
1190 cout << _vec_normal[p] << ",";
1191 cout << "). "<<endl;
1193 nameOfGroup = Fj.getGroupName();
1194 _porosityi=_porosityField(idCells[k]);
1195 _porosityj=_porosityi;
1196 setBoundaryState(nameOfGroup,idCells[k],_vec_normal);
1197 convectionState(idCells[k],0,true);
1198 convectionMatrices();
1199 diffusionStateAndMatrices(idCells[k], 0, true);
1202 _inv_dxi = Fj.getMeasure()/Ctemp1.getMeasure();
1204 _inv_dxi = 1/Ctemp1.getMeasure();
1206 for(int l=0; l<_nVar*_nVar;l++){
1207 _AroeMinusImplicit[l] *= _inv_dxi;
1208 _Diffusion[l] *=_inv_dxi*_inv_dxi;
1211 jacobian(idCells[k],nameOfGroup,_vec_normal);
1212 jacobianDiff(idCells[k],nameOfGroup);
1213 if(_verbose && (_nbTimeStep-1)%_freqSave ==0){
1214 cout << "Matrice Jacobienne CL convection:" << endl;
1215 for(int p=0; p<_nVar; p++){
1216 for(int q=0; q<_nVar; q++)
1217 cout << _Jcb[p*_nVar+q] << "\t";
1221 cout << "Matrice Jacobienne CL diffusion:" << endl;
1222 for(int p=0; p<_nVar; p++){
1223 for(int q=0; q<_nVar; q++)
1224 cout << _JcbDiff[p*_nVar+q] << "\t";
1230 //calcul et insertion de A^-*Jcb
1231 Polynoms::matrixProduct(_AroeMinusImplicit, _nVar, _nVar, _Jcb, _nVar, _nVar, _a);
1232 MatSetValuesBlocked(A, size, &idm, size, &idm, _a, ADD_VALUES);
1235 displayMatrix(_a, _nVar, "produit A^-*Jcb pour CL");
1238 for(int k=0; k<_nVar*_nVar;k++){
1239 _AroeMinusImplicit[k] *= -1;
1241 MatSetValuesBlocked(A, size, &idm, size, &idm, _AroeMinusImplicit, ADD_VALUES);
1243 displayMatrix(_AroeMinusImplicit, _nVar,"-_AroeMinusImplicit: ");
1245 //calcul et insertion de D*JcbDiff
1246 Polynoms::matrixProduct(_Diffusion, _nVar, _nVar, _JcbDiff, _nVar, _nVar, _a);
1247 MatSetValuesBlocked(A, size, &idm, size, &idm, _a, ADD_VALUES);
1248 for(int k=0; k<_nVar*_nVar;k++)
1249 _Diffusion[k] *= -1;
1250 MatSetValuesBlocked(A, size, &idm, size, &idm, _Diffusion, ADD_VALUES);
1252 } else if (Fj.getNumberOfCells()==2 ){ // Fj is inside the domain and has two neighours (no junction)
1253 // compute the normal vector corresponding to face j : from Ctemp1 to Ctemp2
1254 Ctemp1 = _mesh.getCell(idCells[0]);//origin of the normal vector
1255 Ctemp2 = _mesh.getCell(idCells[1]);
1257 for(int l=0; l<Ctemp1.getNumberOfFaces(); l++){//we look for l the index of the face Fj for the cell Ctemp1
1258 if (j == Ctemp1.getFacesId()[l]){
1259 for (int idim = 0; idim < _Ndim; ++idim)
1260 _vec_normal[idim] = Ctemp1.getNormalVector(l,idim);
1264 }else{ // _Ndim = 1, build normal vector (bug cdmath)
1265 if(!_sectionFieldSet)
1267 if (Fj.x()<Ctemp1.x())
1268 _vec_normal[0] = -1;
1274 if(idCells[0]>idCells[1])
1275 _vec_normal[0] = -1;
1280 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1282 cout << "face numero " << j << " cellule gauche " << idCells[0] << " cellule droite " << idCells[1];
1283 cout<<" Normal vector= ";
1284 for (int idim = 0; idim < _Ndim; ++idim)
1285 cout<<_vec_normal[idim]<<", ";
1288 _porosityi=_porosityField(idCells[0]);
1289 _porosityj=_porosityField(idCells[1]);
1290 convectionState(idCells[0],idCells[1],false);
1291 convectionMatrices();
1292 diffusionStateAndMatrices(idCells[0], idCells[1], false);
1294 // compute 1/dxi and 1/dxj
1297 _inv_dxi = Fj.getMeasure()/Ctemp1.getMeasure();
1298 _inv_dxj = Fj.getMeasure()/Ctemp2.getMeasure();
1302 _inv_dxi = 1/Ctemp1.getMeasure();
1303 _inv_dxj = 1/Ctemp2.getMeasure();
1306 for(int k=0; k<_nVar*_nVar;k++)
1308 _AroeMinusImplicit[k] *= _inv_dxi;
1309 _Diffusion[k] *=_inv_dxi*2/(1/_inv_dxi+1/_inv_dxj);
1313 //cout<<"idm= "<<idm<<"idn= "<<idn<<"nbvoismax= "<<_neibMaxNbCells<<endl;
1314 MatSetValuesBlocked(A, size, &idm, size, &idn, _AroeMinusImplicit, ADD_VALUES);
1315 MatSetValuesBlocked(A, size, &idm, size, &idn, _Diffusion, ADD_VALUES);
1318 displayMatrix(_AroeMinusImplicit, _nVar, "+_AroeMinusImplicit: ");
1319 displayMatrix(_Diffusion, _nVar, "+_Diffusion: ");
1321 for(int k=0;k<_nVar*_nVar;k++){
1322 _AroeMinusImplicit[k] *= -1;
1323 _Diffusion[k] *= -1;
1325 MatSetValuesBlocked(A, size, &idm, size, &idm, _AroeMinusImplicit, ADD_VALUES);
1326 MatSetValuesBlocked(A, size, &idm, size, &idm, _Diffusion, ADD_VALUES);
1328 displayMatrix(_AroeMinusImplicit, _nVar, "-_AroeMinusImplicit: ");
1329 displayMatrix(_Diffusion, _nVar, "-_Diffusion: ");
1331 for(int k=0; k<_nVar*_nVar;k++)
1333 _AroePlusImplicit[k] *= _inv_dxj;
1334 _Diffusion[k] *=_inv_dxj/_inv_dxi;
1336 MatSetValuesBlocked(A, size, &idn, size, &idn, _AroePlusImplicit, ADD_VALUES);
1337 MatSetValuesBlocked(A, size, &idn, size, &idn, _Diffusion, ADD_VALUES);
1339 displayMatrix(_AroePlusImplicit, _nVar, "+_AroePlusImplicit: ");
1341 for(int k=0;k<_nVar*_nVar;k++){
1342 _AroePlusImplicit[k] *= -1;
1343 _Diffusion[k] *= -1;
1345 MatSetValuesBlocked(A, size, &idn, size, &idm, _AroePlusImplicit, ADD_VALUES);
1346 MatSetValuesBlocked(A, size, &idn, size, &idm, _Diffusion, ADD_VALUES);
1349 displayMatrix(_AroePlusImplicit, _nVar, "-_AroePlusImplicit: ");
1351 else if( Fj.getNumberOfCells()>2 && _Ndim==1 ){//inner face with more than two neighbours
1352 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1353 cout<<"lattice mesh junction at face "<<j<<" nbvoismax= "<<_neibMaxNbCells<<endl;
1354 *_runLogFile<<"Warning: treatment of a junction node"<<endl;
1356 if(!_sectionFieldSet)
1358 _runLogFile->close();
1359 throw CdmathException("ProblemFluid::ComputeTimeStep(): pipe network requires section field");
1361 int largestSectionCellIndex=0;
1362 for(int i=1;i<Fj.getNumberOfCells();i++){
1363 if(_sectionField(idCells[i])>_sectionField(idCells[largestSectionCellIndex]))
1364 largestSectionCellIndex=i;
1366 idm = idCells[largestSectionCellIndex];
1367 Ctemp1 = _mesh.getCell(idm);//origin of the normal vector
1368 _porosityi=_porosityField(idm);
1370 if (j==15)// bug cdmath (Fj.x() > _mesh.getCell(idm).x())
1373 _vec_normal[0] = -1;
1374 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1376 cout<<"Cell with largest section has index "<< largestSectionCellIndex <<" and number "<<idm<<endl;
1377 cout << " ; vecteur normal=(";
1378 for(int p=0; p<_Ndim; p++)
1379 cout << _vec_normal[p] << ",";
1380 cout << "). "<<endl;
1382 for(int i=0;i<Fj.getNumberOfCells();i++){
1383 if(i != largestSectionCellIndex){
1385 Ctemp2 = _mesh.getCell(idn);
1386 _porosityj=_porosityField(idn);
1387 convectionState(idm,idn,false);
1388 convectionMatrices();
1389 diffusionStateAndMatrices(idm, idn,false);
1391 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1392 cout<<"Neighbour index "<<i<<" cell number "<< idn<<endl;
1394 _inv_dxi = _sectionField(idn)/_sectionField(idm)/Ctemp1.getMeasure();
1395 _inv_dxj = 1/Ctemp2.getMeasure();
1397 for(int k=0; k<_nVar*_nVar;k++)
1399 _AroeMinusImplicit[k] *= _inv_dxi;
1400 _Diffusion[k] *=_inv_dxi*2/(1/_inv_dxi+1/_inv_dxj);//use sqrt as above
1402 MatSetValuesBlocked(A, size, &idm, size, &idn, _AroeMinusImplicit, ADD_VALUES);
1403 MatSetValuesBlocked(A, size, &idm, size, &idn, _Diffusion, ADD_VALUES);
1406 displayMatrix(_AroeMinusImplicit, _nVar, "+_AroeMinusImplicit: ");
1407 displayMatrix(_Diffusion, _nVar, "+_Diffusion: ");
1409 for(int k=0;k<_nVar*_nVar;k++){
1410 _AroeMinusImplicit[k] *= -1;
1411 _Diffusion[k] *= -1;
1413 MatSetValuesBlocked(A, size, &idm, size, &idm, _AroeMinusImplicit, ADD_VALUES);
1414 MatSetValuesBlocked(A, size, &idm, size, &idm, _Diffusion, ADD_VALUES);
1416 displayMatrix(_AroeMinusImplicit, _nVar, "-_AroeMinusImplicit: ");
1417 displayMatrix(_Diffusion, _nVar, "-_Diffusion: ");
1419 for(int k=0; k<_nVar*_nVar;k++)
1421 _AroePlusImplicit[k] *= _inv_dxj;
1422 _Diffusion[k] *=_inv_dxj/_inv_dxi;//use sqrt as above
1424 MatSetValuesBlocked(A, size, &idn, size, &idn, _AroePlusImplicit, ADD_VALUES);
1425 MatSetValuesBlocked(A, size, &idn, size, &idn, _Diffusion, ADD_VALUES);
1427 displayMatrix(_AroePlusImplicit, _nVar, "+_AroePlusImplicit: ");
1429 for(int k=0;k<_nVar*_nVar;k++){
1430 _AroePlusImplicit[k] *= -1;
1431 _Diffusion[k] *= -1;
1433 MatSetValuesBlocked(A, size, &idn, size, &idm, _AroePlusImplicit, ADD_VALUES);
1434 MatSetValuesBlocked(A, size, &idn, size, &idm, _Diffusion, ADD_VALUES);
1437 displayMatrix(_AroePlusImplicit, _nVar, "-_AroePlusImplicit: ");
1443 cout<< "Face j="<<j<< " is not a boundary face and has "<<Fj.getNumberOfCells()<< " neighbour cells"<<endl;
1444 _runLogFile->close();
1445 throw CdmathException("ProblemFluid::ComputeTimeStep(): incompatible number of cells around a face");
1450 for(int imaille = 0; imaille<_Nmailles; imaille++)
1451 MatSetValuesBlocked(A, size, &imaille, size, &imaille, _GravityImplicitationMatrix, ADD_VALUES);
1453 MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
1454 MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
1458 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1460 cout << "ProblemFluid::computeNewtonJacobian : Fin calcul Jacobienne schéma Newton pour PETSc"<<endl;
1461 MatView(A,PETSC_VIEWER_STDOUT_SELF);
1466 int ProblemFluid::computeSnesJacobian(SNES snes, Vec X, Mat A, Mat Aapprox, void *ctx)//Propotype imposé par PETSc
1468 ProblemFluid * myProblem = (ProblemFluid *) ctx;
1469 myProblem->computeNewtonJacobian( X, A);
1476 void ProblemFluid::validateTimeStep()
1480 cout<<" Vecteur Un"<<endl;
1481 VecView(_old, PETSC_VIEWER_STDOUT_WORLD);
1482 cout<<" Vecteur Un+1"<<endl;
1483 VecView(_conservativeVars, PETSC_VIEWER_STDOUT_WORLD);
1485 VecAXPY(_old, -1, _conservativeVars);//old contient old-courant
1487 //Calcul de la variation Un+1-Un
1492 for(int j=1; j<=_Nmailles; j++)
1494 for(int k=0; k<_nVar; k++)
1496 I = (j-1)*_nVar + k;
1497 VecGetValues(_old, 1, &I, &dx);
1498 VecGetValues(_conservativeVars, 1, &I, &x);
1499 if (fabs(x)< _precision)
1501 if(_erreur_rel < fabs(dx))
1502 _erreur_rel = fabs(dx);
1504 else if(_erreur_rel < fabs(dx/x))
1505 _erreur_rel = fabs(dx/x);
1509 _isStationary =_erreur_rel <_precision;
1511 VecCopy(_conservativeVars, _old);
1513 if(_verbose && (_nbTimeStep-1)%_freqSave ==0){
1514 if(!_usePrimitiveVarsInNewton)
1516 cout <<"Valeur propre locale max: " << _maxvp << endl;
1519 if(_nbPhases==2 && (_nbTimeStep-1)%_freqSave ==0){
1520 //Find minimum and maximum void fractions
1521 double alphamin=1e30;
1522 double alphamax=-1e30;
1523 double T, Tmax=-1e30;
1526 for(int j=0; j<_Nmailles; j++)
1528 VecGetValues(_primitiveVars, 1, &I, &x);//extract void fraction
1534 VecGetValues(_primitiveVars, 1, &J, &T);//extract void fraction
1539 cout<<"Alpha min = " << alphamin << ", Alpha max = " << alphamax<<", Tmax= "<<Tmax<<" K"<<endl;
1541 *_runLogFile<<"Alpha min = " << alphamin << " Alpha max = " << alphamax<<", Tmax= "<<Tmax<<" K"<<endl;
1546 if ((_nbTimeStep-1)%_freqSave ==0 || _isStationary || _time>=_timeMax || _nbTimeStep>=_maxNbOfTimeStep)
1550 void ProblemFluid::abortTimeStep(){
1554 void ProblemFluid::addConvectionToSecondMember
1556 const int &j, bool isBord, string groupname
1559 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1560 cout<<"ProblemFluid::addConvectionToSecondMember start"<<endl;
1562 //extraction des valeurs
1563 for(int k=0; k<_nVar; k++)
1564 _idm[k] = _nVar*i + k;
1565 VecGetValues(_conservativeVars, _nVar, _idm, _Ui);
1566 VecGetValues(_primitiveVars, _nVar, _idm, _Vi);
1569 for(int k=0; k<_nVar; k++)
1570 _idn[k] = _nVar*j + k;
1571 VecGetValues(_conservativeVars, _nVar, _idn, _Uj);
1572 VecGetValues(_primitiveVars, _nVar, _idn, _Vj);
1575 for(int k=0; k<_nVar; k++)
1577 VecGetValues(_Uext, _nVar, _idn, _Uj);
1578 consToPrim(_Uj, _Vj,_porosityj);
1583 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1585 cout << "addConvectionToSecondMember : état i= " << i << ", _Ui=" << endl;
1586 for(int q=0; q<_nVar; q++)
1587 cout << _Ui[q] << endl;
1589 cout << "addConvectionToSecondMember : état j= " << j << ", _Uj=" << endl;
1590 for(int q=0; q<_nVar; q++)
1591 cout << _Uj[q] << endl;
1594 if(_nonLinearFormulation!=reducedRoe){//VFRoe, Roe or VFFC
1595 Vector Ui(_nVar), Uj(_nVar), Vi(_nVar), Vj(_nVar), Fi(_nVar), Fj(_nVar),Fij(_nVar);
1596 for(int i1=0;i1<_nVar;i1++)
1603 Vector normale(_Ndim);
1604 for(int i1=0;i1<_Ndim;i1++)
1605 normale(i1)=_vec_normal[i1];
1607 Matrix signAroe(_nVar);
1608 for(int i1=0;i1<_nVar;i1++)
1609 for(int i2=0;i2<_nVar;i2++)
1610 signAroe(i1,i2)=_signAroe[i1*_nVar+i2];
1612 Matrix absAroe(_nVar);
1613 for(int i1=0;i1<_nVar;i1++)
1614 for(int i2=0;i2<_nVar;i2++)
1615 absAroe(i1,i2)=_absAroe[i1*_nVar+i2];
1617 if(_nonLinearFormulation==VFRoe)//VFRoe
1619 Vector Uij(_nVar),Vij(_nVar);
1620 double porosityij=sqrt(_porosityi*_porosityj);
1622 Uij=(Ui+Uj)/2+signAroe*(Ui-Uj)/2;
1624 for(int i1=0;i1<_nVar;i1++)
1627 consToPrim(_Uij, _Vij,porosityij);
1629 applyVFRoeLowMachCorrections(isBord, groupname);
1631 for(int i1=0;i1<_nVar;i1++)
1637 Fij=convectionFlux(Uij,Vij,normale,porosityij);
1639 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1641 cout<<"Etat interfacial conservatif "<<i<<", "<<j<< endl;
1643 cout<<"Etat interfacial primitif "<<i<<", "<<j<< endl;
1649 if(_spaceScheme==staggered && _nonLinearFormulation==VFFC)//special case
1650 Fij=staggeredVFFCFlux();
1653 Fi=convectionFlux(Ui,Vi,normale,_porosityi);
1654 Fj=convectionFlux(Uj,Vj,normale,_porosityj);
1655 if(_nonLinearFormulation==VFFC)//VFFC
1656 Fij=(Fi+Fj)/2+signAroe*(Fi-Fj)/2;
1657 else if(_nonLinearFormulation==Roe)//Roe
1658 Fij=(Fi+Fj)/2+absAroe*(Ui-Uj)/2;
1660 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1662 cout<<"Flux cellule "<<i<<" = "<< endl;
1664 cout<<"Flux cellule "<<j<<" = "<< endl;
1669 for(int i1=0;i1<_nVar;i1++)
1670 _phi[i1]=-Fij(i1)*_inv_dxi;
1671 VecSetValuesBlocked(_b, 1, _idm, _phi, ADD_VALUES);
1672 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1674 cout << "Ajout convection au 2nd membre pour les etats " << i << "," << j << endl;
1675 cout<<"Flux interfacial "<<i<<", "<<j<< endl;
1677 cout << "Contribution convection à " << i << ", -Fij(i1)*_inv_dxi= "<<endl;
1678 for(int q=0; q<_nVar; q++)
1679 cout << _phi[q] << endl;
1683 for(int i1=0;i1<_nVar;i1++)
1684 _phi[i1]*=-_inv_dxj/_inv_dxi;
1685 VecSetValuesBlocked(_b, 1, _idn, _phi, ADD_VALUES);
1686 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1688 cout << "Contribution convection à " << j << ", Fij(i1)*_inv_dxj= "<<endl;
1689 for(int q=0; q<_nVar; q++)
1690 cout << _phi[q] << endl;
1694 }else //_nonLinearFormulation==reducedRoe)
1696 for(int k=0; k<_nVar; k++)
1697 _temp[k]=(_Ui[k] - _Uj[k])*_inv_dxi;//(Ui-Uj)*_inv_dxi
1698 Polynoms::matrixProdVec(_AroeMinus, _nVar, _nVar, _temp, _phi);//phi=A^-(U_i-U_j)/dx
1699 VecSetValuesBlocked(_b, 1, _idm, _phi, ADD_VALUES);
1701 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1703 cout << "Ajout convection au 2nd membre pour les etats " << i << "," << j << endl;
1704 cout << "(Ui - Uj)*_inv_dxi= "<<endl;;
1705 for(int q=0; q<_nVar; q++)
1706 cout << _temp[q] << endl;
1708 cout << "Contribution convection à " << i << ", A^-*(Ui - Uj)*_inv_dxi= "<<endl;
1709 for(int q=0; q<_nVar; q++)
1710 cout << _phi[q] << endl;
1716 for(int k=0; k<_nVar; k++)
1717 _temp[k]*=_inv_dxj/_inv_dxi;//(Ui-Uj)*_inv_dxj
1718 Polynoms::matrixProdVec(_AroePlus, _nVar, _nVar, _temp, _phi);//phi=A^+(U_i-U_j)/dx
1719 VecSetValuesBlocked(_b, 1, _idn, _phi, ADD_VALUES);
1721 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1723 cout << "Contribution convection à " << j << ", A^+*(Ui - Uj)*_inv_dxi= "<<endl;
1724 for(int q=0; q<_nVar; q++)
1725 cout << _phi[q] << endl;
1730 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1732 cout<<"ProblemFluid::addConvectionToSecondMember end : matrices de décentrement cellules i= " << i << ", et j= " << j<< "):"<<endl;
1733 displayMatrix(_absAroe, _nVar,"Valeur absolue matrice de Roe");
1734 displayMatrix(_AroeMinus, _nVar,"Matrice _AroeMinus");
1735 displayMatrix(_AroePlus, _nVar,"Matrice _AroePlus");
1736 displayMatrix(_signAroe, _nVar,"Signe de la matrice de Roe");
1740 void ProblemFluid::addSourceTermToSecondMember
1741 ( const int i, int nbVoisinsi,
1742 const int j, int nbVoisinsj,
1743 bool isBord, int ij, double mesureFace)//To do : generalise to unstructured meshes
1745 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1746 cout<<"ProblemFluid::addSourceTerm cell i= "<<i<< " cell j= "<< j<< " isbord "<<isBord<<endl;
1749 for(int k=1; k<_nVar;k++)
1750 _idm[k] = _idm[k-1] + 1;
1751 VecGetValues(_conservativeVars, _nVar, _idm, _Ui);
1752 VecGetValues(_primitiveVars, _nVar, _idm, _Vi);
1753 sourceVector(_Si,_Ui,_Vi,i);
1755 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1757 cout << "Terme source S(Ui), i= " << i<<endl;
1758 for(int q=0; q<_nVar; q++)
1759 cout << _Si[q] << endl;
1763 for(int k=0; k<_nVar; k++)
1764 _idn[k] = _nVar*j + k;
1765 VecGetValues(_conservativeVars, _nVar, _idn, _Uj);
1766 VecGetValues(_primitiveVars, _nVar, _idn, _Vj);
1767 sourceVector(_Sj,_Uj,_Vj,j);
1770 for(int k=0; k<_nVar; k++)
1772 VecGetValues(_Uext, _nVar, _idn, _Uj);
1773 consToPrim(_Uj, _Vj,_porosityj);
1774 sourceVector(_Sj,_Uj,_Vj,i);
1776 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1779 cout << "Terme source S(Uj), j= " << j<<endl;
1781 cout << "Terme source S(Uj), cellule fantôme "<<endl;
1782 for(int q=0; q<_nVar; q++)
1783 cout << _Sj[q] << endl;
1787 //Compute pressure loss vector
1789 if(_pressureLossFieldSet){
1790 K=_pressureLossField(ij);
1791 pressureLossVector(_pressureLossVector, K,_Ui, _Vi, _Uj, _Vj);
1795 for(int k=0; k<_nVar;k++)
1796 _pressureLossVector[k]=0;
1798 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1800 cout<<"interface i= "<<i<<", j= "<<j<<", ij="<<ij<<", K="<<K<<endl;
1801 for(int k=0; k<_nVar;k++)
1802 cout<< _pressureLossVector[k]<<", ";
1805 //Contribution of the porosityField gradient:
1807 porosityGradientSourceVector();
1809 for(int k=0; k<_nVar;k++)
1810 _porosityGradientSourceVector[k]=0;
1813 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1816 cout<<"interface i= "<<i<<", j= "<<j<<", ij="<<ij<<", dxi= "<<1/_inv_dxi<<", dxj= "<<1/_inv_dxj<<endl;
1818 cout<<"interface frontière i= "<<i<<", ij="<<ij<<", dxi= "<<1/_inv_dxi<<endl;
1819 cout<<"Gradient de porosite à l'interface"<<endl;
1820 for(int k=0; k<_nVar;k++)
1821 cout<< _porosityGradientSourceVector[k]<<", ";
1826 if(_wellBalancedCorrection){
1827 for(int k=0; k<_nVar;k++)
1828 _phi[k]=(_Si[k]+_Sj[k])/2+_pressureLossVector[k]+_porosityGradientSourceVector[k];
1829 Polynoms::matrixProdVec(_signAroe, _nVar, _nVar, _phi, _l);
1830 for(int k=0; k<_nVar;k++){
1831 _Si[k]=(_phi[k]-_l[k])*mesureFace/_perimeters(i);///nbVoisinsi;
1832 _Sj[k]=(_phi[k]+_l[k])*mesureFace/_perimeters(j);///nbVoisinsj;
1834 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1836 cout << "Contribution au terme source Si de la cellule i= " << i<<" venant (après décentrement) de la face (i,j), j="<<j<<endl;
1837 for(int q=0; q<_nVar; q++)
1838 cout << _Si[q] << endl;
1839 cout << "Contribution au terme source Sj de la cellule j= " << j<<" venant (après décentrement) de la face (i,j), i="<<i<<endl;
1840 for(int q=0; q<_nVar; q++)
1841 cout << _Sj[q] << endl;
1843 cout<<"ratio surface sur volume i = "<<mesureFace/_perimeters(i)<<" perimeter = "<< _perimeters(i)<<endl;
1844 cout<<"ratio surface sur volume j = "<<mesureFace/_perimeters(j)<<" perimeter = "<< _perimeters(j)<<endl;
1849 for(int k=0; k<_nVar;k++){
1850 _Si[k]=_Si[k]/nbVoisinsi+_pressureLossVector[k]/2+_porosityGradientSourceVector[k]/2;//mesureFace/_perimeters(i)
1851 _Sj[k]=_Sj[k]/nbVoisinsj+_pressureLossVector[k]/2+_porosityGradientSourceVector[k]/2;//mesureFace/_perimeters(j)
1853 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1855 cout << "Contribution au terme source Si de la cellule i = " << i<<" venant de la face (i,j), j="<<j<<endl;
1856 for(int q=0; q<_nVar; q++)
1857 cout << _Si[q] << endl;
1858 cout << "Contribution au terme source Sj de la cellule j = " << j<<" venant de la face (i,j), i="<<i <<endl;
1859 for(int q=0; q<_nVar; q++)
1860 cout << _Sj[q] << endl;
1865 VecSetValuesBlocked(_b, 1, _idn, _Sj, ADD_VALUES);
1867 if(_wellBalancedCorrection){
1868 for(int k=0; k<_nVar;k++)
1869 _phi[k]=(_Si[k]+_Sj[k])/2+_pressureLossVector[k]+_porosityGradientSourceVector[k];
1870 Polynoms::matrixProdVec(_signAroe, _nVar, _nVar, _phi, _l);
1871 for(int k=0; k<_nVar;k++)
1872 _Si[k]=(_phi[k]-_l[k])*mesureFace/_perimeters(i);///nbVoisinsi;
1873 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1875 cout << "Contribution au terme source Si de la cellule i= " << i<<" venant (après décentrement) de la face (i,bord)"<<endl;
1876 for(int q=0; q<_nVar; q++)
1877 cout << _Si[q] << endl;
1878 cout<<"ratio surface sur volume i ="<<mesureFace/_perimeters(i)<<" perimeter = "<< _perimeters(i)<<endl;
1884 for(int k=0; k<_nVar;k++)
1885 _Si[k]=_Si[k]/nbVoisinsi+_pressureLossVector[k]/2+_porosityGradientSourceVector[k]/2;//mesureFace/_perimeters(i);//
1886 if (_verbose && (_nbTimeStep-1)%_freqSave ==0)
1888 cout << "Contribution au terme source Si de la cellule i = " << i<<" venant de la face (i,bord) "<<endl;
1889 for(int q=0; q<_nVar; q++)
1890 cout << _Si[q] << endl;
1896 VecSetValuesBlocked(_b, 1, _idm, _Si, ADD_VALUES);
1898 if(_verbose && (_nbTimeStep-1)%_freqSave ==0 && _wellBalancedCorrection)
1899 displayMatrix( _signAroe,_nVar,"Signe matrice de Roe");
1902 void ProblemFluid::updatePrimitives()
1904 VecAssemblyBegin(_primitiveVars);
1905 for(int i=1; i<=_Nmailles; i++)
1907 _idm[0] = _nVar*( (i-1));
1908 for(int k=1; k<_nVar; k++)
1909 _idm[k] = _idm[k-1] + 1;
1911 VecGetValues(_conservativeVars, _nVar, _idm, _Ui);
1912 consToPrim(_Ui,_Vi,_porosityField(i-1));
1913 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1915 cout << "ProblemFluid::updatePrimitives() cell " << i-1 << endl;
1917 for(int q=0; q<_nVar; q++)
1918 cout << _Ui[q] << "\t";
1921 for(int q=0; q<_nVar; q++)
1922 cout << _Vi[q] << "\t";
1926 if(_nbPhases==2 && _Psat>-1e30){//Cas simulation flashing
1928 VecGetValues(_primitiveVars, 1, _idm+1, &pressure);
1929 _dp_over_dt(i-1)=(_Vi[1]-pressure)/_dt;//pn+1-pn
1932 VecSetValuesBlocked(_primitiveVars, 1, _idm, _Vi, INSERT_VALUES);
1934 VecAssemblyEnd(_primitiveVars);
1938 cout << "Nouvelles variables primitives : " << endl;
1939 VecView(_primitiveVars, PETSC_VIEWER_STDOUT_WORLD);
1944 void ProblemFluid::updateConservatives()
1946 VecAssemblyBegin(_conservativeVars);
1947 for(int i=1; i<=_Nmailles; i++)
1949 _idm[0] = _nVar*( (i-1));
1950 for(int k=1; k<_nVar; k++)
1951 _idm[k] = _idm[k-1] + 1;
1953 VecGetValues(_primitiveVars, _nVar, _idm, _Vi);
1955 primToCons(_Vi,0,_Ui,0);
1957 VecSetValuesBlocked(_conservativeVars, 1, _idm, _Ui, INSERT_VALUES);
1959 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
1961 cout << "ProblemFluid::updateConservatives() cell " << i-1 << endl;
1963 for(int q=0; q<_nVar; q++)
1964 cout << _Vi[q] << "\t";
1967 for(int q=0; q<_nVar; q++)
1968 cout << _Ui[q] << "\t";
1972 VecAssemblyEnd(_conservativeVars);
1976 cout << "Nouvelles variables conservatives : " << endl;
1977 VecView(_conservativeVars, PETSC_VIEWER_STDOUT_WORLD);
1982 vector< complex<double> > ProblemFluid::getRacines(vector< double > pol_car){
1983 int degre_polynom = pol_car.size()-1;
1985 vector< complex< double > > valeurs_propres (degre_polynom);
1986 vector< double > zeror(degre_polynom);
1987 vector< double > zeroi(degre_polynom);
1988 for(int j=0; j<(degre_polynom+1)/2; j++){//coefficients in order of decreasing powers for rpoly
1990 pol_car[j] =pol_car[degre_polynom-j];
1991 pol_car[degre_polynom-j]=tmp;
1994 //Calcul des racines du polynome
1995 roots_polynoms roots;
1996 int size_vp = roots.rpoly(&pol_car[0],degre_polynom,&zeror[0],&zeroi[0]);
1998 //On ordonne les valeurs propres
1999 if(zeror[1]<zeror[0])
2009 if(size_vp == degre_polynom) {
2010 for(int ct =0; ct<degre_polynom; ct++)
2011 valeurs_propres[ct] = complex<double> (zeror[ct],zeroi[ct]); //vp non triviales
2014 cout << " Pb, found only " << size_vp << " eigenvalues over " << degre_polynom << endl;
2015 *_runLogFile << " Pb, found only " << size_vp << " eigenvalues over " << degre_polynom << endl;
2016 cout<<"Coefficients polynome caracteristique: "<<endl;
2017 for(int ct =0; ct<degre_polynom+1; ct++)
2018 cout<<pol_car[ct]<< " , " <<endl;
2020 *_runLogFile<<"getRacines computation failed"<<endl;
2021 _runLogFile->close();
2022 throw CdmathException("getRacines computation failed");
2025 return valeurs_propres;
2028 void ProblemFluid::AbsMatriceRoe(vector< complex<double> > valeurs_propres_dist)
2030 int nbVp_dist=valeurs_propres_dist.size();
2031 vector< complex< double > > y (nbVp_dist,0);
2032 for( int i=0 ; i<nbVp_dist ; i++)
2033 y[i] = Polynoms::abs_generalise(valeurs_propres_dist[i]);
2034 Polynoms::abs_par_interp_directe(nbVp_dist,valeurs_propres_dist, _Aroe, _nVar,_precision, _absAroe,y);
2035 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
2037 cout<< endl<<"ProblemFluid::AbsMatriceRoe: Valeurs propres :" << nbVp_dist<<endl;
2038 for(int ct =0; ct<nbVp_dist; ct++)
2039 cout<< "("<<valeurs_propres_dist[ct].real()<< ", " <<valeurs_propres_dist[ct].imag() <<") ";
2041 cout<<"ProblemFluid::AbsMatriceRoe: Valeurs à atteindre pour l'interpolation"<<endl;
2042 for(int ct =0; ct<nbVp_dist; ct++)
2043 cout<< "("<<y[ct].real()<< ", " <<y[ct].imag() <<") ";
2045 displayMatrix(_absAroe,_nVar,"Valeur absolue de la matrice de Roe");
2049 void ProblemFluid::SigneMatriceRoe(vector< complex<double> > valeurs_propres_dist)
2051 int nbVp_dist=valeurs_propres_dist.size();
2052 vector< complex< double > > y (nbVp_dist,0);
2053 for( int i=0 ; i<nbVp_dist ; i++)
2055 if(valeurs_propres_dist[i].real()>0)
2057 else if(valeurs_propres_dist[i].real()<0)
2063 Polynoms::abs_par_interp_directe(nbVp_dist,valeurs_propres_dist, _Aroe, _nVar,_precision, _signAroe,y);
2064 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
2066 cout<< endl<<"ProblemFluid::SigneMatriceRoe: Valeurs propres :" << nbVp_dist<<endl;
2067 for(int ct =0; ct<nbVp_dist; ct++)
2068 cout<< "("<<valeurs_propres_dist[ct].real()<< ", " <<valeurs_propres_dist[ct].imag() <<") ";
2070 cout<<"ProblemFluid::SigneMatriceRoe: Valeurs à atteindre pour l'interpolation"<<endl;
2071 for(int ct =0; ct<nbVp_dist; ct++)
2072 cout<< "("<<y[ct].real()<< ", " <<y[ct].imag() <<") ";
2074 displayMatrix(_signAroe,_nVar,"Signe matrice de Roe");
2077 void ProblemFluid::InvMatriceRoe(vector< complex<double> > valeurs_propres_dist)
2079 int nbVp_dist=valeurs_propres_dist.size();
2080 vector< complex< double > > y (nbVp_dist,0);
2082 for( int i=0 ; i<nbVp_dist ; i++)
2084 if(Polynoms::module(valeurs_propres_dist[i])>_precision)
2085 y[i] = 1./valeurs_propres_dist[i];
2087 y[i] = 1./_precision;
2089 Polynoms::abs_par_interp_directe(nbVp_dist,valeurs_propres_dist, _Aroe, _nVar,_precision, _invAroe,y);
2090 if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
2092 cout<< endl<<"ProblemFluid::InvMatriceRoe : Valeurs propres :" << nbVp_dist<<endl;
2093 for(int ct =0; ct<nbVp_dist; ct++)
2094 cout<< "("<<valeurs_propres_dist[ct].real()<< ", " <<valeurs_propres_dist[ct].imag() <<") ";
2096 cout<<"ProblemFluid::InvMatriceRoe : Valeurs à atteindre pour l'interpolation"<<endl;
2097 for(int ct =0; ct<nbVp_dist; ct++)
2098 cout<< "("<<y[ct].real()<< ", " <<y[ct].imag() <<") ";
2100 displayMatrix(_invAroe,_nVar,"Inverse matrice de Roe");
2104 Field ProblemFluid::getConservativeField() const
2106 if(!_initializedMemory)
2108 _runLogFile->close();
2109 throw CdmathException("ProblemFluid::getConservativeField call initialize() first");
2114 Field ProblemFluid::getPrimitiveField() const
2116 if(!_initializedMemory)
2118 _runLogFile->close();
2119 throw CdmathException("ProblemFluid::getPrimitiveField call initialize() first");
2124 void ProblemFluid::terminate(){
2127 delete[] _Diffusion;
2128 delete[] _GravityImplicitationMatrix;
2129 delete[] _AroeMinus;
2134 delete[] _AroeImplicit;
2135 delete[] _AroeMinusImplicit;
2136 delete[] _AroePlusImplicit;
2137 delete[] _absAroeImplicit;
2142 delete[] _primToConsJacoMat;
2149 delete[] _externalStates;
2152 delete[] _vec_normal;
2157 if(_nonLinearFormulation==VFRoe){
2163 delete[] _pressureLossVector;
2164 delete[] _porosityGradientSourceVector;
2167 delete[] _blockDiag;
2168 delete[] _invBlockDiag;
2170 VecDestroy(&_vecScaling);
2171 VecDestroy(&_invVecScaling);
2172 VecDestroy(&_bScaling);
2175 VecDestroy(&_conservativeVars);
2176 VecDestroy(&_newtonVariation);
2178 VecDestroy(&_primitiveVars);
2181 VecDestroy(&_Uextdiff);
2185 for(int i=0;i<_nbPhases;i++)
2188 // Destruction du solveur de Newton de PETSc
2189 if(_timeScheme == Implicit && _nonLinearSolver != Newton_SOLVERLAB)
2190 SNESDestroy(&_snes);
2194 ProblemFluid::getInputFieldsNames()
2196 vector<string> result(1);
2198 result[0]="HeatPower";
2199 result[1]="Porosity";
2200 result[2]="PressureLoss";
2201 result[3]="Section";
2207 ProblemFluid::setInputField(const string& nameField, Field& inputField )
2209 if(nameField=="Porosity" || nameField=="POROSITY" || nameField=="Porosité" || nameField=="POROSITE")
2210 return setPorosityField( inputField) ;
2211 else if(nameField=="HeatPower" || nameField=="HEATPOWER" || nameField=="PuissanceThermique" || nameField=="PUISSANCETHERMIQUE" )
2212 return setHeatPowerField( inputField );
2213 else if(nameField=="PressureLoss" || nameField=="PRESSURELOSS" || nameField=="PerteDeCharge" || nameField=="PPERTEDECHARGE")
2214 return setPressureLossField( inputField) ;
2215 else if(nameField=="Section" || nameField=="SECTION" )
2216 return setSectionField( inputField );
2219 cout<<"Error : Field name "<< nameField << " is not an input field name, call getInputFieldsNames first" << endl;
2220 throw CdmathException("SinglePhase::setInputField error : Unknown Field name");
2225 ProblemFluid::setPorosityField(string fileName, string fieldName){
2226 if(!_initialDataSet)
2227 throw CdmathException("!!!!!!!! ProblemFluid::setPorosityField set initial field first");
2229 _porosityField=Field(fileName, CELLS,fieldName);
2230 _porosityField.getMesh().checkFastEquivalWith(_mesh);
2231 _porosityFieldSet=true;
2235 ProblemFluid::setPressureLossField(Field PressureLoss){
2236 if(!_initialDataSet)
2237 throw CdmathException("!!!!!!!! ProblemFluid::setPressureLossField set initial field first");
2239 PressureLoss.getMesh().checkFastEquivalWith(_mesh);
2240 _pressureLossField=PressureLoss;
2241 _pressureLossFieldSet=true;
2245 ProblemFluid::setPressureLossField(string fileName, string fieldName){
2246 if(!_initialDataSet)
2247 throw CdmathException("!!!!!!!! ProblemFluid::setPressureLossField set initial field first");
2249 _pressureLossField=Field(fileName, FACES,fieldName);
2250 _pressureLossField.getMesh().checkFastEquivalWith(_mesh);
2251 _pressureLossFieldSet=true;
2255 ProblemFluid::setSectionField(Field sectionField){
2256 if(!_initialDataSet)
2257 throw CdmathException("!!!!!!!! ProblemFluid::setSectionField set initial field first");
2259 sectionField.getMesh().checkFastEquivalWith(_mesh);
2260 _sectionField=sectionField;
2261 _sectionFieldSet=true;
2265 ProblemFluid::setSectionField(string fileName, string fieldName){
2266 if(!_initialDataSet)
2267 throw CdmathException("!!!!!!!! ProblemFluid::setSectionField set initial field first");
2269 _sectionField=Field(fileName, CELLS,fieldName);
2270 _sectionField.getMesh().checkFastEquivalWith(_mesh);
2271 _sectionFieldSet=true;
2275 ProblemFluid::setPorosityField(Field Porosity){
2276 if(!_initialDataSet)
2277 throw CdmathException("!!!!!!!! ProblemFluid::setPorosityField set initial field first");
2279 Porosity.getMesh().checkFastEquivalWith(_mesh);
2280 _porosityField=Porosity;
2281 _porosityFieldSet=true;