Salome HOME
Prepare structures for parallel simulation
authormichael <michael@localhost.localdomain>
Fri, 5 Nov 2021 22:16:32 +0000 (23:16 +0100)
committermichael <michael@localhost.localdomain>
Fri, 5 Nov 2021 22:16:32 +0000 (23:16 +0100)
12 files changed:
CoreFlows/Models/inc/DiffusionEquation.hxx
CoreFlows/Models/inc/LinearElasticityModel.hxx
CoreFlows/Models/inc/ProblemCoreFlows.hxx
CoreFlows/Models/inc/ProblemFluid.hxx
CoreFlows/Models/inc/StationaryDiffusionEquation.hxx
CoreFlows/Models/inc/TransportEquation.hxx
CoreFlows/Models/src/DiffusionEquation.cxx
CoreFlows/Models/src/LinearElasticityModel.cxx
CoreFlows/Models/src/ProblemCoreFlows.cxx
CoreFlows/Models/src/ProblemFluid.cxx
CoreFlows/Models/src/StationaryDiffusionEquation.cxx
CoreFlows/Models/src/TransportEquation.cxx

index 7b74369543b4bd9ef71b6639e484dc4bba9e3382..2a3110b1fc563aa0eefa7bd645985e5536fb439c 100755 (executable)
@@ -5,7 +5,7 @@
  * \version 1.0
  * \date 24 March 2015
  * \brief Heat diffusion equation
- * dT/dt - \lambda\Delta T = \Phi + \lambda_{sf} (T_{fluid}-T)
+ * rho*cp*dT/dt - \lambda\Delta T = \Phi + \lambda_{sf} (T_{fluid}-T)
  * Dirichlet (imposed temperature) or Neumann (imposed normal flux) boundary conditions.
  * */
 //============================================================================
@@ -13,7 +13,7 @@
 /*! \class DiffusionEquation DiffusionEquation.hxx "DiffusionEquation.hxx"
  *  \brief Scalar heat equation for the Uranium rods temperature
  *  \details see \ref DiffusionEqPage for more details
- * dT/dt - \lambda\Delta T = \Phi + \lambda_{sf} (T_{fluid}-T)
+ * rho*cp*dT/dt - \lambda\Delta T = \Phi + \lambda_{sf} (T_{fluid}-T)
  */
 #ifndef DiffusionEquation_HXX_
 #define DiffusionEquation_HXX_
@@ -52,7 +52,7 @@ public :
                         * \param [in] double : solid conductivity
                         *  */
 
-       DiffusionEquation( int dim,bool FECalculation=true,double rho=10000,double cp=300,double lambda=5);
+       DiffusionEquation( int dim,bool FECalculation=true,double rho=10000,double cp=300,double lambda=5, MPI_Comm comm = MPI_COMM_WORLD);
 
        //Gestion du calcul
        void initialize();
@@ -121,9 +121,16 @@ public :
                return _fluidTemperatureField;
        }
 
+    /*********** Generic functions for finite element method ***********/
+    static Vector gradientNodal(Matrix M, vector< double > v);//gradient of nodal shape functions
+    static int fact(int n);
+    static int unknownNodeIndex(int globalIndex, std::vector< int > dirichletNodes);
+    static int globalNodeIndex(int unknownIndex, std::vector< int > dirichletNodes);
+
 protected :
        double computeDiffusionMatrix(bool & stop);
        double computeDiffusionMatrixFV(bool & stop);
+       double computeDiffusionMatrixFE(bool & stop);
        double computeRHS(bool & stop);
 
        Field _fluidTemperatureField;
@@ -137,21 +144,12 @@ protected :
        double _dt_diffusion, _dt_src;
     
     /************ Data for FE calculation *************/
-    bool _FECalculation;
-       int _neibMaxNbNodes;/* maximum number of nodes around a node */
        int _NunknownNodes;/* number of unknown nodes for FE calculation */
        int _NboundaryNodes;/* total number of boundary nodes */
        int _NdirichletNodes;/* number of boundary nodes with Dirichlet BC for FE calculation */
     std::vector< int > _boundaryNodeIds;/* List of boundary nodes */
     std::vector< int > _dirichletNodeIds;/* List of boundary nodes with Dirichlet BC */
 
-    /*********** Functions for finite element method ***********/
-    static Vector gradientNodal(Matrix M, vector< double > v);//gradient of nodal shape functions
-       double computeDiffusionMatrixFE(bool & stop);
-    static int fact(int n);
-    static int unknownNodeIndex(int globalIndex, std::vector< int > dirichletNodes);
-    static int globalNodeIndex(int unknownIndex, std::vector< int > dirichletNodes);
-
        TimeScheme _timeScheme;
        map<string, LimitFieldDiffusion> _limitField;
 
index bdaee35ba4e0138168ee4c26a089d1599fcb13df..da3fcb8182f3d7d7a8f13c566c5c68ec600d2f85 100755 (executable)
@@ -55,7 +55,7 @@ public :
                         * \param [in] double : second  Lamé coefficient
                         *  */
 
-       LinearElasticityModel( int dim, bool FECalculation=true, double rho, double lambda, double mu);
+       LinearElasticityModel( int dim, bool FECalculation=true, double rho, double lambda, double mu,MPI_Comm comm = MPI_COMM_WORLD);
 
        void setConstantDensity(double rho) { _rho=rho; }
        void setDensityField(Field densityField) { _densityField=densityField; _densityFieldSet=true;}
@@ -164,6 +164,7 @@ protected :
 
        double computeRHS(bool & stop);
        double computeStiffnessMatrixFV(bool & stop);
+       double computeStiffnessMatrixFE(bool & stop);
 
     /************ Data for FE calculation *************/
     bool _FECalculation;
@@ -175,18 +176,15 @@ protected :
     std::vector< int > _boundaryNodeIds;/* List of boundary nodes */
     std::vector< int > _dirichletNodeIds;/* List of boundary nodes with Dirichlet BC */
 
-    /*********** Functions for finite element method ***********/
-    Vector gradientNodal(Matrix M, vector< double > v);//gradient of nodal shape functions
-       double computeStiffnessMatrixFE(bool & stop);
-    static int fact(int n);
-    static int unknownNodeIndex(int globalIndex, std::vector< int > dirichletNodes);
-    static int globalNodeIndex(int unknownIndex, std::vector< int > dirichletNodes);
-
     /********* Possibility to set a boundary field as Dirichlet boundary condition *********/
     bool _dirichletValuesSet;
     bool _neumannValuesSet;
     std::map< int, double> _dirichletBoundaryValues;
     std::map< int, double> _neumannBoundaryValues;
+
+       //MPI variables
+       PetscMPIInt    _size;        /* size of communicator */
+       PetscMPIInt    _rank;        /* processor rank */
 };
 
 #endif /* LinearElasticityModel_HXX_ */
index 64b2d73af21fe34b40f012977c07dac7860aa987..ac9e73c2724556e67920d8774f659d300463e5a8 100755 (executable)
@@ -90,7 +90,7 @@ class ProblemCoreFlows
 {
 public :
        //! Constructeur par défaut
-       ProblemCoreFlows();
+       ProblemCoreFlows(MPI_Comm comm = MPI_COMM_WORLD);
        virtual ~ProblemCoreFlows();
        
        // -*-*-*- Gestion du calcul (interface ICoCo) -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
@@ -249,42 +249,57 @@ public :
         *  */
        void setInitialField(const Field &VV);
 
+       /** \fn setInitialField
+        * \brief sets the initial field from a field in a med file. 
+        * \details This function is added because we have not been able yet to swig properly the enum EntityType. It is replaced by an integer.
+        * \param [in] string : the file name
+        * \param [in] string : the field name
+        * \param [in] int : the time step number
+        * \param [in] int : int corresponding to the enum CELLS, NODES or FACES
+        * \param [out] void
+        *  */
+       void setInitialField(string fileName, string fieldName, int timeStepNumber, int field_support_type);
+
        /** \fn setInitialField
         * \brief sets the initial field from a field in a med file
         * \details
         * \param [in] string : the file name
         * \param [in] string : the field name
         * \param [in] int : the time step number
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
-       void setInitialField(string fileName, string fieldName, int timeStepNumber);
+       void setInitialField(string fileName, string fieldName, int timeStepNumber, EntityType typeField = CELLS);
 
        /** \fn setInitialFieldConstant
         * \brief sets a constant initial field on a mesh stored in a med file
         * \details
         * \param [in] string : the file name
         * \param [in] vector<double> : the value in each cell
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
-       void setInitialFieldConstant(string fileName, const vector<double> Vconstant);
+       void setInitialFieldConstant(string fileName, const vector<double> Vconstant, EntityType typeField = CELLS);
 
        /** \fn setInitialFieldConstant
         * \brief sets a constant initial field 
         * \details
         * \param [in] Mesh 
         * \param [in] Vector
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
-       void setInitialFieldConstant(const Mesh& M, const Vector Vconstant);
+       void setInitialFieldConstant(const Mesh& M, const Vector Vconstant, EntityType typeField = CELLS);
 
        /** \fn setInitialFieldConstant
         * \brief sets a constant initial field
         * \details
         * \param [in] Mesh
         * \param [in] vector<double>
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
-       void setInitialFieldConstant(const Mesh& M, const vector<double> Vconstant);
+       void setInitialFieldConstant(const Mesh& M, const vector<double> Vconstant, EntityType typeField = CELLS);
 
        /** \fn setInitialFieldConstant
         * \brief sets a constant initial field
@@ -303,11 +318,36 @@ public :
         * \param [in] double the highest value in the z direction
         * \param [in] string name of the bottom boundary
         * \param [in] string name of the top boundary
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
        void setInitialFieldConstant( int nDim, const vector<double> Vconstant, double xmin, double xmax,int nx, string leftSide, string rightSide,
                        double ymin=0, double ymax=0, int ny=0, string backSide="", string frontSide="",
-                       double zmin=0, double zmax=0, int nz=0, string bottomSide="", string topSide="");
+                       double zmin=0, double zmax=0, int nz=0, string bottomSide="", string topSide="", EntityType typeField = CELLS);
+
+       /** \fn setInitialFieldConstant
+        * \brief sets a constant initial field
+        * \details This function is added because we have not been able yet to swig roperly the enum EntityType. It is replaced by an integer.
+        * \param [in] int the space dimension
+        * \param [in] vector<double> the value in each cell
+        * \param [in] double the lowest value in the x direction
+        * \param [in] double the highest value in the x direction
+        * \param [in] string name of the left boundary
+        * \param [in] string name of the right boundary
+        * \param [in] double the lowest value in the y direction
+        * \param [in] double the highest value in the y direction
+        * \param [in] string name of the back boundary
+        * \param [in] string name of the front boundary
+        * \param [in] double the lowest value in the z direction
+        * \param [in] double the highest value in the z direction
+        * \param [in] string name of the bottom boundary
+        * \param [in] string name of the top boundary
+        * \param [in] integer corresponding to the field support enum : CELLS, NODES or FACES
+        * \param [out] void
+        *  */
+       void setInitialFieldConstant( int nDim, const vector<double> Vconstant, double xmin, double xmax,int nx, string leftSide, string rightSide,
+                       double ymin, double ymax, int ny, string backSide, string frontSide,
+                       double zmin, double zmax, int nz, string bottomSide, string topSide, int type_of_field );
 
        /** \fn setInitialFieldStepFunction
         * \brief sets a step function initial field (Riemann problem)
@@ -317,9 +357,10 @@ public :
         * \param [in] Vector
         * \param [in] double position of the discontinuity on one of the three axis
         * \param [in] int direction (axis carrying the discontinuity) : 0 for x, 1 for y, 2 for z
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
-       void setInitialFieldStepFunction(const Mesh M, const Vector Vleft, const Vector Vright, double disc_pos, int direction=0);
+       void setInitialFieldStepFunction(const Mesh M, const Vector Vleft, const Vector Vright, double disc_pos, int direction=0, EntityType typeField = CELLS);
 
        /** \fn setInitialFieldStepFunction
         * \brief sets a constant initial field
@@ -340,12 +381,13 @@ public :
         * \param [in] double the highest value in the z direction
         * \param [in] string name of the bottom boundary
         * \param [in] string name of the top boundary
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
        void setInitialFieldStepFunction( int nDim, const vector<double> VV_Left, vector<double> VV_Right, double xstep,
                        double xmin, double xmax,int nx, string leftSide, string rightSide,
                        double ymin=0, double ymax=0, int ny=0, string backSide="", string frontSide="",
-                       double zmin=0, double zmax=0, int nz=0, string bottomSide="", string topSide="");
+                       double zmin=0, double zmax=0, int nz=0, string bottomSide="", string topSide="", EntityType typeField = CELLS);
 
        /** \fn setInitialFieldSphericalStepFunction
         * \brief sets a step function initial field with value Vin inside the ball with radius Radius and Vout outside
@@ -355,9 +397,10 @@ public :
         * \param [in] Vector Vout, value outside the ball
         * \param [in] double radius of the ball
         * \param [in] Vector Center, coordinates of the ball center
+        * \param [in] EntityType : CELLS, NODES or FACES
         * \param [out] void
         *  */
-       void setInitialFieldSphericalStepFunction(const Mesh M, const Vector Vin, const Vector Vout, double Radius, Vector Center);
+       void setInitialFieldSphericalStepFunction(const Mesh M, const Vector Vin, const Vector Vout, double Radius, Vector Center, EntityType typeField = CELLS);
 
        /** \fn getTime
         * \brief renvoie _time (le temps courant du calcul)
@@ -606,8 +649,8 @@ public :
                _heatTransfertCoeff=heatTransfertCoeff;
        }
 
-       /** \fn setDISPLAY
-        * \brief met à jour les paramètres de l'affichage
+       /** \fn setVerbose
+        * \brief Updates display options
         * \details
         * \param [in] bool
         * \param [in] bool
@@ -716,6 +759,11 @@ protected :
        string _path;//path to execution directory used for saving results
        saveFormat _saveFormat;//file saving format : MED, VTK or CSV
        
+       //MPI variables
+       PetscMPIInt    _size;        /* size of communicator */
+       PetscMPIInt    _rank;        /* processor rank */
+       
+       
 };
 
 #endif /* PROBLEMCOREFLOWS_HXX_ */
index f0100f459c28684f0878abd52686a8e714c3ccbc..9989b61d77c1ccbbf35fe41d7ae2f235c18ee43f 100755 (executable)
@@ -84,7 +84,7 @@ public :
        /**\fn
         * \brief constructeur de la classe ProblemFluid
         */
-       ProblemFluid(void);
+       ProblemFluid(MPI_Comm comm = MPI_COMM_WORLD);
 
        //Gestion du calcul (interface ICoCo)
 
index 7bd065ea5841f484e7acc18fc3ebbc9db3aa66a1..ab0f1c336d279adb365e73b343617604eb189c84 100755 (executable)
@@ -50,7 +50,7 @@ public :
                         * \param [in] double : solid conductivity
                         *  */
 
-       StationaryDiffusionEquation( int dim,bool FECalculation=true,double lambda=1);
+       StationaryDiffusionEquation( int dim,bool FECalculation=true,double lambda=1,MPI_Comm comm = MPI_COMM_WORLD);
 
     void setMesh(const Mesh &M);
     void setFileName(string fileName){
@@ -146,6 +146,19 @@ public :
                _heatPowerFieldSet=true;
        }
 
+       /** \fn setVerbose
+        * \brief Updates display options
+        * \details
+        * \param [in] bool
+        * \param [in] bool
+        * \param [out] void
+        *  */
+       void setVerbose(bool verbose,  bool system=false)
+       {
+               _verbose = verbose;
+               _system = system;
+       };
+
 protected :
        //Main unknown field
        Field _VV;
@@ -205,6 +218,7 @@ protected :
 
        double computeRHS(bool & stop);
        double computeDiffusionMatrixFV(bool & stop);
+       double computeDiffusionMatrixFE(bool & stop);
 
     /************ Data for FE calculation *************/
     bool _FECalculation;
@@ -216,18 +230,15 @@ protected :
     std::vector< int > _boundaryNodeIds;/* List of boundary nodes */
     std::vector< int > _dirichletNodeIds;/* List of boundary nodes with Dirichlet BC */
 
-    /*********** Functions for finite element method ***********/
-    static Vector gradientNodal(Matrix M, vector< double > v);//gradient of nodal shape functions
-       double computeDiffusionMatrixFE(bool & stop);
-    static int fact(int n);
-    static int unknownNodeIndex(int globalIndex, std::vector< int > dirichletNodes);
-    static int globalNodeIndex(int unknownIndex, std::vector< int > dirichletNodes);
-
     /********* Possibility to set a boundary field as DirichletNeumann boundary condition *********/
     bool _dirichletValuesSet;
     bool _neumannValuesSet;
     std::map< int, double> _dirichletBoundaryValues;
     std::map< int, double> _neumannBoundaryValues;
+
+       //MPI variables
+       PetscMPIInt    _size;        /* size of communicator */
+       PetscMPIInt    _rank;        /* processor rank */
 };
 
 #endif /* StationaryDiffusionEquation_HXX_ */
index 5acc4ed90766a857c7a6df0c948557e4d82593c1..6f17e7f46c91d7e362f5eb9c201ecd6aaf1263be 100755 (executable)
@@ -64,7 +64,7 @@ public :
                         * \param [in] pressureMagnitude : \ref around1bar or \ref around155bars
                         * \param [in] vector<double> : fluid velocity (assumed constant)
                         *  */
-       TransportEquation(phase fluid, pressureMagnitude pEstimate,vector<double> vitesseTransport);
+       TransportEquation(phase fluid, pressureMagnitude pEstimate,vector<double> vitesseTransport, MPI_Comm comm = MPI_COMM_WORLD);
 
        //Gestion du calcul
        virtual void initialize();
index 1ac9cc7fc959a645d3a68c17b0ee33ae681eb346..b8993c6fbabdb298182650bf4ebb1973d478bffe 100755 (executable)
@@ -51,7 +51,7 @@ Vector DiffusionEquation::gradientNodal(Matrix M, vector< double > values)
        if(! M.isSquare() )
                throw CdmathException("DiffusionEquation::gradientNodal Matrix M should be square !!!");
                
-       int Ndim = M.getNumberOfRows();
+       int Ndim = M.getNumberOfRows()-1;
     vector< Matrix > matrices(Ndim);
     
     for (int idim=0; idim<Ndim;idim++){
@@ -67,34 +67,34 @@ Vector DiffusionEquation::gradientNodal(Matrix M, vector< double > values)
        return result;    
 }
 
-DiffusionEquation::DiffusionEquation(int dim, bool FECalculation,double rho,double cp, double lambda){
+DiffusionEquation::DiffusionEquation(int dim, bool FECalculation,double rho,double cp, double lambda, MPI_Comm comm ):ProblemCoreFlows(comm)
+{
     /* Control input value are acceptable */
     if(rho<_precision or cp<_precision)
     {
-        std::cout<<"rho = "<<rho<<", cp = "<<cp<< ", precision = "<<_precision;
+        PetscPrintf(PETSC_COMM_WORLD,"rho = %.2f, cp = %.2f, precision = %.2f\n",rho,cp,_precision);
         throw CdmathException("Error : parameters rho and cp should be strictly positive");
     }
     if(lambda < 0.)
     {
-        std::cout<<"Conductivity = "<<lambda<<endl;
+        PetscPrintf(PETSC_COMM_WORLD,"Conductivity = %.2f\n",lambda);
         throw CdmathException("Error : conductivity parameter lambda cannot  be negative");
     }
     if(dim<=0)
     {
-        std::cout<<"Space dimension = "<<dim<<endl;
+        PetscPrintf(PETSC_COMM_WORLD,"Space dimension = %.2f\n",dim);
         throw CdmathException("Error : parameter dim cannot  be negative");
     }
 
-    cout<<"Diffusion problem with density "<<rho<<", specific heat "<< cp<<", conductivity "<< lambda;
+    PetscPrintf(PETSC_COMM_WORLD,"Diffusion problem with density %.2f, specific heat %.2f, conductivity %.2f", rho,cp,lambda);
     if(FECalculation)
-        cout<<" and finite elements method"<<endl;
+        PetscPrintf(PETSC_COMM_WORLD," and finite elements method\n");
     else
-        cout<<" and finite volumes method"<<endl;
+        PetscPrintf(PETSC_COMM_WORLD," and finite volumes method\n");
     
     _FECalculation=FECalculation;
     
     /* Finite element data */
-    _neibMaxNbNodes=0;    
     _boundaryNodeIds=std::vector< int >(0);
     _dirichletNodeIds=std::vector< int >(0);
     _NboundaryNodes=0;
@@ -118,14 +118,14 @@ DiffusionEquation::DiffusionEquation(int dim, bool FECalculation,double rho,doub
        _dt_src=0;
        _diffusionMatrixSet=false;
 
-       _fileName = "CoreFlowsDiffusionProblem";
+       _fileName = "SolverlabDiffusionProblem";
 
        _runLogFile=new ofstream;
 
-    /* Default diffusion tensor is identity matrix */
+    /* Default diffusion tensor is diagonal */
        _DiffusionTensor=Matrix(_Ndim);
        for(int idim=0;idim<_Ndim;idim++)
-               _DiffusionTensor(idim,idim)=1;
+               _DiffusionTensor(idim,idim)=_diffusivity;
 }
 
 void DiffusionEquation::initialize()
@@ -134,7 +134,7 @@ void DiffusionEquation::initialize()
 
        if(_Ndim != _mesh.getSpaceDimension() or _Ndim!=_mesh.getMeshDimension())//for the moment we must have space dim=mesh dim
        {
-        cout<< "Problem : dimension defined is "<<_Ndim<< " but mesh dimension= "<<_mesh.getMeshDimension()<<", and space dimension is "<<_mesh.getSpaceDimension()<<endl;
+        PetscPrintf(PETSC_COMM_WORLD,"Problem : dimension defined is %d but mesh dimension= %d, and space dimension is %d",_Ndim,_mesh.getMeshDimension(),_mesh.getSpaceDimension());
                *_runLogFile<< "Problem : dim = "<<_Ndim<< " but mesh dim= "<<_mesh.getMeshDimension()<<", mesh space dim= "<<_mesh.getSpaceDimension()<<endl;
                *_runLogFile<<"DiffusionEquation::initialize: mesh has incorrect dimension"<<endl;
                _runLogFile->close();
@@ -145,16 +145,16 @@ void DiffusionEquation::initialize()
                throw CdmathException("DiffusionEquation::initialize() set initial data first");
        else
         {
-            cout<<"Initialising the diffusion of a solid temperature using ";
+            PetscPrintf(PETSC_COMM_WORLD,"Initialising the diffusion of a solid temperature using ");
             *_runLogFile<<"Initialising the diffusion of a solid temperature using ";
             if(!_FECalculation)
             {
-                cout<< "Finite volumes method"<<endl<<endl;
+                PetscPrintf(PETSC_COMM_WORLD,"Finite volumes method\n\n");
                 *_runLogFile<< "Finite volumes method"<<endl<<endl;
             }
             else
             {
-                cout<< "Finite elements method"<<endl<<endl;
+                PetscPrintf(PETSC_COMM_WORLD,"Finite elements method\n\n");
                 *_runLogFile<< "Finite elements method"<<endl<<endl;
             }
         }
@@ -178,16 +178,16 @@ void DiffusionEquation::initialize()
     if(_FECalculation)
     {
         if(_Ndim==1 )//The 1D cdmath mesh is necessarily made of segments
-                       cout<<"1D Finite element method on segments"<<endl;
+                       PetscPrintf(PETSC_COMM_WORLD,"1D Finite element method on segments\n");
         else if(_Ndim==2)
         {
                        if( _mesh.isTriangular() )//Mesh dim=2
-                               cout<<"2D Finite element method on triangles"<<endl;
+                               PetscPrintf(PETSC_COMM_WORLD,"2D Finite element method on triangles\n");
                        else if (_mesh.getMeshDimension()==1)//Mesh dim=1
-                               cout<<"1D Finite element method on a 2D network : space dimension is "<<_Ndim<< ", mesh dimension is "<<_mesh.getMeshDimension()<<endl;                 
+                               PetscPrintf(PETSC_COMM_WORLD,"1D Finite element method on a 2D network : space dimension is %d, mesh dimension is %d\n",_Ndim,_mesh.getMeshDimension());                        
                        else
                        {
-                               cout<<"Error Finite element with Space dimension "<<_Ndim<< ", and mesh dimension  "<<_mesh.getMeshDimension()<< ", mesh should be either triangular either 1D network"<<endl;
+                               PetscPrintf(PETSC_COMM_WORLD,"Error Finite element with space dimension %, and mesh dimension  %d, mesh should be either triangular either 1D network\n",_Ndim,_mesh.getMeshDimension());
                                *_runLogFile<<"DiffusionEquation::initialize mesh has incorrect dimension"<<endl;
                                _runLogFile->close();
                                throw CdmathException("DiffusionEquation::initialize: mesh has incorrect cell types");
@@ -196,14 +196,14 @@ void DiffusionEquation::initialize()
         else if(_Ndim==3)
         {
                        if( _mesh.isTetrahedral() )//Mesh dim=3
-                               cout<<"3D Finite element method on tetrahedra"<<endl;
+                               PetscPrintf(PETSC_COMM_WORLD,"3D Finite element method on tetrahedra\n");
                        else if (_mesh.getMeshDimension()==2 and _mesh.isTriangular())//Mesh dim=2
-                               cout<<"2D Finite element method on a 3D surface : space dimension is "<<_Ndim<< ", mesh dimension is "<<_mesh.getMeshDimension()<<endl;                 
+                               PetscPrintf(PETSC_COMM_WORLD,"2D Finite element method on a 3D surface : space dimension is %d, mesh dimension is %d\n",_Ndim,_mesh.getMeshDimension());                        
                        else if (_mesh.getMeshDimension()==1)//Mesh dim=1
-                               cout<<"1D Finite element method on a 3D network : space dimension is "<<_Ndim<< ", mesh dimension is "<<_mesh.getMeshDimension()<<endl;                 
+                               PetscPrintf(PETSC_COMM_WORLD,"1D Finite element method on a 3D network : space dimension is %d, mesh dimension is %d\n",_Ndim,_mesh.getMeshDimension());                        
                        else
                        {
-                               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;
+                               PetscPrintf(PETSC_COMM_WORLD,"Error Finite element with space dimension %d, and mesh dimension  %d, mesh should be either tetrahedral, either a triangularised surface or 1D network",_Ndim,_mesh.getMeshDimension());
                                *_runLogFile<<"DiffusionEquation::initialize mesh has incorrect dimension"<<endl;
                                _runLogFile->close();
                                throw CdmathException("DiffusionEquation::initialize: mesh has incorrect cell types");
@@ -214,14 +214,14 @@ void DiffusionEquation::initialize()
         _NboundaryNodes=_boundaryNodeIds.size();
 
         if(_NboundaryNodes==_Nnodes)
-            cout<<"!!!!! Warning : all nodes are boundary nodes !!!!!"<<endl;
+            PetscPrintf(PETSC_COMM_WORLD,"!!!!! Warning : all nodes are boundary nodes !!!!!");
 
         for(int i=0; i<_NboundaryNodes; i++)
             if(_limitField[(_mesh.getNode(_boundaryNodeIds[i])).getGroupName()].bcType==DirichletDiffusion)
                 _dirichletNodeIds.push_back(_boundaryNodeIds[i]);
         _NdirichletNodes=_dirichletNodeIds.size();
         _NunknownNodes=_Nnodes - _NdirichletNodes;
-        cout<<"Number of unknown nodes " << _NunknownNodes <<", Number of boundary nodes " << _NboundaryNodes<< ", Number of Dirichlet boundary nodes " << _NdirichletNodes <<endl<<endl;
+        PetscPrintf(PETSC_COMM_WORLD,"Number of unknown nodes %d, Number of boundary nodes %d, Number of Dirichlet boundary nodes %d\n\n", _NunknownNodes,_NboundaryNodes, _NdirichletNodes);
         *_runLogFile<<"Number of unknown nodes " << _NunknownNodes <<", Number of boundary nodes " << _NboundaryNodes<< ", Number of Dirichlet boundary nodes " << _NdirichletNodes <<endl<<endl;
     }
 
@@ -294,6 +294,7 @@ double DiffusionEquation::computeDiffusionMatrix(bool & stop)
 }
 
 double DiffusionEquation::computeDiffusionMatrixFE(bool & stop){
+
        Cell Cj;
        string nameOfGroup;
        double coeff;//Diffusion coefficients between nodes i and j
@@ -341,7 +342,7 @@ double DiffusionEquation::computeDiffusionMatrixFE(bool & stop){
                     if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[jdim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[jdim])
                     {//Second node of the edge is not Dirichlet node
                         j_int= unknownNodeIndex(nodeIds[jdim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
-                        MatSetValue(_A,i_int,j_int,_conductivity*(_DiffusionTensor*GradShapeFuncs[idim])*GradShapeFuncs[jdim]/Cj.getMeasure(), ADD_VALUES);
+                        MatSetValue(_A,i_int,j_int,(_DiffusionTensor*GradShapeFuncs[idim])*GradShapeFuncs[jdim]/Cj.getMeasure(), ADD_VALUES);
                     }
                     else if (!dirichletCell_treated)
                     {//Second node of the edge is a Dirichlet node
@@ -360,7 +361,7 @@ double DiffusionEquation::computeDiffusionMatrixFE(bool & stop){
                                 valuesBorder[kdim]=0;                            
                         }
                         GradShapeFuncBorder=gradientNodal(M,valuesBorder)/fact(_Ndim);
-                        coeff =-_conductivity*(_DiffusionTensor*GradShapeFuncBorder)*GradShapeFuncs[idim]/Cj.getMeasure();
+                        coeff =-1.*(_DiffusionTensor*GradShapeFuncBorder)*GradShapeFuncs[idim]/Cj.getMeasure();
                         VecSetValue(_b,i_int,coeff, ADD_VALUES);                        
                     }
                 }
@@ -375,15 +376,15 @@ double DiffusionEquation::computeDiffusionMatrixFE(bool & stop){
         int NboundaryFaces=boundaryFaces.size();
         for(int i = 0; i< NboundaryFaces ; i++)//On parcourt les faces du bord
         {
-            Face Fi = _mesh.getFace(i);
+            Face Fi = _mesh.getFace(boundaryFaces[i]);
             for(int j = 0 ; j<_Ndim ; j++)//On parcourt les noeuds de la face
             {
-                if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Fi.getNodeId(j))==_dirichletNodeIds.end())//node j is an Neumann BC node (not a Dirichlet BC node)
+                if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Fi.getNodeId(j))==_dirichletNodeIds.end())//node j is a Neumann BC node (not a Dirichlet BC node)
                 {
                     j_int=unknownNodeIndex(Fi.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
                     if( _neumannValuesSet )
                         coeff =Fi.getMeasure()/_Ndim*_neumannBoundaryValues[Fi.getNodeId(j)];
-                    else    
+                    else
                         coeff =Fi.getMeasure()/_Ndim*_limitField[_mesh.getNode(Fi.getNodeId(j)).getGroupName()].normalFlux;
                     VecSetValue(_b, j_int, coeff, ADD_VALUES);
                 }
@@ -399,7 +400,8 @@ double DiffusionEquation::computeDiffusionMatrixFE(bool & stop){
        _diffusionMatrixSet=true;
     stop=false ;
 
-       cout<<"Maximum diffusivity is "<<_maxvp<< " CFL = "<<_cfl<<" Delta x = "<<_minl<<endl;
+       _maxvp=_diffusivity;//To do : optimise value with the mesh while respecting stability
+       PetscPrintf(PETSC_COMM_SELF,"Maximum diffusivity is %.2f, CFL = %.2f, Delta x = %.2f\n",_maxvp,_cfl,_minl);
        if(fabs(_maxvp)<_precision)
                throw CdmathException("DiffusionEquation::computeDiffusionMatrixFE(): Error computing time step ! Maximum diffusivity is zero => division by zero");
        else
@@ -436,7 +438,7 @@ double DiffusionEquation::computeDiffusionMatrixFV(bool & stop){
         }
 
                //Compute velocity at the face Fj
-               dn=_conductivity*(_DiffusionTensor*normale)*normale;
+               dn=(_DiffusionTensor*normale)*normale;
                if(fabs(dn)>_maxvp)
                        _maxvp=fabs(dn);
 
@@ -514,22 +516,19 @@ double DiffusionEquation::computeDiffusionMatrixFV(bool & stop){
                return _cfl*_minl*_minl/_maxvp;
 }
 
-double DiffusionEquation::computeRHS(bool & stop){
+double DiffusionEquation::computeRHS(bool & stop){//Contribution of the PDE RHS to the linear systemm RHS (boundary conditions do contribute to the system RHS via the function computeDiffusionMatrix
        VecAssemblyBegin(_b);          
     double Ti;  
     if(!_FECalculation)
         for (int i=0; i<_Nmailles;i++)
-        {
-            VecSetValue(_b,i,_heatPowerField(i)/(_rho*_cp),ADD_VALUES);//Contribution of the volumic heat power
-            //Contribution due to fluid/solide heat exchange
+            //Contribution due to fluid/solide heat exchange + Contribution of the volumic heat power
             if(_timeScheme == Explicit)
             {
                 VecGetValues(_Tn, 1, &i, &Ti);
-                VecSetValue(_b,i,_heatTransfertCoeff/(_rho*_cp)*(_fluidTemperatureField(i)-Ti),ADD_VALUES);
+                VecSetValue(_b,i,(_heatTransfertCoeff*(_fluidTemperatureField(i)-Ti)+_heatPowerField(i))/(_rho*_cp),ADD_VALUES);
             }
             else//Implicit scheme    
-                VecSetValue(_b,i,_heatTransfertCoeff/(_rho*_cp)* _fluidTemperatureField(i)    ,ADD_VALUES);
-        }
+                VecSetValue(_b,i,(_heatTransfertCoeff* _fluidTemperatureField(i)    +_heatPowerField(i))/(_rho*_cp)    ,ADD_VALUES);
     else
         {
             Cell Ci;
@@ -541,7 +540,7 @@ double DiffusionEquation::computeRHS(bool & stop){
                 for (int j=0; j<nodesId.size();j++)
                     if(!_mesh.isBorderNode(nodesId[j])) //or for better performance nodeIds[idim]>dirichletNodes.upper_bound()
                     {
-                        double coeff = _heatTransfertCoeff*_fluidTemperatureField(nodesId[j]) + _heatPowerField(nodesId[j]);
+                        double coeff = (_heatTransfertCoeff*_fluidTemperatureField(nodesId[j]) + _heatPowerField(nodesId[j]))/(_rho*_cp);
                         VecSetValue(_b,unknownNodeIndex(nodesId[j], _dirichletNodeIds), coeff*Ci.getMeasure()/(_Ndim+1),ADD_VALUES);
                     }
             }
@@ -549,8 +548,10 @@ double DiffusionEquation::computeRHS(bool & stop){
        VecAssemblyEnd(_b);
 
     if(_verbose or _system)
+       {
+               PetscPrintf(PETSC_COMM_WORLD,"Right hand side of the linear system\n");
         VecView(_b,PETSC_VIEWER_STDOUT_SELF);
-
+       }
     stop=false ;
     if(_heatTransfertCoeff>_precision)
         return _rho*_cp/_heatTransfertCoeff;
@@ -576,7 +577,7 @@ bool DiffusionEquation::initTimeStep(double dt){
     }
     else//dt<=0
     {
-        cout<<"DiffusionEquation::initTimeStep dt= "<<dt<<endl;
+        PetscPrintf(PETSC_COMM_WORLD,"DiffusionEquation::initTimeStep %.2f = \n",dt);
         throw CdmathException("Error DiffusionEquation::initTimeStep : cannot set time step to zero");        
     }
     //At this stage _b contains _b0 + power + heat exchange
@@ -585,8 +586,11 @@ bool DiffusionEquation::initTimeStep(double dt){
        _dt = dt;
 
        if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
+       {
+               PetscPrintf(PETSC_COMM_WORLD,"Matrix of the linear system\n");
                MatView(_A,PETSC_VIEWER_STDOUT_SELF);
-
+       }
+       
        return _dt>0;
 }
 
@@ -642,7 +646,7 @@ bool DiffusionEquation::iterateTimeStep(bool &converged)
                        _MaxIterLinearSolver = _PetscIts;
                if(_PetscIts>=_maxPetscIts)
                {
-                       cout<<"Systeme lineaire : pas de convergence de Petsc. Itérations maximales "<<_maxPetscIts<<" atteintes"<<endl;
+                       PetscPrintf(PETSC_COMM_WORLD,"Systeme lineaire : pas de convergence de Petsc. Itérations maximales %d atteintes \n",_maxPetscIts);
                        *_runLogFile<<"Systeme lineaire : pas de convergence de Petsc. Itérations maximales "<<_maxPetscIts<<" atteintes"<<endl;
                        converged=false;
                        return false;
@@ -691,7 +695,7 @@ void DiffusionEquation::validateTimeStep()
        VecCopy(_Tk, _Tkm1);
 
        if(_verbose && (_nbTimeStep-1)%_freqSave ==0)
-               cout <<"Valeur propre locale max: " << _maxvp << endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Valeur propre locale max: %.2f\n", _maxvp);
 
        _time+=_dt;
        _nbTimeStep++;
@@ -700,7 +704,7 @@ void DiffusionEquation::validateTimeStep()
 }
 
 void DiffusionEquation::save(){
-    cout<< "Saving numerical results"<<endl<<endl;
+    PetscPrintf(PETSC_COMM_SELF,"Saving numerical results\n\n");
     *_runLogFile<< "Saving numerical results"<< endl<<endl;
 
        string resultFile(_path+"/DiffusionEquation");//Results
@@ -709,8 +713,10 @@ void DiffusionEquation::save(){
        resultFile+=_fileName;
 
     if(_verbose or _system)
+       {
+               PetscPrintf(PETSC_COMM_WORLD,"Unknown of the linear system :\n");
         VecView(_Tk,PETSC_VIEWER_STDOUT_SELF);
-
+       }
     //On remplit le champ
     double Ti;
     if(!_FECalculation)
index bdcd35c313ed2ea208d54dc2fe6e2c2313ccf594..2e3dc50f19bc14847859a62cfa80f7d15bdc2237 100755 (executable)
@@ -8,51 +8,24 @@
 
 using namespace std;
 
-int LinearElasticityModel::fact(int n)
-{
-  return (n == 1 || n == 0) ? 1 : fact(n - 1) * n;
-}
-int LinearElasticityModel::unknownNodeIndex(int globalIndex, std::vector< int > dirichletNodes)
-{//assumes Dirichlet node numbering is strictly increasing
-    int j=0;//indice de parcours des noeuds frontière avec CL Dirichlet
-    int boundarySize=dirichletNodes.size();
-    while(j<boundarySize and dirichletNodes[j]<globalIndex)
-        j++;
-    if(j==boundarySize)
-        return globalIndex-boundarySize;
-    else if (dirichletNodes[j]>globalIndex)
-        return globalIndex-j;
-    else
-        throw CdmathException("LinearElasticityModel::unknownNodeIndex : Error : node is a Dirichlet boundary node");
-}
-
-int LinearElasticityModel::globalNodeIndex(int unknownNodeIndex, std::vector< int > dirichletNodes)
-{//assumes Dirichlet boundary node numbering is strictly increasing
-    int boundarySize=dirichletNodes.size();
-    /* trivial case where all boundary nodes are Neumann BC */
-    if(boundarySize==0)
-        return unknownNodeIndex;
-        
-    double unknownNodeMax=-1;//max unknown node number in the interval between jth and (j+1)th Dirichlet boundary nodes
-    int j=0;//indice de parcours des noeuds frontière
-    //On cherche l'intervale [j,j+1] qui contient le noeud de numéro interieur unknownNodeIndex
-    while(j+1<boundarySize and unknownNodeMax<unknownNodeIndex)
-    {
-        unknownNodeMax += dirichletNodes[j+1]-dirichletNodes[j]-1;
-        j++;
-    }    
-
-    if(j+1==boundarySize)
-        return unknownNodeIndex+boundarySize;
-    else //unknownNodeMax>=unknownNodeIndex) hence our node global number is between dirichletNodes[j-1] and dirichletNodes[j]
-        return unknownNodeIndex - unknownNodeMax + dirichletNodes[j]-1;
-}
-
-LinearElasticityModel::LinearElasticityModel(int dim, bool FECalculation,  double rho, double lambda, double mu){
+LinearElasticityModel::LinearElasticityModel(int dim, bool FECalculation,  double rho, double lambda, double mu,MPI_Comm comm){
+       /* Initialisation of PETSC */
+       //check if PETSC is already initialised
        PetscBool petscInitialized;
        PetscInitialized(&petscInitialized);
        if(!petscInitialized)
-               PetscInitialize(NULL,NULL,0,0);
+       {//check if MPI is already initialised
+               int mpiInitialized;
+               MPI_Initialized(&mpiInitialized);
+               if(mpiInitialized)
+                       PETSC_COMM_WORLD = comm;
+               PetscInitialize(NULL,NULL,0,0);//Note this is ok if MPI has been been initialised independently from PETSC
+       }
+       MPI_Comm_rank(PETSC_COMM_WORLD,&_rank);
+       MPI_Comm_size(PETSC_COMM_WORLD,&_size);
+       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. 
+       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. 
+       PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);
 
     if(lambda < 0.)
     {
@@ -263,22 +236,6 @@ void LinearElasticityModel::initialize()
 
 }
 
-Vector LinearElasticityModel::gradientNodal(Matrix M, vector< double > values){
-    vector< Matrix > matrices(_Ndim);
-    
-    for (int idim=0; idim<_Ndim;idim++){
-        matrices[idim]=M.deepCopy();
-        for (int jdim=0; jdim<_Ndim+1;jdim++)
-                       matrices[idim](jdim,idim) = values[jdim] ;
-    }
-
-       Vector result(_Ndim);
-    for (int idim=0; idim<_Ndim;idim++)
-        result[idim] = matrices[idim].determinant();
-
-       return result;    
-}
-
 double LinearElasticityModel::computeStiffnessMatrix(bool & stop)
 {
     double result;
@@ -328,20 +285,20 @@ double LinearElasticityModel::computeStiffnessMatrixFE(bool & stop){
             M(idim,_Ndim)=1;
         }
         for (int idim=0; idim<_Ndim+1;idim++)
-            GradShapeFuncs[idim]=gradientNodal(M,values[idim])/fact(_Ndim);
+            GradShapeFuncs[idim]=DiffusionEquation::gradientNodal(M,values[idim])/DiffusionEquation::fact(_Ndim);
 
         /* Loop on the edges of the cell */
         for (int idim=0; idim<_Ndim+1;idim++)
         {
             if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[idim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[idim])
             {//First node of the edge is not Dirichlet node
-                i_int=unknownNodeIndex(nodeIds[idim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
+                i_int=DiffusionEquation::unknownNodeIndex(nodeIds[idim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
                 dirichletCell_treated=false;
                 for (int jdim=0; jdim<_Ndim+1;jdim++)
                 {
                     if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[jdim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[jdim])
                     {//Second node of the edge is not Dirichlet node
-                        j_int= unknownNodeIndex(nodeIds[jdim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
+                        j_int= DiffusionEquation::unknownNodeIndex(nodeIds[jdim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
                         MatSetValue(_A,i_int,j_int,_conductivity*(_DiffusionTensor*GradShapeFuncs[idim])*GradShapeFuncs[jdim]/Cj.getMeasure(), ADD_VALUES);
                     }
                     else if (!dirichletCell_treated)
@@ -360,7 +317,7 @@ double LinearElasticityModel::computeStiffnessMatrixFE(bool & stop){
                             else
                                 valuesBorder[kdim]=Vector(_Ndim);                            
                         }
-                        GradShapeFuncBorder=gradientNodal(M,valuesBorder)/fact(_Ndim);
+                        GradShapeFuncBorder=DiffusionEquation::gradientNodal(M,valuesBorder)/DiffusionEquation::fact(_Ndim);
                         double coeff =-_conductivity*(_DiffusionTensor*GradShapeFuncBorder)*GradShapeFuncs[idim]/Cj.getMeasure();
                         VecSetValue(_b,i_int,coeff, ADD_VALUES);                        
                     }
@@ -376,12 +333,12 @@ double LinearElasticityModel::computeStiffnessMatrixFE(bool & stop){
         int NboundaryFaces=boundaryFaces.size();
         for(int i = 0; i< NboundaryFaces ; i++)//On parcourt les faces du bord
         {
-            Face Fi = _mesh.getFace(i);
+            Face Fi = _mesh.getFace(boundaryFaces[i]);
             for(int j = 0 ; j<_Ndim ; j++)//On parcourt les noeuds de la face
             {
                 if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Fi.getNodeId(j))==_dirichletNodeIds.end())//node j is an Neumann BC node (not a Dirichlet BC node)
                 {
-                    j_int=unknownNodeIndex(Fi.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
+                    j_int=DiffusionEquation::unknownNodeIndex(Fi.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
                     if( _neumannValuesSet )
                         coeff =Fi.getMeasure()/(_Ndim+1)*_neumannBoundaryValues[Fi.getNodeId(j)];
                     else    
@@ -540,7 +497,7 @@ double LinearElasticityModel::computeRHS(bool & stop)//Contribution of the PDE R
                 for (int j=0; j<nodesId.size();j++)
                     if(!_mesh.isBorderNode(nodesId[j]))
                                                for (int k=0; k<_Ndim; k++)
-                                                       VecSetValue(_b,unknownNodeIndex(nodesId[j], _dirichletNodeIds)*nVar+k, _gravity(k)*_densityField(j)*Ci.getMeasure()/(_Ndim+1),ADD_VALUES);
+                                                       VecSetValue(_b,DiffusionEquation::unknownNodeIndex(nodesId[j], _dirichletNodeIds)*nVar+k, _gravity(k)*_densityField(j)*Ci.getMeasure()/(_Ndim+1),ADD_VALUES);
             }
         }
     
@@ -790,7 +747,7 @@ void LinearElasticityModel::save(){
         int globalIndex;
         for(int i=0; i<_NunknownNodes; i++)
         {
-                       globalIndex = globalNodeIndex(i, _dirichletNodeIds);
+                       globalIndex = DiffusionEquation::globalNodeIndex(i, _dirichletNodeIds);
                        for(int j=0; j<_nVar; j++)
                        {
                                int k=i*_nVar+j;
index aea9a503b663c73df70cec150b87bf718b0a881e..b34f353e61bcb2fef9df263734af849a7e12f859 100755 (executable)
 
 using namespace std;
 
-ProblemCoreFlows::ProblemCoreFlows()
+ProblemCoreFlows::ProblemCoreFlows(MPI_Comm comm)
 {
+       /* Initialisation of PETSC */
+       //check if PETSC is already initialised
        PetscBool petscInitialized;
        PetscInitialized(&petscInitialized);
        if(!petscInitialized)
-               PetscInitialize(NULL,NULL,0,0);
+       {//check if MPI is already initialised
+               int mpiInitialized;
+               MPI_Initialized(&mpiInitialized);
+               if(mpiInitialized)
+                       PETSC_COMM_WORLD = comm;
+               PetscInitialize(NULL,NULL,0,0);//Note this is ok if MPI has been been initialised independently from PETSC
+       }
+       MPI_Comm_rank(PETSC_COMM_WORLD,&_rank);
+       MPI_Comm_size(PETSC_COMM_WORLD,&_size);
+       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. 
+       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. 
+       PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);
+
+       if(_size>1)
+       {
+               PetscPrintf(PETSC_COMM_WORLD,"---- More than one processor detected : running a parallel simulation ----\n");
+               PetscPrintf(PETSC_COMM_WORLD,"---- Limited parallelism : input and output fields remain sequential ----\n");
+               PetscPrintf(PETSC_COMM_WORLD,"---- Only the matrixoperations are done in parallel thanks to PETSc----\n");
+               PetscPrintf(PETSC_COMM_WORLD,"---- Processor %d is in charge of building the mesh, saving the results, filling and then distributing the matrix to other processors.\n\n",_rank);
+       }
+       
+       /* Numerical parameter */
        _dt = 0;
        _time = 0;
        _nbTimeStep=0;
@@ -34,35 +57,45 @@ ProblemCoreFlows::ProblemCoreFlows()
        _precision_Newton=_precision;
        _erreur_rel= 0;
        _isStationary=false;
+       _timeScheme=Explicit;
+       _wellBalancedCorrection=false;
+    _FECalculation=false;
+       _nonLinearSolver = Newton_SOLVERLAB;
+       _conditionNumber=false;
+       _maxvp=0;
+       _runLogFile=new ofstream;
+
+       /* Monitoring of simulation */
+       _restartWithNewTimeScheme=false;
+       _restartWithNewFileName=false;
+       _fileName = "myCoreFlowsProblem";
+       _freqSave = 1;
+       _verbose = false;
+       _system = false;
+
+       /* Mesh parameters */
        _Ndim=0;
        _minl=0;
        _neibMaxNb=0;
-       _fileName = "myCoreFlowsProblem";
-       _freqSave = 1;
+
+       /* Memory and restart */
        _initialDataSet=false;
        _initializedMemory=false;
-       _restartWithNewTimeScheme=false;
-       _restartWithNewFileName=false;
-       _timeScheme=Explicit;
-       _wellBalancedCorrection=false;
-    _FECalculation=false;
-       _maxPetscIts=50;
+
+       /* PETSc and linear solver parameters */
        _MaxIterLinearSolver=0;//During several newton iterations, stores the max petssc interations
-       _maxNewtonIts=50;
        _NEWTON_its=0;
-       int _PetscIts=0;//the number of iterations of the linear solver
+       _maxPetscIts=50;
+       _maxNewtonIts=50;
+       _PetscIts=0;//the number of iterations of the linear solver
        _ksptype = (char*)&KSPGMRES;
        _pctype = (char*)&PCLU;
-       _nonLinearSolver = Newton_SOLVERLAB;
+
+       /* Physical parameter */
        _heatPowerFieldSet=false;
        _heatTransfertCoeff=0;
        _rodTemperatureFieldSet=false;
        _heatSource=0;
-       _verbose = false;
-       _system = false;
-       _conditionNumber=false;
-       _maxvp=0;
-       _runLogFile=new ofstream;
 
        //extracting current directory
        char result[ PATH_MAX ];
@@ -126,96 +159,163 @@ void ProblemCoreFlows::setInitialField(const Field &VV)
        }
        if(_FECalculation && VV.getTypeOfField()!=NODES)
        {
-               *_runLogFile<<"ProblemCoreFlows::setInitialField: Initial field has incorrect support : should be on nodes for the Finite Element method"<<endl;
+               *_runLogFile<<"ProblemCoreFlows::setInitialField: Initial field has incorrect support : should be on nodes for the Finite Elements method"<<endl;
+               _runLogFile->close();
+               throw CdmathException("ProblemCoreFlows::setInitialField: Initial field has incorrect support : should be on nodes for the Finite Elements method");
+       }
+       else if(!_FECalculation && VV.getTypeOfField()==NODES)
+       {
+               *_runLogFile<<"ProblemCoreFlows::setInitialField: Initial field has incorrect support : should be on cells or faces for the Finite Volumes method"<<endl;
                _runLogFile->close();
-               throw CdmathException("ProblemCoreFlows::setInitialField: Initial field has incorrect support : should be on nodes for the Finite Element method");
+               throw CdmathException("ProblemCoreFlows::setInitialField: Initial field has incorrect support : should be on cells or faces for the Finite Volumes method");
        }
 
        _VV=VV;
        _VV.setName("SOLVERLAB results");
        _time=_VV.getTime();
        _mesh=_VV.getMesh();
+       _initialDataSet=true;
+
+       //Mesh data
        _Nmailles = _mesh.getNumberOfCells();
        _Nnodes =   _mesh.getNumberOfNodes();
        _Nfaces =   _mesh.getNumberOfFaces();
        _perimeters=Field("Perimeters", CELLS, _mesh,1);
 
-       // find _minl and maximum nb of neibourghs
+       // find _minl (delta x) and maximum nb of neibourghs
        _minl  = INFINITY;
        int nbNeib,indexFace;
        Cell Ci;
        Face Fk;
 
        if(_verbose)
-               cout<<"Computing cell perimeters and mesh minimal diameter"<<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Computing cell perimeters and mesh minimal diameter\n");
 
+       //Compute the maximum number of neighbours for nodes or cells
     if(VV.getTypeOfField()==NODES)
-    {
-        _minl = _mesh.getMaxNbNeighbours(NODES);
         _neibMaxNbNodes=_mesh.getMaxNbNeighbours(NODES);
-    }
     else
-        for (int i=0; i<_mesh.getNumberOfCells(); i++){
-            Ci = _mesh.getCell(i);
-            //Detect mesh with junction
-            nbNeib=0;
-            for(int j=0; j<Ci.getNumberOfFaces(); j++){
-                Fk=_mesh.getFace(Ci.getFacesId()[j]);
-                nbNeib+=Fk.getNumberOfCells()-1;
-            }
-            if(nbNeib>_neibMaxNb)
-                _neibMaxNb=nbNeib;
-            //Compute mesh data
-            if (_Ndim > 1){
-                _perimeters(i)=0;
-                for (int k=0 ; k<Ci.getNumberOfFaces() ; k++){
-                    indexFace=Ci.getFacesId()[k];
-                    Fk = _mesh.getFace(indexFace);
-                    _minl = min(_minl,Ci.getMeasure()/Fk.getMeasure());
-                    _perimeters(i)+=Fk.getMeasure();
-                }
-            }else{
-                _minl = min(_minl,Ci.getMeasure());
-                _perimeters(i)=Ci.getNumberOfFaces();
-            }
-        }
-       _initialDataSet=true;
-
+        _neibMaxNb=_mesh.getMaxNbNeighbours(CELLS);
+        
+       //Compute Delta x and the cell perimeters
+       for (int i=0; i<_mesh.getNumberOfCells(); i++){
+               Ci = _mesh.getCell(i);
+               if (_Ndim > 1){
+                       _perimeters(i)=0;
+                       for (int k=0 ; k<Ci.getNumberOfFaces() ; k++){
+                               indexFace=Ci.getFacesId()[k];
+                               Fk = _mesh.getFace(indexFace);
+                               _minl = min(_minl,Ci.getMeasure()/Fk.getMeasure());
+                               _perimeters(i)+=Fk.getMeasure();
+                       }
+               }else{
+                       _minl = min(_minl,Ci.getMeasure());
+                       _perimeters(i)=Ci.getNumberOfFaces();
+               }
+       }
        if(_verbose)
                cout<<_perimeters<<endl;
 }
-void ProblemCoreFlows::setInitialField(string fileName, string fieldName, int timeStepNumber)
+//Function needed because swig of enum EntityType fails
+void ProblemCoreFlows::setInitialField(string fileName, string fieldName, int timeStepNumber, int field_support_type)
 {
-       Field VV(fileName,CELLS,fieldName,timeStepNumber,0);
+       if(_FECalculation && field_support_type!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
+
+       Field VV;
+       
+       switch(field_support_type)
+       {
+       case CELLS:
+               VV = Field(fileName, CELLS, fieldName, timeStepNumber, 0);
+               break;
+       case NODES:
+               VV = Field(fileName, NODES, fieldName, timeStepNumber, 0);
+               break;
+       case FACES:
+               VV = Field(fileName, FACES, fieldName, timeStepNumber, 0);
+               break;
+       default:
+               std::ostringstream message;
+               message << "Error ProblemCoreFlows::setInitialField \n Accepted field support integers are "<< CELLS <<" (for CELLS), "<<NODES<<" (for NODES), and "<< FACES <<" (for FACES)" ;
+               throw CdmathException(message.str().c_str());
+       }       
+
+       setInitialField(VV);
+}
+//Function needed because swig of enum EntityType fails
+void ProblemCoreFlows::setInitialFieldConstant( int nDim, const vector<double> Vconstant, double xmin, double xmax, int nx, string leftSide, string rightSide,
+               double ymin, double ymax, int ny, string backSide, string frontSide,
+               double zmin, double zmax, int nz, string bottomSide, string topSide, int field_support_type)
+{      
+       if(_FECalculation && field_support_type!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
+
+       EntityType typeField;
+       
+       switch(field_support_type)
+       {
+       case CELLS:
+               typeField=CELLS;
+               break;
+       case NODES:
+               typeField=NODES;
+               break;
+       case FACES:
+               typeField=FACES;
+               break;
+       default:
+               std::ostringstream message;
+               message << "Error ProblemCoreFlows::setInitialField \n Accepted field support integers are "<< CELLS <<" (for CELLS), "<<NODES<<" (for NODES), and "<< FACES <<" (for FACES)" ;
+               throw CdmathException(message.str().c_str());
+       }       
+       
+       setInitialFieldConstant( nDim, Vconstant, xmin, xmax, nx, leftSide, rightSide, ymin, ymax, ny, backSide, frontSide, zmin, zmax, nz, bottomSide, topSide, typeField);
+}
+void ProblemCoreFlows::setInitialField(string fileName, string fieldName, int timeStepNumber, EntityType typeField)
+{
+       if(_FECalculation && typeField!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
+
+       Field VV(fileName, typeField, fieldName, timeStepNumber, 0);
+       
        setInitialField(VV);
 }
-void ProblemCoreFlows::setInitialFieldConstant(string fileName, const vector<double> Vconstant)
+void ProblemCoreFlows::setInitialFieldConstant(string fileName, const vector<double> Vconstant, EntityType typeField)
 {
+       if(_FECalculation && typeField!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
        Mesh M(fileName);
-       Field VV("SOLVERLAB results", CELLS, M, Vconstant.size());
+       Field VV("SOLVERLAB results", typeField, M, Vconstant.size());
 
-       for (int j = 0; j < M.getNumberOfCells(); j++) {
+       for (int j = 0; j < VV.getNumberOfElements(); j++) {
                for (int i=0; i< VV.getNumberOfComponents(); i++)
                        VV(j,i) = Vconstant[i];
        }
 
        setInitialField(VV);
 }
-void ProblemCoreFlows::        setInitialFieldConstant(const Mesh& M, const Vector Vconstant)
+void ProblemCoreFlows::        setInitialFieldConstant(const Mesh& M, const Vector Vconstant, EntityType typeField)
 {
-       Field VV("SOLVERLAB results", CELLS, M, Vconstant.getNumberOfRows());
+       if(_FECalculation && typeField!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
+
+       Field VV("SOLVERLAB results", typeField, M, Vconstant.getNumberOfRows());
 
-       for (int j = 0; j < M.getNumberOfCells(); j++) {
+       for (int j = 0; j < VV.getNumberOfElements(); j++) {
                for (int i=0; i< VV.getNumberOfComponents(); i++)
                        VV(j,i) = Vconstant(i);
        }
        setInitialField(VV);
 }
-void ProblemCoreFlows::        setInitialFieldConstant(const Mesh& M, const vector<double> Vconstant)
+void ProblemCoreFlows::        setInitialFieldConstant(const Mesh& M, const vector<double> Vconstant, EntityType typeField)
 {
-       Field VV("SOLVERLAB results", CELLS, M, Vconstant.size());
+       if(_FECalculation && typeField!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
 
-       for (int j = 0; j < M.getNumberOfCells(); j++) {
+       Field VV("SOLVERLAB results", typeField, M, Vconstant.size());
+
+       for (int j = 0; j < VV.getNumberOfElements(); j++) {
                for (int i=0; i< VV.getNumberOfComponents(); i++)
                        VV(j,i) = Vconstant[i];
        }
@@ -223,20 +323,17 @@ void ProblemCoreFlows::   setInitialFieldConstant(const Mesh& M, const vector<doub
 }
 void ProblemCoreFlows::setInitialFieldConstant( int nDim, const vector<double> Vconstant, double xmin, double xmax, int nx, string leftSide, string rightSide,
                double ymin, double ymax, int ny, string backSide, string frontSide,
-               double zmin, double zmax, int nz, string bottomSide, string topSide)
+               double zmin, double zmax, int nz, string bottomSide, string topSide, EntityType typeField)
 {
        Mesh M;
-       if(nDim==1){
-               //cout<<"coucou1 xmin="<<xmin<<", xmax= "<<xmax<< ", nx= "<<nx<<endl;
+       if(nDim==1)
                M=Mesh(xmin,xmax,nx);
-               //cout<<"coucou2"<<endl;
-       }
        else if(nDim==2)
                M=Mesh(xmin,xmax,nx,ymin,ymax,ny);
        else if(nDim==3)
                M=Mesh(xmin,xmax,nx,ymin,ymax,ny,zmin,zmax,nz);
        else{
-               cout<<"ProblemCoreFlows::setInitialFieldConstant: Space dimension nDim should be between 1 and 3"<<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"ProblemCoreFlows::setInitialFieldConstant: Space dimension nDim should be between 1 and 3\n");
                *_runLogFile<<"ProblemCoreFlows::setInitialFieldConstant: Space dimension nDim should be between 1 and 3"<<endl;
                _runLogFile->close();
                throw CdmathException("Space dimension nDim should be between 1 and 3");
@@ -253,28 +350,30 @@ void ProblemCoreFlows::setInitialFieldConstant( int nDim, const vector<double> V
                M.setGroupAtPlan(zmin,2,_precision,bottomSide);
        }
 
-       setInitialFieldConstant(M, Vconstant);
+       setInitialFieldConstant(M, Vconstant, typeField);
 }
-void ProblemCoreFlows::setInitialFieldStepFunction(const Mesh M, const Vector VV_Left, const Vector VV_Right, double disc_pos, int direction)
+void ProblemCoreFlows::setInitialFieldStepFunction(const Mesh M, const Vector VV_Left, const Vector VV_Right, double disc_pos, int direction, EntityType typeField)
 {
+       if(_FECalculation && typeField!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
+
        if  (VV_Right.getNumberOfRows()!=VV_Left.getNumberOfRows())
        {
                *_runLogFile<<"ProblemCoreFlows::setStepFunctionInitialField: Vectors VV_Left and VV_Right have different sizes"<<endl;
                _runLogFile->close();
                throw CdmathException( "ProblemCoreFlows::setStepFunctionInitialField: Vectors VV_Left and VV_Right have different sizes");
        }
-       Field VV("SOLVERLAB results", CELLS, M, VV_Left.getNumberOfRows());
+       Field VV("SOLVERLAB results", typeField, M, VV_Left.getNumberOfRows());
 
        double component_value;
 
-       for (int j = 0; j < M.getNumberOfCells(); j++) {
-               if(direction==0)
-                       component_value=M.getCell(j).x();
-               else if(direction==1)
-                       component_value=M.getCell(j).y();
-               else if(direction==2)
-                       component_value=M.getCell(j).z();
-               else{
+       for (int j = 0; j < VV.getNumberOfElements(); j++) 
+       {
+               if(direction<=2)
+                       component_value=VV.getElementComponent(j, direction);
+               else
+               {
+                       PetscPrintf(PETSC_COMM_WORLD,"Error : space dimension is %d,  direction asked is \%d \n",M.getSpaceDimension(),direction);
                        _runLogFile->close();
                        throw CdmathException( "ProblemCoreFlows::setStepFunctionInitialField: direction should be an integer between 0 and 2");
                }
@@ -290,7 +389,7 @@ void ProblemCoreFlows::setInitialFieldStepFunction(const Mesh M, const Vector VV
 void ProblemCoreFlows::setInitialFieldStepFunction( int nDim, const vector<double> VV_Left, vector<double> VV_Right, double xstep,
                double xmin, double xmax, int nx, string leftSide, string rightSide,
                double ymin, double ymax, int ny, string backSide, string frontSide,
-               double zmin, double zmax, int nz, string bottomSide, string topSide)
+               double zmin, double zmax, int nz, string bottomSide, string topSide, EntityType typeField)
 {
        Mesh M;
        if(nDim==1)
@@ -320,29 +419,32 @@ void ProblemCoreFlows::setInitialFieldStepFunction( int nDim, const vector<doubl
                V_Left(i)=VV_Left[i];
                V_Right(i)=VV_Right[i];
        }
-       setInitialFieldStepFunction(M, V_Left, V_Right, xstep);
+       setInitialFieldStepFunction(M, V_Left, V_Right, xstep, typeField);
 }
 
-void ProblemCoreFlows::setInitialFieldSphericalStepFunction(const Mesh M, const Vector Vin, const Vector Vout, double radius, const Vector Center)
+void ProblemCoreFlows::setInitialFieldSphericalStepFunction(const Mesh M, const Vector Vin, const Vector Vout, double radius, const Vector Center, EntityType typeField)
 {
+       if(_FECalculation && typeField!= NODES)
+               cout<<"Warning : finite element simulation should have initial field on nodes!!!"<<endl;
+
        if((Center.size()!=M.getSpaceDimension()) || (Vout.size() != Vin.size()) )
        {
-               cout<< "Vout.size()= "<<Vout.size() << ", Vin.size()= "<<Vin.size()<<", Center.size()="<<Center.size()<<", M.getSpaceDim= "<< M.getSpaceDimension()<<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Vout.size() = %d, Vin.size()= %d, Center.size() = %d, M.getSpaceDim = %d \n",Vout.size(),Vin.size(),Center.size(), M.getSpaceDimension());
                throw CdmathException("ProblemCoreFlows::setInitialFieldSphericalStepFunction : Vector size error");
        }
        int nVar=Vout.size();
        int spaceDim=M.getSpaceDimension();
-       Field VV("Primitive variables for spherical step function", CELLS, M, nVar);
+       Field VV("Primitive variables for spherical step function", typeField, M, nVar);
 
        Vector currentPoint(spaceDim);
-       for(int i=0;i<M.getNumberOfCells();i++)
+       for(int i=0;i<VV.getNumberOfElements();i++)
        {
-               currentPoint(0)=M.getCell(i).x();
+               currentPoint(0)=VV.getElementComponent(i,0);
                if(spaceDim>1)
                {
-                       currentPoint(1)=M.getCell(i).y();
+                       currentPoint(1)=VV.getElementComponent(i,1);
                        if(spaceDim>2)
-                               currentPoint(2)=M.getCell(i).z();
+                               currentPoint(2)=VV.getElementComponent(i,2);
                }
                if((currentPoint-Center).norm()<radius)
                        for(int j=0;j<nVar;j++)
@@ -386,13 +488,13 @@ void ProblemCoreFlows::setLinearSolver(linearSolver kspType, preconditioner pcTy
        else if (kspType==BCGS)
                _ksptype = (char*)&KSPBCGS;
        else {
-               cout << "!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!" << endl;
+               PetscPrintf(PETSC_COMM_WORLD,"!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!\n");
                *_runLogFile << "!!! Error : only 'GMRES', 'CG' or 'BCGS' is acceptable as a linear solver !!!" << endl;
                _runLogFile->close();
                throw CdmathException("!!! Error : only 'GMRES', 'CG' or 'BCGS' algorithm is acceptable !!!");
        }
        // set preconditioner
-       if (pcType == NONE)
+       if (pcType == NOPC)
                _pctype = (char*)&PCNONE;
        else if (pcType ==LU)
                _pctype = (char*)&PCLU;
@@ -403,10 +505,10 @@ void ProblemCoreFlows::setLinearSolver(linearSolver kspType, preconditioner pcTy
        else if (pcType == ICC)
                _pctype = (char*)&PCICC;
        else {
-               cout << "!!! Error : only 'NONE', 'LU', 'ILU', 'CHOLESKY' or 'ICC' preconditioners are acceptable !!!" << endl;
-               *_runLogFile << "!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" << endl;
+               PetscPrintf(PETSC_COMM_WORLD,"!!! Error : only 'NOPC', 'LU', 'ILU', 'CHOLESKY' or 'ICC' preconditioners are acceptable !!!\n");
+               *_runLogFile << "!!! Error : only 'NOPC' or 'LU' or 'ILU' preconditioners are acceptable !!!" << endl;
                _runLogFile->close();
-               throw CdmathException("!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" );
+               throw CdmathException("!!! Error : only 'NOPC' or 'LU' or 'ILU' preconditioners are acceptable !!!" );
        }
 }
 
@@ -435,7 +537,7 @@ bool ProblemCoreFlows::run()
        bool ok; // Is the time interval successfully solved ?
        _isStationary=false;//in case of a second run with a different physics or cfl
 
-       cout<< "Running test case "<< _fileName<<endl<<endl;
+       PetscPrintf(PETSC_COMM_WORLD,"Running test case %d\n",_fileName);
 
        _runLogFile->open((_fileName+".log").c_str(), ios::out | ios::trunc);;//for creation of a log file to save the history of the simulation
        *_runLogFile<< "Running test case "<< _fileName<<endl;
@@ -448,7 +550,7 @@ bool ProblemCoreFlows::run()
                // Guess the next time step length
                _dt=computeTimeStep(stop);
                if (stop){
-                       cout << "Failed computing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
+                       PetscPrintf(PETSC_COMM_WORLD,"Failed computing time step %d, time = %.2f, dt= %.2f, stopping calculation",_nbTimeStep,_time,_dt);
                        *_runLogFile << "Failed computing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
                        break;
                }
@@ -458,7 +560,7 @@ bool ProblemCoreFlows::run()
                        stop=!initTimeStep(_dt);
                        // Prepare the next time step
                        if (stop){
-                               cout << "Failed initializing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
+                               PetscPrintf(PETSC_COMM_WORLD,"Failed initializing time step %d, time = %.2f, dt= %.2f, stopping calculation",_nbTimeStep,_time,_dt);
                                *_runLogFile << "Failed initializing time step "<<_nbTimeStep<<", time = " << _time <<", dt= "<<_dt<<", stopping calculation"<< endl;
                                break;
                        }
@@ -478,7 +580,7 @@ bool ProblemCoreFlows::run()
                                        //_dt=computeTimeStep(stop);
                                }
                                else{*/
-                                       cout << "Failed solving time step "<<_nbTimeStep<<", _time = " << _time<<" _dt= "<<_dt<<", cfl= "<<_cfl <<", stopping calculation"<< endl;
+                                       PetscPrintf(PETSC_COMM_WORLD,"Failed solving time step %d, time = %.2f, dt= %.2f, cfl = %.2f, stopping calculation \n",_nbTimeStep,_time,_dt,_cfl);
                                        *_runLogFile << "Failed solving time step "<<_nbTimeStep<<", _time = " << _time<<" _dt= "<<_dt<<", cfl= "<<_cfl <<", stopping calculation"<< endl;
                                        stop=true; // Impossible to solve the next time step, the Problem has given up
                                        break;
@@ -488,29 +590,29 @@ bool ProblemCoreFlows::run()
                        {
                                validateTimeStep();
                                if ((_nbTimeStep-1)%_freqSave ==0){
-                                       cout << "Time step = "<< _nbTimeStep << ", dt = "<< _dt <<", time = "<<_time << ", ||Un+1-Un||= "<<_erreur_rel<<endl<<endl;
+                                       PetscPrintf(PETSC_COMM_WORLD,"Time step = %d, dt = %.2f, time = %.2f, ||Un+1-Un||= %.2f\n\n",_nbTimeStep,_dt,_time,_erreur_rel);
                                        *_runLogFile << "Time step = "<< _nbTimeStep << ", dt = "<< _dt <<", time = "<<_time << ", ||Un+1-Un||= "<<_erreur_rel<<endl<<endl;
                                }
                        }
                }
        }
        if(_isStationary){
-               cout << "Stationary state reached" <<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Stationary state reached\n");
                *_runLogFile << "Stationary state reached" <<endl;
        }
        else if(_time>=_timeMax){
-               cout<<"Maximum time "<<_timeMax<<" reached"<<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Maximum time %.2f reached\n",_timeMax);
                *_runLogFile<<"Maximum time "<<_timeMax<<" reached"<<endl;
        }
        else if(_nbTimeStep>=_maxNbOfTimeStep){
-               cout<<"Maximum number of time steps "<<_maxNbOfTimeStep<<" reached"<<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Maximum number of time steps %d reached\n",_maxNbOfTimeStep);
                *_runLogFile<<"Maximum number of time steps "<<_maxNbOfTimeStep<<" reached"<<endl;
        }
        else{
-               cout<<"Error problem wants to stop!"<<endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Error problem wants to stop!\n");
                *_runLogFile<<"Error problem wants to stop!"<<endl;
        }
-       cout << "End of calculation time t= " << _time << " at time step number "<< _nbTimeStep << endl;
+       PetscPrintf(PETSC_COMM_WORLD,"End of calculation at time t = %.2f and time step number %d\n",_time,_nbTimeStep);
        *_runLogFile << "End of calculation time t= " << _time << " at time step number "<< _nbTimeStep << endl;
 
        _runLogFile->close();
@@ -558,14 +660,14 @@ bool ProblemCoreFlows::solveTimeStep(){
 
                if(_timeScheme == Implicit && (_nbTimeStep-1)%_freqSave ==0)//To monitor the convergence of the newton scheme
                {
-                       cout << " Newton iteration " << _NEWTON_its<< ", "<< _ksptype << " iterations : " << _PetscIts<< " maximum variation ||Uk+1-Uk||: " << _erreur_rel << endl;
+                       PetscPrintf(PETSC_COMM_WORLD," Newton iteration %d, %s iterations : %d maximum variation ||Uk+1-Uk||: %.2f\n",_NEWTON_its,_ksptype,_PetscIts,_erreur_rel);
                        *_runLogFile<< " Newton iteration " << _NEWTON_its<< ", "<< _ksptype << " iterations : " << _PetscIts<< " maximum variation ||Uk+1-Uk||: " << _erreur_rel << endl;
 
                        if(_conditionNumber)
                        {
                                PetscReal sv_max, sv_min;
                                KSPComputeExtremeSingularValues(_ksp, &sv_max, &sv_min);
-                               cout<<" Singular value max = " << sv_max <<", singular value min = " << sv_min <<", condition number = " << sv_max/sv_min <<endl;
+                               PetscPrintf(PETSC_COMM_WORLD," Singular value max = %.2f, singular value min = %.2f, condition number = %.2f\n",sv_max,sv_min,sv_max/sv_min);
                                *_runLogFile<<" Singular value max = " << sv_max <<", singular value min = " << sv_min <<", condition number = " << sv_max/sv_min <<endl;
                        }
                }
@@ -573,17 +675,17 @@ bool ProblemCoreFlows::solveTimeStep(){
        }
        if(!converged){
                if(_NEWTON_its >= _maxNewtonIts){
-                       cout << "Maximum number of Newton iterations "<<_maxNewtonIts<<" reached"<< endl;
+                       PetscPrintf(PETSC_COMM_WORLD,"Maximum number of Newton iterations %d reached\n",_maxNewtonIts);
                        *_runLogFile << "Maximum number of Newton iterations "<<_maxNewtonIts<<" reached"<< endl;
                }
                else if(!ok){
-                       cout<<"iterateTimeStep: solving Newton iteration "<<_NEWTON_its<<" Failed"<<endl;
+                       PetscPrintf(PETSC_COMM_WORLD,"iterateTimeStep: solving Newton iteration %d Failed\n",_NEWTON_its);
                        *_runLogFile<<"iterateTimeStep: solving Newton iteration "<<_NEWTON_its<<" Failed"<<endl;
                }
        }
        else if(_timeScheme == Implicit && (_nbTimeStep-1)%_freqSave ==0)
        {
-               cout << "Nombre d'iterations de Newton "<< _NEWTON_its << ", Nombre max d'iterations "<< _ksptype << " : " << _MaxIterLinearSolver << endl << endl;
+               PetscPrintf(PETSC_COMM_WORLD,"Nombre d'iterations de Newton %d, Nombre max d'iterations %s : %d\n\n",_NEWTON_its, _ksptype, _MaxIterLinearSolver);
                *_runLogFile <<endl;
                *_runLogFile << "Nombre d'iterations de Newton "<< _NEWTON_its << "Nombre max d'iterations "<< _ksptype << " : " << _MaxIterLinearSolver << endl << endl;
                _MaxIterLinearSolver = 0;
index 731b5a72c4c30b159f06af7d3d87a86e9f21b0a4..ff58beb41415aa9096989ba9a630a3f732b4c6b8 100755 (executable)
@@ -3,7 +3,8 @@
 
 using namespace std;
 
-ProblemFluid::ProblemFluid(void){
+ProblemFluid::ProblemFluid(MPI_Comm comm):ProblemCoreFlows(comm)
+{
        _latentHeat=1e30;
        _Tsat=1e30;
        _Psat=-1e30;
index 44ae333bfbfbb811805c547e9eb6f3c044f18d95..a2d5c778f1befd5b833694eaceb8afbaf1773410 100755 (executable)
@@ -1,4 +1,5 @@
 #include "StationaryDiffusionEquation.hxx"
+#include "DiffusionEquation.hxx"
 #include "Node.hxx"
 #include "SparseMatrixPetsc.hxx"
 #include "math.h"
@@ -8,51 +9,24 @@
 
 using namespace std;
 
-int StationaryDiffusionEquation::fact(int n)
-{
-  return (n == 1 || n == 0) ? 1 : fact(n - 1) * n;
-}
-int StationaryDiffusionEquation::unknownNodeIndex(int globalIndex, std::vector< int > dirichletNodes) 
-{//assumes Dirichlet node numbering is strictly increasing
-    int j=0;//indice de parcours des noeuds frontière avec CL Dirichlet
-    int boundarySize=dirichletNodes.size();
-    while(j<boundarySize and dirichletNodes[j]<globalIndex)
-        j++;
-    if(j==boundarySize)
-        return globalIndex-boundarySize;
-    else if (dirichletNodes[j]>globalIndex)
-        return globalIndex-j;
-    else
-        throw CdmathException("StationaryDiffusionEquation::unknownNodeIndex : Error : node is a Dirichlet boundary node");
-}
-
-int StationaryDiffusionEquation::globalNodeIndex(int unknownNodeIndex, std::vector< int > dirichletNodes)
-{//assumes Dirichlet boundary node numbering is strictly increasing
-    int boundarySize=dirichletNodes.size();
-    /* trivial case where all boundary nodes are Neumann BC */
-    if(boundarySize==0)
-        return unknownNodeIndex;
-        
-    double unknownNodeMax=-1;//max unknown node number in the interval between jth and (j+1)th Dirichlet boundary nodes
-    int j=0;//indice de parcours des noeuds frontière
-    //On cherche l'intervale [j,j+1] qui contient le noeud de numéro interieur unknownNodeIndex
-    while(j+1<boundarySize and unknownNodeMax<unknownNodeIndex)
-    {
-        unknownNodeMax += dirichletNodes[j+1]-dirichletNodes[j]-1;
-        j++;
-    }    
-
-    if(j+1==boundarySize)
-        return unknownNodeIndex+boundarySize;
-    else //unknownNodeMax>=unknownNodeIndex, hence our node global number is between dirichletNodes[j-1] and dirichletNodes[j]
-        return unknownNodeIndex - unknownNodeMax + dirichletNodes[j]-1;
-}
-
-StationaryDiffusionEquation::StationaryDiffusionEquation(int dim, bool FECalculation, double lambda){
+StationaryDiffusionEquation::StationaryDiffusionEquation(int dim, bool FECalculation, double lambda,MPI_Comm comm){
+       /* Initialisation of PETSC */
+       //check if PETSC is already initialised
        PetscBool petscInitialized;
        PetscInitialized(&petscInitialized);
        if(!petscInitialized)
-               PetscInitialize(NULL,NULL,0,0);
+       {//check if MPI is already initialised
+               int mpiInitialized;
+               MPI_Initialized(&mpiInitialized);
+               if(mpiInitialized)
+                       PETSC_COMM_WORLD = comm;
+               PetscInitialize(NULL,NULL,0,0);//Note this is ok if MPI has been been initialised independently from PETSC
+       }
+       MPI_Comm_rank(PETSC_COMM_WORLD,&_rank);
+       MPI_Comm_size(PETSC_COMM_WORLD,&_size);
+       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. 
+       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. 
+       PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);
 
     if(lambda < 0.)
     {
@@ -121,6 +95,11 @@ StationaryDiffusionEquation::StationaryDiffusionEquation(int dim, bool FECalcula
        _heatPowerFieldSet=false;
        _heatTransfertCoeff=0;
        _heatSource=0;
+
+    /* Default diffusion tensor is diagonal */
+       _DiffusionTensor=Matrix(_Ndim);
+       for(int idim=0;idim<_Ndim;idim++)
+               _DiffusionTensor(idim,idim)=_conductivity;
 }
 
 void StationaryDiffusionEquation::initialize()
@@ -145,9 +124,6 @@ void StationaryDiffusionEquation::initialize()
         }
     }
     
-       _DiffusionTensor=Matrix(_Ndim);
-       for(int idim=0;idim<_Ndim;idim++)
-               _DiffusionTensor(idim,idim)=1;
        /**************** Field creation *********************/
 
        if(!_heatPowerFieldSet){
@@ -279,27 +255,6 @@ double StationaryDiffusionEquation::computeTimeStep(bool & stop){
        return _dt_src;
 }
 
-Vector StationaryDiffusionEquation::gradientNodal(Matrix M, vector< double > values)
-{
-       if(! M.isSquare() )
-               throw CdmathException("DiffusionEquation::gradientNodal Matrix M should be square !!!");
-               
-       int Ndim = M.getNumberOfRows();
-    vector< Matrix > matrices(Ndim);
-    
-    for (int idim=0; idim<Ndim;idim++){
-        matrices[idim]=M.deepCopy();
-        for (int jdim=0; jdim<Ndim+1;jdim++)
-                       matrices[idim](jdim,idim) = values[jdim] ;
-    }
-
-       Vector result(Ndim);
-    for (int idim=0; idim<Ndim;idim++)
-        result[idim] = matrices[idim].determinant();
-
-       return result;    
-}
-
 double StationaryDiffusionEquation::computeDiffusionMatrix(bool & stop)
 {
     double result;
@@ -354,21 +309,21 @@ double StationaryDiffusionEquation::computeDiffusionMatrixFE(bool & stop){
             M(idim,_Ndim)=1;
         }
         for (int idim=0; idim<_Ndim+1;idim++)
-            GradShapeFuncs[idim]=gradientNodal(M,values[idim])/fact(_Ndim);
+            GradShapeFuncs[idim]=DiffusionEquation::gradientNodal(M,values[idim])/DiffusionEquation::fact(_Ndim);
 
         /* Loop on the edges of the cell */
         for (int idim=0; idim<_Ndim+1;idim++)
         {
             if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[idim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[idim])
             {//First node of the edge is not Dirichlet node
-                i_int=unknownNodeIndex(nodeIds[idim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
+                i_int=DiffusionEquation::unknownNodeIndex(nodeIds[idim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
                 dirichletCell_treated=false;
                 for (int jdim=0; jdim<_Ndim+1;jdim++)
                 {
                     if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),nodeIds[jdim])==_dirichletNodeIds.end())//!_mesh.isBorderNode(nodeIds[jdim])
                     {//Second node of the edge is not Dirichlet node
-                        j_int= unknownNodeIndex(nodeIds[jdim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
-                        MatSetValue(_A,i_int,j_int,_conductivity*(_DiffusionTensor*GradShapeFuncs[idim])*GradShapeFuncs[jdim]/Cj.getMeasure(), ADD_VALUES);
+                        j_int= DiffusionEquation::unknownNodeIndex(nodeIds[jdim], _dirichletNodeIds);//assumes Dirichlet boundary node numbering is strictly increasing
+                        MatSetValue(_A,i_int,j_int,(_DiffusionTensor*GradShapeFuncs[idim])*GradShapeFuncs[jdim]/Cj.getMeasure(), ADD_VALUES);
                     }
                     else if (!dirichletCell_treated)
                     {//Second node of the edge is a Dirichlet node
@@ -386,8 +341,8 @@ double StationaryDiffusionEquation::computeDiffusionMatrixFE(bool & stop){
                             else
                                 valuesBorder[kdim]=0;                            
                         }
-                        GradShapeFuncBorder=gradientNodal(M,valuesBorder)/fact(_Ndim);
-                        coeff =-_conductivity*(_DiffusionTensor*GradShapeFuncBorder)*GradShapeFuncs[idim]/Cj.getMeasure();
+                        GradShapeFuncBorder=DiffusionEquation::gradientNodal(M,valuesBorder)/DiffusionEquation::fact(_Ndim);
+                        coeff =-1.*(_DiffusionTensor*GradShapeFuncBorder)*GradShapeFuncs[idim]/Cj.getMeasure();
                         VecSetValue(_b,i_int,coeff, ADD_VALUES);                        
                     }
                 }
@@ -402,21 +357,22 @@ double StationaryDiffusionEquation::computeDiffusionMatrixFE(bool & stop){
         int NboundaryFaces=boundaryFaces.size();
         for(int i = 0; i< NboundaryFaces ; i++)//On parcourt les faces du bord
         {
-            Face Fi = _mesh.getFace(i);
+            Face Fi = _mesh.getFace(boundaryFaces[i]);
             for(int j = 0 ; j<_Ndim ; j++)//On parcourt les noeuds de la face
             {
-                if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Fi.getNodeId(j))==_dirichletNodeIds.end())//node j is an Neumann BC node (not a Dirichlet BC node)
+                if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Fi.getNodeId(j))==_dirichletNodeIds.end())//node j is a Neumann BC node (not a Dirichlet BC node)
                 {
-                    j_int=unknownNodeIndex(Fi.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
+                    j_int=DiffusionEquation::unknownNodeIndex(Fi.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
                     if( _neumannValuesSet )
                         coeff =Fi.getMeasure()/_Ndim*_neumannBoundaryValues[Fi.getNodeId(j)];
-                    else    
+                    else
                         coeff =Fi.getMeasure()/_Ndim*_limitField[_mesh.getNode(Fi.getNodeId(j)).getGroupName()].normalFlux;
                     VecSetValue(_b, j_int, coeff, ADD_VALUES);
                 }
             }
         }
     }
+
     MatAssemblyBegin(_A, MAT_FINAL_ASSEMBLY);
        MatAssemblyEnd(_A, MAT_FINAL_ASSEMBLY);
        VecAssemblyBegin(_b);
@@ -469,7 +425,7 @@ double StationaryDiffusionEquation::computeDiffusionMatrixFV(bool & stop){
         }
 
                //Compute velocity at the face Fj
-               dn=_conductivity*(_DiffusionTensor*normale)*normale;
+               dn=(_DiffusionTensor*normale)*normale;
 
                // compute 1/dxi = volume of Ci/area of Fj
         inv_dxi = Fj.getMeasure()/Cell1.getMeasure();
@@ -503,8 +459,7 @@ double StationaryDiffusionEquation::computeDiffusionMatrixFV(bool & stop){
                     MatSetValue(_A,idm,idm,dn*inv_dxi/barycenterDistance                           , ADD_VALUES);
                     VecSetValue(_b,idm,    dn*inv_dxi/barycenterDistance*_limitField[nameOfGroup].T, ADD_VALUES);
                 }
-                else {//Problem for 3D tetrahera 
-                                       //cout<< "Fj.getGroupNames().size()= "<<Fj.getGroupNames().size()<<", Fj.x()= "<<Fj.x()<<", Fj.y()= "<<Fj.y()<<", Fj.z()= "<<Fj.z()<<endl;
+                else {
                     stop=true ;
                     cout<<"!!!!!!!!!!!!!!! Error StationaryDiffusionEquation::computeDiffusionMatrixFV !!!!!!!!!!"<<endl;
                     cout<<"!!!!!! No boundary condition set for boundary named "<<nameOfGroup<< "!!!!!!!!!! _limitField[nameOfGroup].bcType= "<<_limitField[nameOfGroup].bcType<<endl;
@@ -567,13 +522,13 @@ double StationaryDiffusionEquation::computeDiffusionMatrixFV(bool & stop){
     return INFINITY;
 }
 
-double StationaryDiffusionEquation::computeRHS(bool & stop)//Contribution of the PDE RHS to the linear systemm RHS (boundary conditions do contribute to the system RHS via the function computeDiffusionMatrix)
+double StationaryDiffusionEquation::computeRHS(bool & stop)//Contribution of the PDE RHS to the linear systemm RHS (boundary conditions do contribute to the system RHS via the function computeDiffusionMatrix
 {
        VecAssemblyBegin(_b);
 
     if(!_FECalculation)
         for (int i=0; i<_Nmailles;i++)
-            VecSetValue(_b,i,_heatTransfertCoeff*_fluidTemperatureField(i) + _heatPowerField(i),ADD_VALUES);
+            VecSetValue(_b,i, _heatTransfertCoeff*_fluidTemperatureField(i) + _heatPowerField(i) ,ADD_VALUES);
     else
         {
             Cell Ci;
@@ -586,7 +541,7 @@ double StationaryDiffusionEquation::computeRHS(bool & stop)//Contribution of the
                     if(!_mesh.isBorderNode(nodesId[j])) 
                     {
                         double coeff = _heatTransfertCoeff*_fluidTemperatureField(nodesId[j]) + _heatPowerField(nodesId[j]);
-                        VecSetValue(_b,unknownNodeIndex(nodesId[j], _dirichletNodeIds), coeff*Ci.getMeasure()/(_Ndim+1),ADD_VALUES);
+                        VecSetValue(_b,DiffusionEquation::unknownNodeIndex(nodesId[j], _dirichletNodeIds), coeff*Ci.getMeasure()/(_Ndim+1),ADD_VALUES);
                     }
             }
         }
@@ -651,13 +606,18 @@ bool StationaryDiffusionEquation::iterateNewtonStep(bool &converged)
         VecAssemblyBegin(_deltaT);
         VecAssemblyEnd(  _deltaT);
 
-               for(int i=0; i<_VV.getNumberOfElements(); i++)
+               if(_verbose)
+                       cout<<"Début calcul de la variation relative"<<endl;
+
+               for(int i=0; i<_NunknownNodes; i++)
                {
                        VecGetValues(_deltaT, 1, &i, &dTi);
                        VecGetValues(_Tk, 1, &i, &Ti);
                        if(_erreur_rel < fabs(dTi/Ti))
                                _erreur_rel = fabs(dTi/Ti);
                }
+               if(_verbose)
+                       cout<<"Fin calcul de la variation relative, erreur relative maximale : " << _erreur_rel <<endl;
         stop=false;
         converged = (_erreur_rel <= _precision) ;//converged=convergence des iterations de Newton
     }
@@ -753,7 +713,7 @@ void StationaryDiffusionEquation::setLinearSolver(linearSolver kspType, precondi
                throw CdmathException("!!! Error : only 'GMRES', 'CG' or 'BCGS' algorithm is acceptable !!!");
        }
        // set preconditioner
-       if (pcType == NONE)
+       if (pcType == NOPC)
                _pctype = (char*)&PCNONE;
        else if (pcType ==LU)
                _pctype = (char*)&PCLU;
@@ -764,10 +724,10 @@ void StationaryDiffusionEquation::setLinearSolver(linearSolver kspType, precondi
        else if (pcType == ICC)
                _pctype = (char*)&PCICC;
        else {
-               cout << "!!! Error : only 'NONE', 'LU', 'ILU', 'CHOLESKY' or 'ICC' preconditioners are acceptable !!!" << endl;
-               *_runLogFile << "!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" << endl;
+               cout << "!!! Error : only 'NOPC', 'LU', 'ILU', 'CHOLESKY' or 'ICC' preconditioners are acceptable !!!" << endl;
+               *_runLogFile << "!!! Error : only 'NOPC' or 'LU' or 'ILU' preconditioners are acceptable !!!" << endl;
                _runLogFile->close();
-               throw CdmathException("!!! Error : only 'NONE' or 'LU' or 'ILU' preconditioners are acceptable !!!" );
+               throw CdmathException("!!! Error : only 'NOPC' or 'LU' or 'ILU' preconditioners are acceptable !!!" );
        }
 }
 
@@ -881,7 +841,7 @@ void StationaryDiffusionEquation::save(){
         for(int i=0; i<_NunknownNodes; i++)
         {
             VecGetValues(_Tk, 1, &i, &Ti);
-            globalIndex = globalNodeIndex(i, _dirichletNodeIds);
+            globalIndex = DiffusionEquation::globalNodeIndex(i, _dirichletNodeIds);
             _VV(globalIndex)=Ti;
         }
 
@@ -962,7 +922,7 @@ StationaryDiffusionEquation::getEigenvalues(int nev, EPSWhich which, double tol)
         {
             if(find(_dirichletNodeIds.begin(),_dirichletNodeIds.end(),Ci.getNodeId(j))==_dirichletNodeIds.end())//node j is an unknown node (not a Dirichlet node)
                        {
-                j_int=unknownNodeIndex(Ci.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
+                j_int=DiffusionEquation::unknownNodeIndex(Ci.getNodeId(j), _dirichletNodeIds);//indice du noeud j en tant que noeud inconnu
                 nodal_volumes[j_int]+=Ci.getMeasure()/(_Ndim+1);
             }
         }
index cdd54132dcfb447ce8c6f3b66376b7e3313b46f1..de715fd8fc6f22591945fea09eab035e88ad9d7b 100755 (executable)
@@ -5,7 +5,8 @@
 
 using namespace std;
 
-TransportEquation::TransportEquation(phase fluid, pressureMagnitude pEstimate,vector<double> vitesseTransport){
+TransportEquation::TransportEquation(phase fluid, pressureMagnitude pEstimate,vector<double> vitesseTransport, MPI_Comm comm):ProblemCoreFlows(comm)
+{
        if(pEstimate==around1bar300KTransport){
                _Tref=300;
                if(fluid==GasPhase){//Nitrogen pressure 1 bar and temperature 27°C