From fb73e883850d2ce45ebd47ffaf4ab219620fbda5 Mon Sep 17 00:00:00 2001
From: Lizzzka007 <gashchuk2011@mail.ru>
Date: Tue, 3 Jan 2023 00:46:06 +0300
Subject: [PATCH] Rename Jikan functions

---
 Jikan.cpp        | 361 +++++++++++++++++++++++++----------------------
 Jikan.h          | 136 +++++++++++++-----
 JikanDepths.cpp  | 234 ++++++++++++++++++++++++++++++
 JikanDepths.h    |  57 ++++++++
 JikanWrapper.cpp | 253 ---------------------------------
 JikanWrapper.h   | 111 ---------------
 6 files changed, 580 insertions(+), 572 deletions(-)
 create mode 100644 JikanDepths.cpp
 create mode 100644 JikanDepths.h
 delete mode 100644 JikanWrapper.cpp
 delete mode 100644 JikanWrapper.h

diff --git a/Jikan.cpp b/Jikan.cpp
index 111f567..c60294d 100644
--- a/Jikan.cpp
+++ b/Jikan.cpp
@@ -1,234 +1,253 @@
 #include "Jikan.h"
-#include "ToJSON.h"
+#include "JikanWrapper.h"
 
-#include <iostream>
-#include <map>
-#include <string>
+#ifdef INCLUDE_OPEN_MP
+    #include "omp.h"
+#endif
 
-using namespace std;
+#ifdef INCLUDE_MPI
+    #include "mpi.h"
+#endif
 
-class Jikan Timer;
+using namespace std;
 
-Jikan::Jikan()
+extern "C"
 {
-    this->EventType["Synchronous events"] = set<string>();
-    this->EventType["Asynchronous events"] = set<string>();
-    this->EventType["CUDA events"] = set<string>();
-
-    this->JSONname = OUTPUT_NAME + string(".json");
-    this->JSONdata = "";
-    this->Error = "";
-};
+    extern class Jikan Timer;
 
-#ifdef INCLUDE_MPI
-    bool Jikan::ifWriteProc(MPI_Comm comm, int id)
+    void TimerStart(const char* name)
     {
-        bool if_write = false;
-        int init_flag, fin_flag, iproc;
-
-        MPI_Initialized(&init_flag);
-        MPI_Finalized(&fin_flag);
-
-        bool if_MPI = (init_flag) && (!fin_flag);
-        if(if_MPI)
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
         {
-            MPI_Comm_rank(comm, &iproc);
-            if( iproc == id)
-                if_write = true;
-        }
-        else
-            if_write = true;
+    #endif
+        
+        string str_name = name;
 
+        Timer.Jikan_start(str_name);
 
-        return if_write;
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
     }
-#else
-    bool Jikan::ifWriteProc()
+
+    void TimerEnd(const char* name)
     {
-        return true;
-    }
-#endif
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
+        
+        string str_name = name;
 
-Jikan::~Jikan()
-{
-    this->Events.clear();
-    map<string, set<string> >::iterator it;
+        Timer.Jikan_end(str_name);
 
-    for(it = this->EventType.begin(); it!=this->EventType.end(); ++it)
-        it->second.clear();
-    this->EventType.clear();
-}
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
+    }
 
-bool Jikan::ifContains(const string& Name)
-{
-    map<string, EventData>::iterator it;
+#ifdef INCLUDE_MPI
+    void MPI_SyncTimerStart(const char* name)
+    {
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
+        
+        string str_name = name;
 
-    it = this->Events.find(Name);
-    if (it == this->Events.end())
-        return false;
+        int init_flag, fin_flag;
 
-    return true;
-}
+        MPI_Initialized(&init_flag);
+        MPI_Finalized(&fin_flag);
 
-void Jikan::Jikan_sync_start(const string& name)
-{
-    bool ExistFlag;
-    ExistFlag = this->ifContains(name);
+        if((!fin_flag) && init_flag)
+            MPI_Barrier(MPI_COMM_WORLD);
 
-    if(ExistFlag)
-    {
-        chrono_time_type start = chrono::steady_clock::now();
-        (this->Events)[name].start = start;
+        Timer.Jikan_sync_start(str_name);
+
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
     }
-    else
+
+    void MPI_SyncTimerEnd(const char* name)
     {
-        this->EventType["Synchronous events"].insert(name);
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
+        string str_name = name;
 
-        (this->Events)[name] = EventData(name);
-        chrono_time_type start = chrono::steady_clock::now();
-        (this->Events)[name].start = start;
-    }
+        int init_flag, fin_flag;
 
-    (this->Events)[name].ifStart = true;
-}
+        MPI_Initialized(&init_flag);
+        MPI_Finalized(&fin_flag);
 
-void Jikan::Jikan_sync_end(const string& name)
-{
-    bool ExistFlag, ifStart;
-    ExistFlag = this->ifContains(name);
-    ifStart = (this->Events)[name].ifStart;
+        if((!fin_flag) && init_flag)
+            MPI_Barrier(MPI_COMM_WORLD);
 
-    if((!ExistFlag) || (!ifStart))
-        return;
+        Timer.Jikan_sync_end(str_name);
 
-    chrono_time_type end = chrono::steady_clock::now();
-    chrono_time_type start = (this->Events)[name].start;
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
+    }
 
-    double main_elapsed = chrono::duration_cast<chrono::nanoseconds>(end - start).count() * 1e-9;
+    void MPI_SyncTimerStartCustom(const char* name, MPI_Comm comm)
+    {
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
+        string str_name = name;
 
-    (this->Events)[name].elapsed_time += main_elapsed;
-    (this->Events)[name].count ++;
+        int init_flag, fin_flag;
 
-#ifdef SAVE_TIME_SERIES
-    (this->Events)[name].time_series.push_back(main_elapsed);
-#endif
+        MPI_Initialized(&init_flag);
+        MPI_Finalized(&fin_flag);
 
-    (this->Events)[name].ifStart = false;
-}
+        if((!fin_flag) && init_flag)
+            MPI_Barrier(MPI_COMM_WORLD);
 
-void Jikan::Jikan_start(const string& name)
-{
-    bool ExistFlag;
-    ExistFlag = this->ifContains(name);
+        Timer.Jikan_sync_start(str_name);
 
-    if(ExistFlag)
-    {
-        chrono_time_type start = chrono::steady_clock::now();
-        (this->Events)[name].start = start;
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
     }
-    else
+
+    void MPI_SyncTimerEndCustom(const char* name, MPI_Comm comm)
     {
-        this->EventType["Asynchronous events"].insert(name);
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif        
+        string str_name = name;
 
-        (this->Events)[name] = EventData(name);
-        chrono_time_type start = chrono::steady_clock::now();
-        (this->Events)[name].start = start;
-    }
+        int init_flag, fin_flag;
 
-    (this->Events)[name].ifStart = true;
-}
+        MPI_Initialized(&init_flag);
+        MPI_Finalized(&fin_flag);
 
-void Jikan::Jikan_end(const string& name)
-{
-    bool ExistFlag, ifStart;
-    ExistFlag = this->ifContains(name);
-    ifStart = (this->Events)[name].ifStart;
+        if((!fin_flag) && init_flag)
+            MPI_Barrier(comm);
 
-    if((!ExistFlag) || (!ifStart))
-        return;
+        Timer.Jikan_sync_end(str_name);
 
-    chrono_time_type end = chrono::steady_clock::now();
-    chrono_time_type start = (this->Events)[name].start;
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
+    }
 
-    double main_elapsed = chrono::duration_cast<chrono::nanoseconds>(end - start).count() * 1e-9;
+    void WriteOutputCustom(MPI_Comm comm, int id)
+    {
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
 
-    (this->Events)[name].elapsed_time += main_elapsed;
-    (this->Events)[name].count ++;
+        bool ifWrite = Timer.ifWriteProc(comm, id);
+        if(ifWrite == true)
+            Timer.GenerateOutputData();
 
-#ifdef SAVE_TIME_SERIES
-    (this->Events)[name].time_series.push_back(main_elapsed);
-#endif
+        #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
+    }
 
-    (this->Events)[name].ifStart = false;
-}
+    void WriteOutput(int id)
+    {
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
 
-void Jikan::GenerateTypedOutputData(const string& EventType, string& EventTypeString)
-{
-    const int n = this->EventType[EventType].size();
-    EventTypeString = JSON::StartTypedBlock(EventType);
+        bool ifWrite = Timer.ifWriteProc(MPI_COMM_WORLD, id);
+        // cout << ifWrite << endl;
+        if(ifWrite == true)
+            Timer.GenerateOutputData();
 
-    if(n == 0)
-    {
-        EventTypeString += "\n\t}";
-        return;
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
     }
 
-    string Row;
-    string Name;
-    set<string>::iterator it;
-    set<string>::iterator end_m = this->EventType[EventType].end();
-    --end_m;
+#else
+    void WriteOutput()
+    {
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
+    
+        bool ifWrite = Timer.ifWriteProc();
+        if(ifWrite == true)
+            Timer.GenerateOutputData();
 
-    for (it = this->EventType[EventType].begin(); it != end_m; ++it)
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
+    }
+#endif
+
+#ifdef INCLUDE_OPEN_MP
+    void OpenMP_SyncTimerStart(const char* name)
     {
-        Name = *it;
-        JSON::GenerateRow(this->Events[Name], Row, JSON::SeparateRows);
-        EventTypeString += Row;
+        #pragma omp barrier
+        #pragma omp master
+        {
+            string str_name = name;
+
+            Timer.Jikan_sync_start(str_name);
+        }
     }
 
-    Name = *end_m;
-    JSON::GenerateRow(this->Events[Name], Row, JSON::FinishRows);
-    EventTypeString += Row;
-}
+    void OpenMP_SyncTimerEnd(const char* name)
+    {
+        #pragma omp barrier
+        #pragma omp master
+        {
+            string str_name = name;
 
-void Jikan::GenerateOutputData()
-{
-    map<string, set<string> >::iterator it;
-    map<string, set<string> >::iterator end_m = this->EventType.end();
-    --end_m;
-
-    string Name;
-    string Out = "{ ";
-    string TypedOutput;
-
-    for(it = this->EventType.begin(); it!=end_m; ++it)
-    {    
-        Name = it->first;
-        TypedOutput = "";
-        this->GenerateTypedOutputData(Name, TypedOutput);
-        Out += TypedOutput + ",\n";
+            Timer.Jikan_sync_end(str_name);
+        }
     }
+#endif
+//--------
 
-    Name = end_m->first;
-    TypedOutput = "";
-    this->GenerateTypedOutputData(Name, TypedOutput);
-    Out += TypedOutput + "\n}";
+#ifdef INCLUDE_GPU_TIMER
+    void CudaTimerStart(const char* name)
+    {
+    #ifdef INCLUDE_OPEN_MP
+        #pragma omp master
+        {
+    #endif
 
-    this->JSONdata = Out;
+        string str_name = name;
 
-    bool OutputRes = JSON::WriteOutput(this->JSONname, this->JSONdata);
+        Timer.cuda_Jikan_start(str_name);
 
-    if(OutputRes != true)
-    {
-        this->Error = JSON::Error;
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
     }
+    
+    void CudaTimerEnd(const char* name)
+    {
+    #ifdef INCLUDE_OPEN_MP
 
-    #ifdef INCLUDE_GPU_TIMER
-        this->FreeCudaEvents();
+        #pragma omp master
+        {
     #endif
-}
+        string str_name = name;
 
-void Jikan::SetDumpFilename(const std::string& name)
-{
-    this->JSONname = name;
+        Timer.cuda_Jikan_end(str_name);
+
+    #ifdef INCLUDE_OPEN_MP
+        }
+    #endif
+    }
+#endif
 }
\ No newline at end of file
diff --git a/Jikan.h b/Jikan.h
index b67ae99..38cb838 100644
--- a/Jikan.h
+++ b/Jikan.h
@@ -1,57 +1,119 @@
 #pragma once
 
-#include "JikanWrapper.h"
-#include "Jikan-config.h"
-#include "Event.h"
+//------------------------- Jikan-config ---------------------------------------------
+#define TIMER_ON
+#define INCLUDE_GPU_TIMER
+#define INCLUDE_MPI
+#define INCLUDE_OPEN_MP
+#define SAVE_TIME_SERIES
+
+#define OUTPUT_NAME "Jikan-output"
+//------------------------------------------------------------------------------------
 
-#include <iostream>
-#include <string>
-#include <set>
 #ifdef INCLUDE_MPI
-    #include <mpi.h>
+        #include <mpi.h>
+#endif 
+
+#ifdef __cplusplus
+extern "C" {  
+#endif                  
+        void TimerStart(const char* name);
+        void TimerEnd(const char* name);
+
+//------------------------- Asynchronous timer mode functions -------------------------
+#ifdef TIMER_ON
+        #define START_JIKAN_TIMER(name) TimerStart(name);
+        #define END_JIKAN_TIMER(name) TimerEnd(name);
+#else
+        #define START_JIKAN_TIMER(name)
+        #define END_JIKAN_TIMER(name)
 #endif
+//-------------------------------------------------------------------------------------
 
-class Jikan
-{
-public:
-    std::map<std::string, EventData> Events;
-    std::map<std::string, std::set<std::string> > EventType;
-    std::string JSONname;
-    std::string JSONdata;
-    std::string Error;
+//------------------------- MPI-synchronous timer mode functions ----------------------
+#ifdef INCLUDE_MPI
+                void MPI_SyncTimerStart(const char* name);
+                void MPI_SyncTimerEnd(const char* name);
 
-    Jikan();
-    ~Jikan();
+                #define MPI_SYNC_JIKAN_TIMER_START_DEF(name) MPI_SyncTimerStart(name);
+                #define MPI_SYNC_JIKAN_TIMER_END_DEF(name) MPI_SyncTimerEnd(name);
 
-    void Jikan_sync_start(const std::string& name);
-    void Jikan_sync_end(  const std::string& name);
+                void MPI_SyncTimerStartCustom(const char* name, MPI_Comm comm);
+                void MPI_SyncTimerEndCustom(const char* name, MPI_Comm comm);
 
-    void Jikan_start(const std::string& name);
-    void Jikan_end(  const std::string& name);
+                #define MPI_SYNC_JIKAN_TIMER_START_CUSTOM(name, comm) MPI_SyncTimerStartCustom(name, comm);
+                #define MPI_SYNC_JIKAN_TIMER_END_CUSTOM(name, comm) MPI_SyncTimerEndCustom(name, comm);
 
-#ifdef INCLUDE_GPU_TIMER
-    void cuda_Jikan_start(const std::string& name);
-    void cuda_Jikan_end(  const std::string& name);
+        #ifdef TIMER_ON
+                #define SYNC_SELECT(_1, _2, macro, ...) macro
+                #define START_JIKAN_TIMER_MPI(...) SYNC_SELECT(__VA_ARGS__, MPI_SYNC_JIKAN_TIMER_START_CUSTOM, MPI_SYNC_JIKAN_TIMER_START_DEF)(__VA_ARGS__)
+                #define END_JIKAN_TIMER_MPI(...)   SYNC_SELECT(__VA_ARGS__, MPI_SYNC_JIKAN_TIMER_END_CUSTOM,   MPI_SYNC_JIKAN_TIMER_END_DEF  )(__VA_ARGS__)
+        #else
+                #define START_JIKAN_TIMER_MPI(...) 
+                #define END_JIKAN_TIMER_MPI(...) 
+        #endif
+#else 
+        #define START_JIKAN_TIMER_MPI(...)
+        #define END_JIKAN_TIMER_MPI(...) 
 #endif
+//-------------------------------------------------------------------------------------
 
-    void GenerateTypedOutputData(const std::string& EventType, std::string& EventTypeString);
-    void GenerateOutputData();
+//------------------------- OpenMP-synchronous timer mode functions -------------------
+#ifdef INCLUDE_OPEN_MP
+                void OpenMP_SyncTimerStart(const char* name);
+                void OpenMP_SyncTimerEnd(const char* name);
 
-// private:
-    bool ifContains(const std::string& name);
+        #ifdef TIMER_ON
+                #define START_JIKAN_TIMER_OpenMP(name) OpenMP_SyncTimerStart(name);
+                #define END_JIKAN_TIMER_OpenMP(name) OpenMP_SyncTimerEnd(name);
+        #else
+                #define START_JIKAN_TIMER_OpenMP(name) 
+                #define END_JIKAN_TIMER_OpenMP(name) 
+        #endif
+#else
+        #define START_JIKAN_TIMER_OpenMP(name) 
+        #define END_JIKAN_TIMER_OpenMP(name) 
+#endif
+//-------------------------------------------------------------------------------------
 
-#ifdef INCLUDE_MPI
-    bool ifWriteProc(MPI_Comm comm, int id);
-#else 
-    bool ifWriteProc();
+//------------------------- CUDA-synchronous timer mode functions ---------------------
+#ifdef INCLUDE_GPU_TIMER
+                void CudaTimerStart(const char* name);
+                void CudaTimerEnd(const char* name);
+
+        #ifdef TIMER_ON
+                #define START_JIKAN_TIMER_CUDA(name) CudaTimerStart(name);
+                #define END_JIKAN_TIMER_CUDA(name) CudaTimerEnd(name);
+        #else
+                #define START_JIKAN_TIMER_CUDA(name)
+                #define END_JIKAN_TIMER_CUDA(name)
+        #endif
+#else
+        #define START_JIKAN_TIMER_CUDA(name)
+        #define END_JIKAN_TIMER_CUDA(name)
 #endif
+//-------------------------------------------------------------------------------------
 
-    void SetDumpFilename(const std::string& name);
+//------------------------- Dump functions --------------------------------------------
+#ifdef INCLUDE_MPI
+        void WriteOutputCustom(MPI_Comm comm, int id);
+        void WriteOutput(int id);
 
-private:
+        #ifdef TIMER_ON
+                #define JIKAN_TIMER_OUTPUT_CUSTOM(comm) WriteOutputCustom(comm, 0);
+                #define JIKAN_TIMER_OUTPUT_DEF() WriteOutput(0);
 
-#ifdef INCLUDE_GPU_TIMER
-    void FreeCudaEvents();
+                #define OUTPUT_SELECT(_0, _1, macro, ...) macro
+                #define JIKAN_TIMER_OUTPUT(...) OUTPUT_SELECT(__VA_ARGS__, JIKAN_TIMER_OUTPUT_CUSTOM, JIKAN_TIMER_OUTPUT_DEF)(__VA_ARGS__)
+        #else
+                #define JIKAN_TIMER_OUTPUT(...)
+        #endif
+#else
+        void WriteOutput();
+        #define JIKAN_TIMER_OUTPUT() WriteOutput();
 #endif
+//-------------------------------------------------------------------------------------
 
-};
\ No newline at end of file
+#ifdef __cplusplus  
+} 
+#endif
\ No newline at end of file
diff --git a/JikanDepths.cpp b/JikanDepths.cpp
new file mode 100644
index 0000000..c158103
--- /dev/null
+++ b/JikanDepths.cpp
@@ -0,0 +1,234 @@
+#include "JikanDepths.h"
+#include "ToJSON.h"
+
+#include <iostream>
+#include <map>
+#include <string>
+
+using namespace std;
+
+class Jikan Timer;
+
+Jikan::Jikan()
+{
+    this->EventType["Synchronous events"] = set<string>();
+    this->EventType["Asynchronous events"] = set<string>();
+    this->EventType["CUDA events"] = set<string>();
+
+    this->JSONname = OUTPUT_NAME + string(".json");
+    this->JSONdata = "";
+    this->Error = "";
+};
+
+#ifdef INCLUDE_MPI
+    bool Jikan::ifWriteProc(MPI_Comm comm, int id)
+    {
+        bool if_write = false;
+        int init_flag, fin_flag, iproc;
+
+        MPI_Initialized(&init_flag);
+        MPI_Finalized(&fin_flag);
+
+        bool if_MPI = (init_flag) && (!fin_flag);
+        if(if_MPI)
+        {
+            MPI_Comm_rank(comm, &iproc);
+            if( iproc == id)
+                if_write = true;
+        }
+        else
+            if_write = true;
+
+
+        return if_write;
+    }
+#else
+    bool Jikan::ifWriteProc()
+    {
+        return true;
+    }
+#endif
+
+Jikan::~Jikan()
+{
+    this->Events.clear();
+    map<string, set<string> >::iterator it;
+
+    for(it = this->EventType.begin(); it!=this->EventType.end(); ++it)
+        it->second.clear();
+    this->EventType.clear();
+}
+
+bool Jikan::ifContains(const string& Name)
+{
+    map<string, EventData>::iterator it;
+
+    it = this->Events.find(Name);
+    if (it == this->Events.end())
+        return false;
+
+    return true;
+}
+
+void Jikan::Jikan_sync_start(const string& name)
+{
+    bool ExistFlag;
+    ExistFlag = this->ifContains(name);
+
+    if(ExistFlag)
+    {
+        chrono_time_type start = chrono::steady_clock::now();
+        (this->Events)[name].start = start;
+    }
+    else
+    {
+        this->EventType["Synchronous events"].insert(name);
+
+        (this->Events)[name] = EventData(name);
+        chrono_time_type start = chrono::steady_clock::now();
+        (this->Events)[name].start = start;
+    }
+
+    (this->Events)[name].ifStart = true;
+}
+
+void Jikan::Jikan_sync_end(const string& name)
+{
+    bool ExistFlag, ifStart;
+    ExistFlag = this->ifContains(name);
+    ifStart = (this->Events)[name].ifStart;
+
+    if((!ExistFlag) || (!ifStart))
+        return;
+
+    chrono_time_type end = chrono::steady_clock::now();
+    chrono_time_type start = (this->Events)[name].start;
+
+    double main_elapsed = chrono::duration_cast<chrono::nanoseconds>(end - start).count() * 1e-9;
+
+    (this->Events)[name].elapsed_time += main_elapsed;
+    (this->Events)[name].count ++;
+
+#ifdef SAVE_TIME_SERIES
+    (this->Events)[name].time_series.push_back(main_elapsed);
+#endif
+
+    (this->Events)[name].ifStart = false;
+}
+
+void Jikan::Jikan_start(const string& name)
+{
+    bool ExistFlag;
+    ExistFlag = this->ifContains(name);
+
+    if(ExistFlag)
+    {
+        chrono_time_type start = chrono::steady_clock::now();
+        (this->Events)[name].start = start;
+    }
+    else
+    {
+        this->EventType["Asynchronous events"].insert(name);
+
+        (this->Events)[name] = EventData(name);
+        chrono_time_type start = chrono::steady_clock::now();
+        (this->Events)[name].start = start;
+    }
+
+    (this->Events)[name].ifStart = true;
+}
+
+void Jikan::Jikan_end(const string& name)
+{
+    bool ExistFlag, ifStart;
+    ExistFlag = this->ifContains(name);
+    ifStart = (this->Events)[name].ifStart;
+
+    if((!ExistFlag) || (!ifStart))
+        return;
+
+    chrono_time_type end = chrono::steady_clock::now();
+    chrono_time_type start = (this->Events)[name].start;
+
+    double main_elapsed = chrono::duration_cast<chrono::nanoseconds>(end - start).count() * 1e-9;
+
+    (this->Events)[name].elapsed_time += main_elapsed;
+    (this->Events)[name].count ++;
+
+#ifdef SAVE_TIME_SERIES
+    (this->Events)[name].time_series.push_back(main_elapsed);
+#endif
+
+    (this->Events)[name].ifStart = false;
+}
+
+void Jikan::GenerateTypedOutputData(const string& EventType, string& EventTypeString)
+{
+    const int n = this->EventType[EventType].size();
+    EventTypeString = JSON::StartTypedBlock(EventType);
+
+    if(n == 0)
+    {
+        EventTypeString += "\n\t}";
+        return;
+    }
+
+    string Row;
+    string Name;
+    set<string>::iterator it;
+    set<string>::iterator end_m = this->EventType[EventType].end();
+    --end_m;
+
+    for (it = this->EventType[EventType].begin(); it != end_m; ++it)
+    {
+        Name = *it;
+        JSON::GenerateRow(this->Events[Name], Row, JSON::SeparateRows);
+        EventTypeString += Row;
+    }
+
+    Name = *end_m;
+    JSON::GenerateRow(this->Events[Name], Row, JSON::FinishRows);
+    EventTypeString += Row;
+}
+
+void Jikan::GenerateOutputData()
+{
+    map<string, set<string> >::iterator it;
+    map<string, set<string> >::iterator end_m = this->EventType.end();
+    --end_m;
+
+    string Name;
+    string Out = "{ ";
+    string TypedOutput;
+
+    for(it = this->EventType.begin(); it!=end_m; ++it)
+    {    
+        Name = it->first;
+        TypedOutput = "";
+        this->GenerateTypedOutputData(Name, TypedOutput);
+        Out += TypedOutput + ",\n";
+    }
+
+    Name = end_m->first;
+    TypedOutput = "";
+    this->GenerateTypedOutputData(Name, TypedOutput);
+    Out += TypedOutput + "\n}";
+
+    this->JSONdata = Out;
+
+    bool OutputRes = JSON::WriteOutput(this->JSONname, this->JSONdata);
+
+    if(OutputRes != true)
+    {
+        this->Error = JSON::Error;
+    }
+
+    #ifdef INCLUDE_GPU_TIMER
+        this->FreeCudaEvents();
+    #endif
+}
+
+void Jikan::SetDumpFilename(const std::string& name)
+{
+    this->JSONname = name;
+}
\ No newline at end of file
diff --git a/JikanDepths.h b/JikanDepths.h
new file mode 100644
index 0000000..b67ae99
--- /dev/null
+++ b/JikanDepths.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "JikanWrapper.h"
+#include "Jikan-config.h"
+#include "Event.h"
+
+#include <iostream>
+#include <string>
+#include <set>
+#ifdef INCLUDE_MPI
+    #include <mpi.h>
+#endif
+
+class Jikan
+{
+public:
+    std::map<std::string, EventData> Events;
+    std::map<std::string, std::set<std::string> > EventType;
+    std::string JSONname;
+    std::string JSONdata;
+    std::string Error;
+
+    Jikan();
+    ~Jikan();
+
+    void Jikan_sync_start(const std::string& name);
+    void Jikan_sync_end(  const std::string& name);
+
+    void Jikan_start(const std::string& name);
+    void Jikan_end(  const std::string& name);
+
+#ifdef INCLUDE_GPU_TIMER
+    void cuda_Jikan_start(const std::string& name);
+    void cuda_Jikan_end(  const std::string& name);
+#endif
+
+    void GenerateTypedOutputData(const std::string& EventType, std::string& EventTypeString);
+    void GenerateOutputData();
+
+// private:
+    bool ifContains(const std::string& name);
+
+#ifdef INCLUDE_MPI
+    bool ifWriteProc(MPI_Comm comm, int id);
+#else 
+    bool ifWriteProc();
+#endif
+
+    void SetDumpFilename(const std::string& name);
+
+private:
+
+#ifdef INCLUDE_GPU_TIMER
+    void FreeCudaEvents();
+#endif
+
+};
\ No newline at end of file
diff --git a/JikanWrapper.cpp b/JikanWrapper.cpp
deleted file mode 100644
index c60294d..0000000
--- a/JikanWrapper.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-#include "Jikan.h"
-#include "JikanWrapper.h"
-
-#ifdef INCLUDE_OPEN_MP
-    #include "omp.h"
-#endif
-
-#ifdef INCLUDE_MPI
-    #include "mpi.h"
-#endif
-
-using namespace std;
-
-extern "C"
-{
-    extern class Jikan Timer;
-
-    void TimerStart(const char* name)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-        
-        string str_name = name;
-
-        Timer.Jikan_start(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-    void TimerEnd(const char* name)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-        
-        string str_name = name;
-
-        Timer.Jikan_end(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-#ifdef INCLUDE_MPI
-    void MPI_SyncTimerStart(const char* name)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-        
-        string str_name = name;
-
-        int init_flag, fin_flag;
-
-        MPI_Initialized(&init_flag);
-        MPI_Finalized(&fin_flag);
-
-        if((!fin_flag) && init_flag)
-            MPI_Barrier(MPI_COMM_WORLD);
-
-        Timer.Jikan_sync_start(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-    void MPI_SyncTimerEnd(const char* name)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-        string str_name = name;
-
-        int init_flag, fin_flag;
-
-        MPI_Initialized(&init_flag);
-        MPI_Finalized(&fin_flag);
-
-        if((!fin_flag) && init_flag)
-            MPI_Barrier(MPI_COMM_WORLD);
-
-        Timer.Jikan_sync_end(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-    void MPI_SyncTimerStartCustom(const char* name, MPI_Comm comm)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-        string str_name = name;
-
-        int init_flag, fin_flag;
-
-        MPI_Initialized(&init_flag);
-        MPI_Finalized(&fin_flag);
-
-        if((!fin_flag) && init_flag)
-            MPI_Barrier(MPI_COMM_WORLD);
-
-        Timer.Jikan_sync_start(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-    void MPI_SyncTimerEndCustom(const char* name, MPI_Comm comm)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif        
-        string str_name = name;
-
-        int init_flag, fin_flag;
-
-        MPI_Initialized(&init_flag);
-        MPI_Finalized(&fin_flag);
-
-        if((!fin_flag) && init_flag)
-            MPI_Barrier(comm);
-
-        Timer.Jikan_sync_end(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-    void WriteOutputCustom(MPI_Comm comm, int id)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-
-        bool ifWrite = Timer.ifWriteProc(comm, id);
-        if(ifWrite == true)
-            Timer.GenerateOutputData();
-
-        #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-    void WriteOutput(int id)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-
-        bool ifWrite = Timer.ifWriteProc(MPI_COMM_WORLD, id);
-        // cout << ifWrite << endl;
-        if(ifWrite == true)
-            Timer.GenerateOutputData();
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-
-#else
-    void WriteOutput()
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-    
-        bool ifWrite = Timer.ifWriteProc();
-        if(ifWrite == true)
-            Timer.GenerateOutputData();
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-#endif
-
-#ifdef INCLUDE_OPEN_MP
-    void OpenMP_SyncTimerStart(const char* name)
-    {
-        #pragma omp barrier
-        #pragma omp master
-        {
-            string str_name = name;
-
-            Timer.Jikan_sync_start(str_name);
-        }
-    }
-
-    void OpenMP_SyncTimerEnd(const char* name)
-    {
-        #pragma omp barrier
-        #pragma omp master
-        {
-            string str_name = name;
-
-            Timer.Jikan_sync_end(str_name);
-        }
-    }
-#endif
-//--------
-
-#ifdef INCLUDE_GPU_TIMER
-    void CudaTimerStart(const char* name)
-    {
-    #ifdef INCLUDE_OPEN_MP
-        #pragma omp master
-        {
-    #endif
-
-        string str_name = name;
-
-        Timer.cuda_Jikan_start(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-    
-    void CudaTimerEnd(const char* name)
-    {
-    #ifdef INCLUDE_OPEN_MP
-
-        #pragma omp master
-        {
-    #endif
-        string str_name = name;
-
-        Timer.cuda_Jikan_end(str_name);
-
-    #ifdef INCLUDE_OPEN_MP
-        }
-    #endif
-    }
-#endif
-}
\ No newline at end of file
diff --git a/JikanWrapper.h b/JikanWrapper.h
deleted file mode 100644
index 6d7a357..0000000
--- a/JikanWrapper.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#pragma once
-
-#include "Jikan-config.h"
-
-#ifdef INCLUDE_MPI
-        #include <mpi.h>
-#endif 
-
-#ifdef __cplusplus
-extern "C" {  
-#endif                  
-        void TimerStart(const char* name);
-        void TimerEnd(const char* name);
-
-// SIMPLE TIMER -------------------------------------------
-#ifdef TIMER_ON
-        #define JIKAN_TIMER_START(name) TimerStart(name);
-        #define JIKAN_TIMER_END(name) TimerEnd(name);
-#else
-        #define JIKAN_TIMER_START(name)
-        #define JIKAN_TIMER_END(name)
-#endif
-//---------------------------------------------------------
-
-// MPI TIMER ----------------------------------------------
-#ifdef INCLUDE_MPI
-                void MPI_SyncTimerStart(const char* name);
-                void MPI_SyncTimerEnd(const char* name);
-
-                #define MPI_SYNC_JIKAN_TIMER_START_DEF(name) MPI_SyncTimerStart(name);
-                #define MPI_SYNC_JIKAN_TIMER_END_DEF(name) MPI_SyncTimerEnd(name);
-
-                void MPI_SyncTimerStartCustom(const char* name, MPI_Comm comm);
-                void MPI_SyncTimerEndCustom(const char* name, MPI_Comm comm);
-
-                #define MPI_SYNC_JIKAN_TIMER_START_CUSTOM(name, comm) MPI_SyncTimerStartCustom(name, comm);
-                #define MPI_SYNC_JIKAN_TIMER_END_CUSTOM(name, comm) MPI_SyncTimerEndCustom(name, comm);
-
-        #ifdef TIMER_ON
-                #define SYNC_SELECT(_1, _2, macro, ...) macro
-                #define MPI_SYNC_JIKAN_TIMER_START(...) SYNC_SELECT(__VA_ARGS__, MPI_SYNC_JIKAN_TIMER_START_CUSTOM, MPI_SYNC_JIKAN_TIMER_START_DEF)(__VA_ARGS__)
-                #define MPI_SYNC_JIKAN_TIMER_END(...)   SYNC_SELECT(__VA_ARGS__, MPI_SYNC_JIKAN_TIMER_END_CUSTOM,   MPI_SYNC_JIKAN_TIMER_END_DEF  )(__VA_ARGS__)
-        #else
-                #define MPI_SYNC_JIKAN_TIMER_START(...)
-                #define MPI_SYNC_JIKAN_TIMER_END(...) 
-        #endif
-#else 
-        #define MPI_SYNC_JIKAN_TIMER_START(...)
-        #define MPI_SYNC_JIKAN_TIMER_END(...) 
-#endif
-//---------------------------------------------------------
-
-// OpenMP TIMER -------------------------------------------
-#ifdef INCLUDE_OPEN_MP
-                void OpenMP_SyncTimerStart(const char* name);
-                void OpenMP_SyncTimerEnd(const char* name);
-
-        #ifdef TIMER_ON
-                #define OpenMP_SYNC_JIKAN_TIMER_START(name) OpenMP_SyncTimerStart(name);
-                #define OpenMP_SYNC_JIKAN_TIMER_END(name) OpenMP_SyncTimerEnd(name);
-        #else
-                #define OpenMP_SYNC_JIKAN_TIMER_START(name) 
-                #define OpenMP_SYNC_JIKAN_TIMER_END(name) 
-        #endif
-#else
-        #define OpenMP_SYNC_JIKAN_TIMER_START(name) 
-        #define OpenMP_SYNC_JIKAN_TIMER_END(name) 
-#endif
-//---------------------------------------------------------
-
-// CUDA TIMER ---------------------------------------------
-#ifdef INCLUDE_GPU_TIMER
-                void CudaTimerStart(const char* name);
-                void CudaTimerEnd(const char* name);
-
-        #ifdef TIMER_ON
-                #define JIKAN_CUDA_TIMER_START(name) CudaTimerStart(name);
-                #define JIKAN_CUDA_TIMER_END(name) CudaTimerEnd(name);
-        #else
-                #define JIKAN_CUDA_TIMER_START(name)
-                #define JIKAN_CUDA_TIMER_END(name)
-        #endif
-#else
-        #define JIKAN_CUDA_TIMER_START(name)
-        #define JIKAN_CUDA_TIMER_END(name)
-#endif
-//---------------------------------------------------------
-
-
-#ifdef INCLUDE_MPI
-        void WriteOutputCustom(MPI_Comm comm, int id);
-        void WriteOutput(int id);
-
-        #ifdef TIMER_ON
-                #define JIKAN_TIMER_OUTPUT_CUSTOM(comm) WriteOutputCustom(comm, 0);
-                #define JIKAN_TIMER_OUTPUT_DEF() WriteOutput(0);
-
-                #define OUTPUT_SELECT(_0, _1, macro, ...) macro
-                #define JIKAN_TIMER_OUTPUT(...) OUTPUT_SELECT(__VA_ARGS__, JIKAN_TIMER_OUTPUT_CUSTOM, JIKAN_TIMER_OUTPUT_DEF)(__VA_ARGS__)
-        #else
-                #define JIKAN_TIMER_OUTPUT(...)
-        #endif
-#else
-        void WriteOutput();
-        #define JIKAN_TIMER_OUTPUT() WriteOutput();
-#endif
-
-
-#ifdef __cplusplus  
-} 
-#endif
\ No newline at end of file
-- 
GitLab