Index: /XIOS2/trunk/scripts/index_load.html
===================================================================
--- /XIOS2/trunk/scripts/index_load.html	(revision 2429)
+++ /XIOS2/trunk/scripts/index_load.html	(revision 2429)
@@ -0,0 +1,75 @@
+
+<head>
+  <script src="https://cdn.anychart.com/releases/8.11.0/js/anychart-base.min.js" type="text/javascript"></script>
+  <script src="https://cdn.anychart.com/releases/8.11.0/js/anychart-stock.min.js"></script>
+
+</head>
+
+<body>
+  <!--
+      <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
+
+    <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
+    <link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet" type="text/css" />
+
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
+    <link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css" rel="stylesheet" type="text/css" />
+
+    <link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
+    <script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
+
+  <div id="container" >
+    <div class="row">
+      <label class="btn btn-primary" for="file">
+        <input type="file" id="file" style="display:none" onchange="$('#upload-file-info').html(this.files[0].name)">
+        Load a JS XIOS memory file
+      </label>
+      <button type="button" class="btn btn-default disabled" id="upload-file-info">...</button>
+    </div>
+  </div>
+  -->
+
+  <div id="container" ></div>
+  <script src="mem_4.js" ></script>
+
+  <script>
+    anychart.onDocumentLoad(function () {
+
+      
+        
+    // create a data table using this data
+    var dataTable = anychart.data.table();
+    dataTable.addData(get_xios_mem_data());
+ 
+    mapping_mem = dataTable.mapAs();
+    mapping_mem.addField('value', 2);
+    mapping_event = dataTable.mapAs();
+    mapping_event.addField('value', 1);
+ 
+    // create a stock chart
+    var chart = anychart.stock();
+
+    // create a plot on the chart
+    var plot = chart.plot(0);		
+	
+    // create a line series
+    var lineSeries2 = plot.line(mapping_event);
+    lineSeries2.name("Event");
+    var lineSeries1 = plot.line(mapping_mem);
+    lineSeries1.name("Mo");
+	
+    // set the container id
+    chart.container("container");
+ 
+    // initiate drawing the chart
+    chart.draw();
+
+
+
+	
+    });
+  </script>
+  
+</body>
Index: /XIOS2/trunk/scripts/plotly_memory.js
===================================================================
--- /XIOS2/trunk/scripts/plotly_memory.js	(revision 2429)
+++ /XIOS2/trunk/scripts/plotly_memory.js	(revision 2429)
@@ -0,0 +1,108 @@
+
+Plotly.d3.select('body')
+    .append('div')
+    .html("Select a CSV XIOS file");
+
+// ------------------ select csv data
+var input = Plotly.d3.select("body").append("input")
+    .attr("type","file")
+    .attr("accept",".csv")
+    .on("change", handleFileSelect)
+
+
+// Single file handler
+function handleFileSelect() {
+    // Check for the various File API support.
+    if (window.File && window.FileReader && window.FileList && window.Blob) {
+    // Great success! All the File APIs are supported.
+    } else {
+        alert('The File APIs are not fully supported in this browser.');
+    }
+
+    var f = event.target.files[0]; // FileList object
+    var reader = new FileReader();
+
+    reader.onload = function(event) {
+        makeplot_read_selected(event.target.result)
+    };
+    // Read in the file as a data URL.
+    reader.readAsDataURL(f);
+}
+
+
+function makeplot_read_selected(filename) {
+    Plotly.d3.csv(filename,  function(d) {
+	// formating data
+ 	return {
+ 	    time: +d.time,
+ 	    event: d.event,
+ 	    vsize: +d.vsize,
+ 	    rss: +d.rss,
+ 	    VmHWM: +d.VmHWM
+ 	};
+    }, function(xios_mem_obj) {
+ 	processData(xios_mem_obj)
+    });
+};
+
+function processData(xios_mem_data) {
+
+    // transpose data to use it more easily
+    var transData = [];
+    for(var i = 0; i < 5 ; i++){
+	transData.push([]);
+    };
+    for(var i = 0; i < xios_mem_data.length ; i++){
+	//console.log( xios_mem_data[i]  );
+	transData[0].push( xios_mem_data[i].time )   // x axis
+	transData[1].push( xios_mem_data[i].vsize ) // y axis
+	transData[2].push( xios_mem_data[i].event )  // labels
+	transData[3].push( xios_mem_data[i].rss ) // y axis
+	transData[4].push( xios_mem_data[i].VmHWM ) // y axis
+    };
+    //console.log(transData[0]);
+
+    var data = [];
+    var result = {
+	x: transData[0],
+	y: transData[1],
+	type: 'scatter',
+	mode: 'markers',
+	text: transData[2],
+        name:'vsize',
+    };
+    data.push(result);
+    
+    var result2 = {
+        x: transData[0],
+        y: transData[3],
+        type: 'scatter',
+        mode: 'markers',
+        text: transData[2],
+        name:'RSS',
+    };
+    data.push(result2);
+    
+    var result3 = {
+        x: transData[0],
+        y: transData[4],
+        type: 'scatter',
+        mode: 'markers',
+        text: transData[2],
+        name:'VmHWM',
+    };
+    data.push(result3);
+
+    var layout = {
+	title: "Memory consumption",
+	xaxis: {
+	    title: "Time (s)",
+	},
+	yaxis: {
+	    title: "Memory (Mo)",
+	}
+    };
+
+    Plotly.newPlot('myDiv', data, layout);
+    
+}
Index: /XIOS2/trunk/scripts/xios_memory.html
===================================================================
--- /XIOS2/trunk/scripts/xios_memory.html	(revision 2429)
+++ /XIOS2/trunk/scripts/xios_memory.html	(revision 2429)
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
+  </head>
+
+  <body>
+    
+    <div id=myDiv></div>
+    <script src="plotly_memory.js"></script>
+		  
+  </body>
+</html>
Index: /XIOS2/trunk/src/interface/c/icmem_checker.cpp
===================================================================
--- /XIOS2/trunk/src/interface/c/icmem_checker.cpp	(revision 2429)
+++ /XIOS2/trunk/src/interface/c/icmem_checker.cpp	(revision 2429)
@@ -0,0 +1,32 @@
+
+#include "mem_checker.hpp"
+#include <string>
+#include <iostream>
+
+
+using namespace xios;
+
+extern "C"
+{
+  void cxios_mem_checker_get(double* mem)
+  {
+    std::vector<double> memories = CMemChecker::getMem();
+    if (memories.size()>1)
+    {
+      *mem=memories[1]; //rss
+    }
+    else
+    {
+      *mem = 0.;
+    }
+  }
+
+  void cxios_mem_checker_log(const char* mem_id, int len_mem_id, bool* finalize)
+  {
+    std::string str(mem_id,len_mem_id);
+    CMemChecker::logMem(str, *finalize);
+  }
+
+}
+
+
Index: /XIOS2/trunk/src/interface/fortran/imem_checker.F90
===================================================================
--- /XIOS2/trunk/src/interface/fortran/imem_checker.F90	(revision 2429)
+++ /XIOS2/trunk/src/interface/fortran/imem_checker.F90	(revision 2429)
@@ -0,0 +1,46 @@
+#include "xios_fortran_prefix.hpp"
+
+MODULE IMEM_CHECKER
+   USE, INTRINSIC :: ISO_C_BINDING
+   
+   INTERFACE ! Ne pas appeler directement/Interface FORTRAN 2003 <-> C99
+      
+      SUBROUTINE cxios_mem_checker_get(mem) BIND(C)
+         USE ISO_C_BINDING
+         REAL     (kind = C_DOUBLE), VALUE        :: mem
+      END SUBROUTINE cxios_mem_checker_get
+
+      SUBROUTINE cxios_mem_checker_log(memid, memid_size, finalize) BIND(C)
+         USE ISO_C_BINDING
+         CHARACTER(kind = C_CHAR)  , DIMENSION(*) :: memid
+         INTEGER  (kind = C_INT)   , VALUE        :: memid_size
+         LOGICAL  (kind = C_BOOL)                 :: finalize
+      END SUBROUTINE cxios_mem_checker_log
+       
+   END INTERFACE
+
+   CONTAINS ! Fonctions disponibles pour les utilisateurs.
+
+   FUNCTION xios(mem_checker_get)() RESULT(mem)
+      IMPLICIT NONE
+      REAL                                       :: mem
+      REAL(KIND=C_DOUBLE)                        :: mem_
+      
+      CALL cxios_mem_checker_get(mem_)
+      mem=mem_
+   END FUNCTION xios(mem_checker_get)
+ 
+   SUBROUTINE xios(mem_checker_log)(mem_id, finalize)
+   USE ISO_C_BINDING
+      IMPLICIT NONE
+      CHARACTER(len = *) , INTENT(IN) :: mem_id
+      LOGICAL, OPTIONAL,INTENT(IN)    :: finalize
+      LOGICAL (KIND=C_BOOL)           :: finalize_               
+
+      finalize_=.FALSE.
+      IF (PRESENT(finalize)) finalize_ = finalize
+      CALL cxios_mem_checker_log(mem_id, len(mem_id), finalize_)
+
+   END SUBROUTINE xios(mem_checker_log)
+
+END MODULE IMEM_CHECKER
Index: /XIOS2/trunk/src/mem_checker.cpp
===================================================================
--- /XIOS2/trunk/src/mem_checker.cpp	(revision 2429)
+++ /XIOS2/trunk/src/mem_checker.cpp	(revision 2429)
@@ -0,0 +1,240 @@
+#include "mem_checker.hpp"
+#include "cxios.hpp"
+#include "mpi.hpp"
+#include <string>
+#include <map>
+#include <iostream>
+#include <sstream>
+
+#include <fcntl.h>
+#include <iomanip>
+#include <unistd.h>
+#include <cstring>
+
+namespace xios
+{
+  CMemChecker CMemChecker::dummy_("") ;
+  std::map<std::string,CMemChecker> CMemChecker::allMemChecker_;
+  bool CMemChecker::enabled_=true;
+  bool CMemChecker::first_=true;
+  double CMemChecker::vsize_init_=0;
+  double CMemChecker::rss_init_=0;
+  double CMemChecker::vmhwm_init_=0;
+  double CMemChecker::time_init_=0;
+  std::ofstream CMemChecker::fout_;
+  int CMemChecker::flush_counter_=1;
+  
+  CMemChecker::CMemChecker(const std::string& name) : name_(name)
+  { 
+    if (first_) check() ;
+    reset();
+  }
+
+  void CMemChecker::check(void)
+  {
+    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
+    enabled_ &= statStream.good() ;
+    first_=false ;
+  }
+  
+  // Return vector of memories amount :
+  //   - vector[0] : virtual memory (vsize) from /proc/self/stat
+  //   - vector[1] : resident set size (rss) from /proc/self/stat
+  std::vector<double> CMemChecker::getMem(void)
+  {
+    std::vector<double> memories(0);
+    memories.clear();
+    
+    if (first_) check() ;
+    if (!enabled_) return memories;
+    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
+    std::string dummy ;
+    for(int i=1;i<=22;i++) statStream>>dummy ;
+    unsigned long vsize; 
+    statStream>>vsize ;
+    memories.push_back(vsize);
+    unsigned long rss;
+    statStream>>rss ;
+    memories.push_back(rss*4096);
+    return memories ;
+  }
+  
+  // Return vector of memories amount, register values (see _init) as first call as reference :
+  //   - vector[0] : virtual memory (vsize) from /proc/self/stat
+  //   - vector[1] : resident set size (rss) from /proc/self/stat
+  //   - vector[2] : Peak resident set size (VmHWM) from /proc/self/status
+  std::vector<double> CMemChecker::getMemories(void)
+  {
+    std::vector<double> memories;
+
+    if (first_) check() ;
+    if (!enabled_) return memories;
+    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
+    std::string dummy ;
+    for(int i=1;i<=22;i++) statStream>>dummy ;
+
+    // 1 - Virtual
+    unsigned long vsize; 
+    statStream>>vsize ;
+    if (vsize_init_==0) {
+      vsize_init_ = vsize;
+      time_init_=MPI_Wtime();
+    }
+    vsize -= vsize_init_;
+    memories.push_back(vsize);
+
+    // 2 - RSS
+    unsigned long rss;
+    statStream>>rss ;
+    if (rss_init_==0) {
+      rss_init_ = rss;
+    }
+    rss -= rss_init_;
+    rss *= 4096; //getconf("PAGE_SIZE");    
+    memories.push_back(rss);
+
+    // 3 - Peak
+    char sbuf[1024];
+    std::ifstream file( "/proc/self/status" );
+    if( file.fail() ) {
+      return memories;
+    }
+    int fd = open( "/proc/self/status", O_RDONLY, 0 );
+    int num_read=read( fd, sbuf, ( sizeof sbuf )-1 );
+    close( fd );
+    if( !num_read ) {
+      return memories;             
+    }
+    // Peak resident set size
+    char *S=strstr( sbuf, "VmHWM:" )+6;
+    double vmhwm = ( int )atoi( S );
+    if (vmhwm_init_==0) {
+      vmhwm_init_ = vmhwm;
+    }
+    vmhwm -= vmhwm_init_;
+    memories.push_back(vmhwm);
+    
+    return memories;
+  }
+  
+  void CMemChecker::logMem( std::string id, bool finalizeLog )
+  {
+    if ( !CXios::logMemory ) return ;
+
+    int rk = 0;
+    MPI_Comm_rank( MPI_COMM_WORLD, &rk );
+    std::string logName("xios_memory_"+std::to_string(rk)+".csv");
+    vector<double> mem = getMemories();
+    if (!mem[0]) {
+      fout_.open( logName );
+      fout_ << "time,event,vsize,rss,VmHWM" << std::endl;
+    }
+
+    fout_.precision(4);
+    // Time format : YYYY-MM-DD HH:MM:SS.XXX -> seconds * 1000.
+    fout_ << (MPI_Wtime()-time_init_) << "," << id
+          << "," << mem[0]/1024./1024.
+          << "," << mem[1]/1024./1024.
+          << "," << mem[2]/1024.
+          << std::endl;
+
+    if ((MPI_Wtime()-time_init_)>flush_counter_*600.)
+    {
+      fout_.flush();
+      flush_counter_++;
+    }
+    
+    if (finalizeLog)
+    {
+      fout_.close();
+    }
+  }
+
+  
+  void CMemChecker::suspend(void)
+  {
+    if (first_) check() ;
+    if (!enabled_) return ;
+    if (!suspended_)
+    {
+      vector<double> mem = getMem();
+      cumulatedMem_.resize( mem.size() );
+      for (int i=0;i<mem.size() ; i++)
+      {
+        cumulatedMem_[i] += mem[i] - lastMem_[i];
+      }
+    }
+    suspended_ = true;
+  }
+  
+  void CMemChecker::resume(void)
+  {
+    if (first_) check() ;
+    if (!enabled_) return ;
+    if (suspended_)
+    {
+      vector<double> mem = getMem();
+      lastMem_.resize( mem.size() );
+      for (int i=0;i<mem.size() ; i++)
+      {
+        lastMem_[i] = mem[i];
+      }
+    }
+    suspended_ = false;
+  }
+
+  void CMemChecker::reset(void)
+  {
+    if (first_) check() ;
+    if (!enabled_) return ;
+    cumulatedMem_.clear();
+    suspended_ = true;
+  }
+  
+  std::vector<double> CMemChecker::getCumulatedMem(void)
+  {
+    std::vector<double> memories;
+    memories.clear();
+    if (first_) check() ;
+    if (!enabled_) return memories;
+    return cumulatedMem_;
+  }
+  
+  CMemChecker& CMemChecker::get(const std::string name)
+  {
+    if (first_) check() ;
+    if (!enabled_) return dummy_ ;
+    else
+    {
+      std::map<std::string,CMemChecker>::iterator it = allMemChecker_.find(name);
+      if (it == allMemChecker_.end())
+        it = allMemChecker_.insert(std::make_pair(name, CMemChecker(name))).first;
+      return it->second;
+    }
+  }
+
+  std::string CMemChecker::getAllCumulatedMem(void)
+  {
+    if (first_) check() ;
+    if (!enabled_) return std::string(" MemChecker : memory consumption report not available") ; 
+    std::ostringstream strOut ;
+    const double Kb=1024 ;
+    const double Mb=Kb*1024 ;
+    const double Gb=Mb*1024 ;
+    const double Tb=Gb*1024 ;
+    for(std::map<std::string,CMemChecker>::iterator it=allMemChecker_.begin();it!=allMemChecker_.end();++it)
+    {  
+      vector<double> mem=it->second.getCumulatedMem() ;
+      if (mem.size()>0)
+      {
+        strOut<<"MemChecker : "<<it->first<<"    -->   consumed memory : " ;      
+        if ((fabs(mem[0])>=Tb)||(fabs(mem[1])>=Tb)) strOut<< mem[0] / Tb<<" Tb - "<<mem[1] / Tb<<" Tb"<<std::endl ;
+        else if ((fabs(mem[0])>=Gb)||(fabs(mem[1])>=Gb)) strOut<< mem[0] / Gb<<" Gb - "<<mem[1] / Gb<<" Gb"<<std::endl ;
+        else if ((fabs(mem[0])>=Mb)||(fabs(mem[1])>=Mb)) strOut<< mem[0] / Mb<<" Mb - "<<mem[1] / Mb<<" Mb"<<std::endl ;
+        else if ((fabs(mem[0])>=Kb)||(fabs(mem[1])>=Kb)) strOut<< mem[0] / Kb<<" Kb - "<<mem[1] / Kb<<" Kb"<<std::endl ;
+        else strOut<< mem[0] <<" bytes - "<<mem[1] <<" bytes"<<std::endl ;
+      }
+    }
+    return strOut.str() ;
+  }
+}
Index: /XIOS2/trunk/src/mem_checker.hpp
===================================================================
--- /XIOS2/trunk/src/mem_checker.hpp	(revision 2429)
+++ /XIOS2/trunk/src/mem_checker.hpp	(revision 2429)
@@ -0,0 +1,50 @@
+#ifndef __XIOS_MEM_CHECKER_HPP__
+#define __XIOS_MEM_CHECKER_HPP__
+
+#include <string>
+#include <map>
+#include <fstream>
+#include <vector>
+
+namespace xios
+{
+  class CMemChecker
+  {
+    public:
+      CMemChecker(const std::string& name);
+      void suspend(void);
+      void resume(void);
+      void reset(void);
+      std::vector<double> getCumulatedMem(void);
+      static std::vector<double> getMem(void);
+      static std::vector<double> getMemories(void);
+      static void logMem( std::string id, bool finalizeLog = false );
+      static CMemChecker& get(std::string name);
+      static std::string getAllCumulatedMem(void) ;
+      static void disable(void) { enabled_=false ;}
+      static void enable(void) {enabled_=true ;}
+      static void release(void) {allMemChecker_.clear();}
+    private:
+      static void check(void) ;
+      std::vector<double> cumulatedMem_;
+      std::vector<double> lastMem_;
+      bool suspended_;
+      std::string name_;
+
+      static std::map<std::string,CMemChecker> allMemChecker_;
+      static CMemChecker dummy_ ;
+      static bool first_ ;
+      static bool enabled_ ;
+
+      static double vsize_init_;
+      static double rss_init_;
+      static double vmhwm_init_;
+      static double time_init_;
+      static std::ofstream fout_;
+      static int flush_counter_;
+  };
+}
+
+
+
+#endif
