From 4765d09fecf2d809f452285a1db8ea9fcbd672c2 Mon Sep 17 00:00:00 2001
From: Matteo Cicuttin <datafl4sh@toxicnet.eu>
Date: Mon, 30 Aug 2021 15:43:49 +0200
Subject: [PATCH] Reworked Silo export for MPI.

---
 CMakeLists.txt              | 15 +++++--
 include/maxwell_interface.h |  6 +--
 src/maxwell_common.cpp      | 69 +++++++++++++++++++++++---------
 src/maxwell_cpu.cpp         | 80 +++++++++++++++++++++++--------------
 src/maxwell_gpu.cpp         | 10 +++--
 src/maxwell_solver.cpp      | 35 ++++++++--------
 6 files changed, 137 insertions(+), 78 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 81dbb89..105a8c9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -275,6 +275,13 @@ option(OPT_DISABLE_TEXTURE_CACHE "On ROCm 4.1 texture stuff is broken, disable i
 if (OPT_DISABLE_TEXTURE_CACHE)
     add_definitions(-DDISABLE_TEXTURE_CACHE)
 endif()
+
+######################################################################
+## Enable code to handle geometric diode simulation for UniUD project
+option(OPT_ENABLE_EXP_GEOMETRIC_DIODE "Enable Geometric Diode stuff [EXPERIMENTAL][NO GPU]")
+if (OPT_ENABLE_EXP_GEOMETRIC_DIODE)
+    add_definitions(-DENABLE_EXP_GEOMETRIC_DIODE)
+endif()
 ######################################################################
 ## Configure targets
 include_directories(contrib/sgr)
@@ -312,11 +319,11 @@ endif()
 
 ########## mpi testing stuff
 
-add_executable(testpart src/testpart.cpp)
-target_link_libraries(testpart gmshdg)
+#add_executable(testpart src/testpart.cpp)
+#target_link_libraries(testpart gmshdg)
 
-add_executable(testmod src/testmod.cpp)
-target_link_libraries(testmod gmshdg)
+#add_executable(testmod src/testmod.cpp)
+#target_link_libraries(testmod gmshdg)
 
 ########## maxwell solver
 set(MAXWELL_SOURCES     src/maxwell_interface.cpp
diff --git a/include/maxwell_interface.h b/include/maxwell_interface.h
index fc686a3..2c344cc 100644
--- a/include/maxwell_interface.h
+++ b/include/maxwell_interface.h
@@ -325,8 +325,7 @@ struct solver_state_gpu
 void init_from_model(const model&, solver_state&);
 void init_matparams(const model&, solver_state&, const parameter_loader&);
 //void apply_operator(solver_state&, const field&, field&);
-void export_fields_to_silo(const model&, const solver_state&, const parameter_loader&);
-void export_fields_to_silo_2(const model&, solver_state&, const parameter_loader&);
+void export_fields_to_silo(const model&, solver_state&, const parameter_loader&);
 void timestep(solver_state&, const parameter_loader&, time_integrator_type);
 void prepare_sources(const model&, maxwell::solver_state&, maxwell::parameter_loader&);
 void do_sources(const model&, maxwell::solver_state&, maxwell::parameter_loader&);
@@ -339,8 +338,7 @@ void gather_field(const model&, maxwell::field&, int, MPI_Comm);
 void init_from_model(const model&, solver_state_gpu&);
 void init_matparams(const model&, solver_state_gpu&, const parameter_loader&);
 //void apply_operator(solver_state_gpu&, const field_gpu&, field_gpu&);
-void export_fields_to_silo(const model&, const solver_state_gpu&, const parameter_loader&);
-void export_fields_to_silo_2(const model&, solver_state_gpu&, const parameter_loader&);
+void export_fields_to_silo(const model&, solver_state_gpu&, const parameter_loader&);
 void timestep(solver_state_gpu&, const parameter_loader&, time_integrator_type);
 void prepare_sources(const model&, maxwell::solver_state_gpu&, maxwell::parameter_loader&);
 void do_sources(const model&, maxwell::solver_state_gpu&, maxwell::parameter_loader&);
diff --git a/src/maxwell_common.cpp b/src/maxwell_common.cpp
index 3a8bf17..ba1e8db 100644
--- a/src/maxwell_common.cpp
+++ b/src/maxwell_common.cpp
@@ -151,12 +151,18 @@ void export_E_field_nodal(const model& mod, silo& sdb, const vecxd& Ex,
     std::vector<double> accum_Ez( sdb.num_nodes(), 0.0 );
     std::vector<size_t> count( sdb.num_nodes(), 0 );
 
+#ifdef USE_MPI
+    for (auto& etag : mod.world_entities_tags())
+    {
+        auto& e = mod.entity_world_lookup(etag);
+#else /* USE_MPI */
     for (auto& e : mod)
     {
+#endif /* USE_MPI */
         for (size_t iT = 0; iT < e.num_cells(); iT++)
         {
             auto& pe = e.cell(iT);
-            auto cgofs = e.cell_model_dof_offset(iT);
+            auto cgofs = e.cell_world_dof_offset(iT);
             auto nodetags = pe.node_tags();
             for (size_t iD = 0; iD < 4; iD++)
             {
@@ -191,12 +197,18 @@ void export_H_field_nodal(const model& mod, silo& sdb, const vecxd& Hx,
     std::vector<double> accum_Hz( sdb.num_nodes(), 0.0 );
     std::vector<size_t> count( sdb.num_nodes(), 0 );
 
+#ifdef USE_MPI
+    for (auto& etag : mod.world_entities_tags())
+    {
+        auto& e = mod.entity_world_lookup(etag);
+#else /* USE_MPI */
     for (auto& e : mod)
     {
+#endif /* USE_MPI */
         for (size_t iT = 0; iT < e.num_cells(); iT++)
         {
             auto& pe = e.cell(iT);
-            auto cgofs = e.cell_model_dof_offset(iT);
+            auto cgofs = e.cell_world_dof_offset(iT);
             auto nodetags = pe.node_tags();
             for (size_t iD = 0; iD < 4; iD++)
             {
@@ -231,15 +243,20 @@ void export_J_field_nodal(const model& mod, silo& sdb, const vecxd& Ex,
     std::vector<double> accum_Jz( sdb.num_nodes(), 0.0 );
     std::vector<size_t> count( sdb.num_nodes(), 0 );
 
+#ifdef USE_MPI
+    for (auto& etag : mod.world_entities_tags())
+    {
+        auto& e = mod.entity_world_lookup(etag);
+#else /* USE_MPI */
     for (auto& e : mod)
     {
-        auto etag = e.material_tag();
+#endif /* USE_MPI */
         for (size_t iT = 0; iT < e.num_cells(); iT++)
         {
             auto& pe = e.cell(iT);
             auto bar = pe.barycenter();
-            auto sigma = mpl.sigma(etag, bar);
-            auto cgofs = e.cell_model_dof_offset(iT);
+            auto sigma = mpl.sigma(e.material_tag(), bar);
+            auto cgofs = e.cell_world_dof_offset(iT);
             auto nodetags = pe.node_tags();
             for (size_t iD = 0; iD < 4; iD++)
             {
@@ -275,17 +292,22 @@ void export_E_field_zonal(const model& mod, silo& sdb, const vecxd& Ex,
     std::vector<double> out_Ey( mod.num_cells() );
     std::vector<double> out_Ez( mod.num_cells() );
 
-    for (size_t iE = 0; iE < mod.num_entities(); iE++)
+#ifdef USE_MPI
+    for (auto& etag : mod.world_entities_tags())
+    {
+        auto& e = mod.entity_world_lookup(etag);
+#else /* USE_MPI */
+    for (auto& e : mod)
     {
-        auto& e = mod.entity_at(iE);
+#endif /* USE_MPI */
         for (size_t iT = 0; iT < e.num_cells(); iT++)
         {
             auto& pe = e.cell(iT);
             auto& re = e.cell_refelem(pe);
             vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.});
             auto num_bf = re.num_basis_functions();
-            auto ofs = e.cell_model_dof_offset(iT);
-            auto gi = e.cell_model_index_by_gmsh(iT);
+            auto ofs = e.cell_world_dof_offset(iT);
+            auto gi = e.cell_world_index_by_gmsh(iT);
             out_Ex[gi] = Ex.segment(ofs, num_bf).dot(phi_bar);
             out_Ey[gi] = Ey.segment(ofs, num_bf).dot(phi_bar);
             out_Ez[gi] = Ez.segment(ofs, num_bf).dot(phi_bar);
@@ -305,17 +327,22 @@ void export_H_field_zonal(const model& mod, silo& sdb, const vecxd& Hx,
     std::vector<double> out_Hy( mod.num_cells() );
     std::vector<double> out_Hz( mod.num_cells() );
 
-    for (size_t iE = 0; iE < mod.num_entities(); iE++)
+#ifdef USE_MPI
+    for (auto& etag : mod.world_entities_tags())
     {
-        auto& e = mod.entity_at(iE);
+        auto& e = mod.entity_world_lookup(etag);
+#else /* USE_MPI */
+    for (auto& e : mod)
+    {
+#endif /* USE_MPI */
         for (size_t iT = 0; iT < e.num_cells(); iT++)
         {
             auto& pe = e.cell(iT);
             auto& re = e.cell_refelem(pe);
             vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.});
             auto num_bf = re.num_basis_functions();
-            auto ofs = e.cell_model_dof_offset(iT);
-            auto gi = e.cell_model_index_by_gmsh(iT);
+            auto ofs = e.cell_world_dof_offset(iT);
+            auto gi = e.cell_world_index_by_gmsh(iT);
             out_Hx[gi] = Hx.segment(ofs, num_bf).dot(phi_bar);
             out_Hy[gi] = Hy.segment(ofs, num_bf).dot(phi_bar);
             out_Hz[gi] = Hz.segment(ofs, num_bf).dot(phi_bar);
@@ -335,20 +362,24 @@ void export_J_field_zonal(const model& mod, silo& sdb, const vecxd& Ex,
     std::vector<double> out_Jy( mod.num_cells() );
     std::vector<double> out_Jz( mod.num_cells() );
 
-    for (size_t iE = 0; iE < mod.num_entities(); iE++)
+#ifdef USE_MPI
+    for (auto& etag : mod.world_entities_tags())
+    {
+        auto& e = mod.entity_world_lookup(etag);
+#else /* USE_MPI */
+    for (auto& e : mod)
     {
-        auto& e = mod.entity_at(iE);
-        auto etag = e.material_tag();
+#endif /* USE_MPI */
         for (size_t iT = 0; iT < e.num_cells(); iT++)
         {
             auto& pe = e.cell(iT);
             auto& re = e.cell_refelem(pe);
             auto bar = pe.barycenter();
-            auto sigma = mpl.sigma(etag, bar);
+            auto sigma = mpl.sigma(e.material_tag(), bar);
             vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.});
             auto num_bf = re.num_basis_functions();
-            auto ofs = e.cell_model_dof_offset(iT);
-            auto gi = e.cell_model_index_by_gmsh(iT);
+            auto ofs = e.cell_world_dof_offset(iT);
+            auto gi = e.cell_world_index_by_gmsh(iT);
             out_Jx[gi] = sigma*Ex.segment(ofs, num_bf).dot(phi_bar);
             out_Jy[gi] = sigma*Ey.segment(ofs, num_bf).dot(phi_bar);
             out_Jz[gi] = sigma*Ez.segment(ofs, num_bf).dot(phi_bar);
diff --git a/src/maxwell_cpu.cpp b/src/maxwell_cpu.cpp
index 0491151..2af0267 100644
--- a/src/maxwell_cpu.cpp
+++ b/src/maxwell_cpu.cpp
@@ -609,7 +609,7 @@ gather_field(const model& mod, maxwell::field& in, maxwell::field& out,
             auto& e = mod.entity_world_lookup(tag);
             auto base = e.dof_base_world();
             auto len = e.num_dofs();
-            std::cout << "GR: " << tag << " " << len << std::endl;
+            //std::cout << "GR: " << tag << " " << len << std::endl;
             receive_field(out, mod.entity_rank(tag), tag, base, len, comm);
         }
 
@@ -630,14 +630,14 @@ gather_field(const model& mod, maxwell::field& in, maxwell::field& out,
     {
         for (auto& e : mod)
         {
-            std::cout << "GS: " << e.gmsh_tag() << " " << e.num_dofs() << std::endl;
+            //std::cout << "GS: " << e.gmsh_tag() << " " << e.num_dofs() << std::endl;
             send_field(in, root, e.gmsh_tag(), e.dof_base(), e.num_dofs(), comm);
         }
     }
 }
 
 void
-export_fields_to_silo_2(const model& mod, maxwell::solver_state& state,
+export_fields_to_silo(const model& mod, maxwell::solver_state& state,
     const maxwell::parameter_loader& mpl)
 {
     int rank;
@@ -658,31 +658,47 @@ export_fields_to_silo_2(const model& mod, maxwell::solver_state& state,
         sdb.import_mesh_from_gmsh();
         sdb.write_mesh(state.curr_time, state.curr_timestep);
 
-        std::vector<double> out_Ex( mod.num_cells_world() );
-        std::vector<double> out_Ey( mod.num_cells_world() );
-        std::vector<double> out_Ez( mod.num_cells_world() );
+        switch( mpl.postpro_fieldExportMode("E") )
+        {
+            case field_export_mode::NONE:
+                break;
+
+            case field_export_mode::NODAL:
+                export_E_field_nodal(mod, sdb, f.Ex, f.Ey, f.Ez, mpl);
+                break;
 
-        for (auto& tag : mod.world_entities_tags())
+            case field_export_mode::ZONAL:
+                export_E_field_zonal(mod, sdb, f.Ex, f.Ey, f.Ez, mpl);
+                break;
+        }
+
+        switch( mpl.postpro_fieldExportMode("H") )
         {
-            auto& e = mod.entity_world_lookup(tag);
-            for (size_t iT = 0; iT < e.num_cells(); iT++)
-            {
-                auto& pe = e.cell(iT);
-                auto& re = e.cell_refelem(pe);
-                vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.});
-                auto num_bf = re.num_basis_functions();
-                auto ofs = e.cell_world_dof_offset(iT);
-                auto gi = e.cell_world_index_by_gmsh(iT);
-                out_Ex[gi] = f.Ex.segment(ofs, num_bf).dot(phi_bar);
-                out_Ey[gi] = f.Ey.segment(ofs, num_bf).dot(phi_bar);
-                out_Ez[gi] = f.Ez.segment(ofs, num_bf).dot(phi_bar);
-            }
+            case field_export_mode::NONE:
+                break;
+
+            case field_export_mode::NODAL:
+                export_H_field_nodal(mod, sdb, f.Hx, f.Hy, f.Hz, mpl);
+                break;
+
+            case field_export_mode::ZONAL:
+                export_H_field_zonal(mod, sdb, f.Hx, f.Hy, f.Hz, mpl);
+                break;
         }
 
-        sdb.write_zonal_variable("Ex", out_Ex);
-        sdb.write_zonal_variable("Ey", out_Ey);
-        sdb.write_zonal_variable("Ez", out_Ez);
-        sdb.write_vector_expression("E", "{Ex, Ey, Ez}");    
+        switch( mpl.postpro_fieldExportMode("J") )
+        {
+            case field_export_mode::NONE:
+                break;
+
+            case field_export_mode::NODAL:
+                export_J_field_nodal(mod, sdb, f.Ex, f.Ey, f.Ez, mpl);
+                break;
+
+            case field_export_mode::ZONAL:
+                export_J_field_zonal(mod, sdb, f.Ex, f.Ey, f.Ez, mpl);
+                break;
+        }
     }
     else
     {
@@ -690,21 +706,22 @@ export_fields_to_silo_2(const model& mod, maxwell::solver_state& state,
         gather_field(mod, state.emf_next, dummy, 0, MPI_COMM_WORLD);
     }
 }
-#endif /* USE_MPI */
+
+#else /* USE_MPI */
 
 void
-export_fields_to_silo(const model& mod, const maxwell::solver_state& state,
-    const maxwell::parameter_loader& mpl)
+export_fields_to_silo(const model &mod, maxwell::solver_state &state,
+                      const maxwell::parameter_loader &mpl)
 {
     std::stringstream ss;
     ss << mpl.sim_name() << "/timestep_" << state.curr_timestep << ".silo";
-    
+
     silo sdb;
     sdb.create_db(ss.str());
     sdb.import_mesh_from_gmsh();
     sdb.write_mesh(state.curr_time, state.curr_timestep);
 
-    switch( mpl.postpro_fieldExportMode("E") )
+    switch (mpl.postpro_fieldExportMode("E"))
     {
         case field_export_mode::NONE:
             break;
@@ -720,7 +737,7 @@ export_fields_to_silo(const model& mod, const maxwell::solver_state& state,
             break;
     }
 
-    switch( mpl.postpro_fieldExportMode("H") )
+    switch (mpl.postpro_fieldExportMode("H"))
     {
         case field_export_mode::NONE:
             break;
@@ -736,7 +753,7 @@ export_fields_to_silo(const model& mod, const maxwell::solver_state& state,
             break;
     }
 
-    switch( mpl.postpro_fieldExportMode("J") )
+    switch (mpl.postpro_fieldExportMode("J"))
     {
         case field_export_mode::NONE:
             break;
@@ -752,5 +769,6 @@ export_fields_to_silo(const model& mod, const maxwell::solver_state& state,
             break;
     }
 }
+#endif /* USE_MPI */
 
 } // namespace maxwell
diff --git a/src/maxwell_gpu.cpp b/src/maxwell_gpu.cpp
index 00ff575..2314859 100644
--- a/src/maxwell_gpu.cpp
+++ b/src/maxwell_gpu.cpp
@@ -33,7 +33,7 @@ init_matparams(const model& mod, solver_state_gpu& state,
             auto v_epsilon = mpl.epsilon(etag, bar);
             auto v_mu = mpl.mu(etag, bar);
             auto v_sigma = mpl.sigma(etag, bar);
-            auto ofs = e.cell_global_dof_offset(iT);
+            auto ofs = e.cell_model_dof_offset(iT);
 
             for (size_t iD = 0; iD < re.num_basis_functions(); iD++)
             {
@@ -555,18 +555,21 @@ swap(solver_state_gpu& state, const parameter_loader& mpl)
     std::swap(state.emf_curr, state.emf_next);
 }
 
+#ifdef USE_MPI
 void
 gather_field(const model& mod, const maxwell::field_gpu& in, maxwell::field_gpu& f,
     int root, MPI_Comm comm)
 {}
 
 void
-export_fields_to_silo_2(const model& mod, maxwell::solver_state_gpu& state,
+export_fields_to_silo(const model& mod, maxwell::solver_state_gpu& state,
     const maxwell::parameter_loader& mpl)
 {}
 
+#else /* USE_MPI */
+
 void
-export_fields_to_silo(const model& mod, const maxwell::solver_state_gpu& state,
+export_fields_to_silo(const model& mod, maxwell::solver_state_gpu& state,
     const maxwell::parameter_loader& mpl)
 {
     std::stringstream ss;
@@ -623,5 +626,6 @@ export_fields_to_silo(const model& mod, const maxwell::solver_state_gpu& state,
             break;
     }
 }
+#endif /* USE_MPI */
 
 } // namespace maxwell
diff --git a/src/maxwell_solver.cpp b/src/maxwell_solver.cpp
index a4d7480..ebe6249 100644
--- a/src/maxwell_solver.cpp
+++ b/src/maxwell_solver.cpp
@@ -68,6 +68,7 @@ void initialize_solver(const model& mod, State& state, const maxwell::parameter_
     init_matparams(mod, state, mpl);
 }
 
+#ifdef ENABLE_EXP_GEOMETRIC_DIODE
 class integration_line
 {
     std::vector<size_t>     element_tags;
@@ -187,6 +188,7 @@ reinit_materials(const model& mod, maxwell::solver_state& state, maxwell::parame
         }
     }
 }
+#endif /* ENABLE_EXP_GEOMETRIC_DIODE */
 
 template<typename State>
 void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl)
@@ -205,12 +207,12 @@ void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl)
     std::cout << "Time integrator: " << mpl.sim_timeIntegratorName() << std::endl;
 
     mpl.call_initialization_callback();
-
+#ifdef ENABLE_EXP_GEOMETRIC_DIODE
     auto relmat = [&](){ reinit_materials(mod, state, mpl); };
 
     sol::state& lua = mpl.lua_state();
     lua["relmat"] = relmat;
-
+#endif /* ENABLE_EXP_GEOMETRIC_DIODE */
     timecounter tc;
     tc.tic();
     prepare_sources(mod, state, mpl);
@@ -220,13 +222,8 @@ void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl)
         timestep(state, mpl, ti);
         do_sources(mod, state, mpl);
         
-#ifdef USE_MPI
-            if ( (silo_output_rate != 0) and (i%silo_output_rate == 0) )
-                export_fields_to_silo_2(mod, state, mpl);
-#else
-            if ( (silo_output_rate != 0) and (i%silo_output_rate == 0) )
-                export_fields_to_silo(mod, state, mpl);
-#endif /* USE_MPI */
+        if ( (silo_output_rate != 0) and (i%silo_output_rate == 0) )
+            export_fields_to_silo(mod, state, mpl);
 
         swap(state, mpl);
 
@@ -243,6 +240,7 @@ void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl)
 void
 register_lua_usertypes(maxwell::parameter_loader& mpl)
 {
+#ifdef ENABLE_EXP_GEOMETRIC_DIODE
     sol::state& lua = mpl.lua_state();
     sol::usertype<point_3d> point_3d_ut = lua.new_usertype<point_3d>("point",
         sol::constructors<point_3d(), point_3d(double, double, double)>()
@@ -252,18 +250,21 @@ register_lua_usertypes(maxwell::parameter_loader& mpl)
         lua.new_usertype<integration_line>("integration_line",
             sol::constructors<integration_line(const point_3d&, const point_3d&, size_t)>()
         );
+#endif /* ENABLE_EXP_GEOMETRIC_DIODE */
 }
 
 void
 register_lua_usertypes_bystate(maxwell::parameter_loader& mpl,
     model& mod, maxwell::solver_state& state)
 {
+#ifdef ENABLE_EXP_GEOMETRIC_DIODE
     sol::state& lua = mpl.lua_state();
 
     lua["internal"] = lua.create_table();
     lua["internal"]["model"] = &mod;
     lua["internal"]["state"] = &state;
     lua["integrate_E"] = integrate_electric_field;
+#endif /*ENABLE_EXP_GEOMETRIC_DIODE */
 }
 
 #ifdef ENABLE_GPU_SOLVER
@@ -273,15 +274,15 @@ register_lua_usertypes_bystate(maxwell::parameter_loader& mpl,
 {}
 #endif
 
-int main(int argc, const char *argv[])
+int main(int argc, char *argv[])
 {
 #ifdef USE_MPI
     MPI_Init(&argc, &argv);
 
-    int rank, size;
-    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-    MPI_Comm_size(MPI_COMM_WORLD, &size);
-    std::cout << "Running with MPI: " << rank+1 << "/" << size << std::endl;
+    int comm_rank, comm_size;
+    MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
+    std::cout << "Running with MPI: " << comm_rank+1 << "/" << comm_size << std::endl;
 #endif
 
     if (argc != 2)
@@ -312,11 +313,11 @@ int main(int argc, const char *argv[])
     model mod( mpl.sim_geomorder(), mpl.sim_approxorder() );
 
 #ifdef USE_MPI
-    if (rank == 0)
+    if (comm_rank == 0)
     {
         mod.generate_mesh();
-        if (size > 1)
-            mod.partition_mesh(size);
+        if (comm_size > 1)
+            mod.partition_mesh(comm_size);
 
         mod.populate_from_gmsh();
     }
-- 
GitLab