diff --git a/contrib/sgr b/contrib/sgr index af618523a0c76d5ae4cebde9f5f07c702833d924..79794aae8124bbae25f7b2a13e0f675a37bd7b04 160000 --- a/contrib/sgr +++ b/contrib/sgr @@ -1 +1 @@ -Subproject commit af618523a0c76d5ae4cebde9f5f07c702833d924 +Subproject commit 79794aae8124bbae25f7b2a13e0f675a37bd7b04 diff --git a/doc/lua_api.md b/doc/lua_api.md index c1cf993f9e35e96e749f8fc4d9cdae6a278884ab..9d40e5c71b40e7f115700cc0f07c189bb3825942 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -145,6 +145,7 @@ None. ### Debug and validation The solver has some facilities to allow validation and comparison with analytical solutions. Those facilities are accessed via the `debug` table. In the current implementation the `debug` table is undefined by default, so it must be initialized explicitly in the configuration with a statement `debug = {}`. Possible members of the `debug` table are: - `analytical_solution(tag, x, y, z, t)`: define the analytical solution of the problem. If defined, the numerical solution is compared with the analytical solution at each timestep in the whole domain. The function has to return 6 values, namely `Ex`, `Ey`, `Ez`, `Hx`, `Hy` and `Hz`. +- `dump_cell_ranks` (bool): if true, and if the solver has MPI support compiled in, add to the Silo output a variable showing the cell-to-rank mapping. ### Postprocessing The export of the fields E, H and J to Silo is controlled using the appropriate sections in the `postpro` table. diff --git a/include/maxwell_common.h b/include/maxwell_common.h index 83bbfe992c797f94d57a3317f25b417fb404dcdb..886e74642a326fe3c8cec53b67d0d8c2f1ce843d 100644 --- a/include/maxwell_common.h +++ b/include/maxwell_common.h @@ -165,24 +165,9 @@ eval_interface_sources(const model& mod, const parameter_loader& mpl, } } -void export_E_field_nodal(const model&, silo&, const vecxd&, const vecxd&, - const vecxd&, const parameter_loader&); - -void export_H_field_nodal(const model&, silo&, const vecxd&, const vecxd&, - const vecxd&, const parameter_loader&); - -void export_J_field_nodal(const model&, silo&, const vecxd&, const vecxd&, - const vecxd&, const parameter_loader&); - -void export_E_field_zonal(const model&, silo&, const vecxd&, const vecxd&, - const vecxd&, const parameter_loader&); - -void export_H_field_zonal(const model&, silo&, const vecxd&, const vecxd&, - const vecxd&, const parameter_loader&); - -void export_J_field_zonal(const model&, silo&, const vecxd&, const vecxd&, - const vecxd&, const parameter_loader&); - +#ifdef USE_MPI +std::vector<double> compute_cell_ranks(const model&); +#endif /* USE_MPI */ using MaterialFunc = std::function<double(int, const point_3d&)>; diff --git a/include/maxwell_interface.h b/include/maxwell_interface.h index 3b24d81c8bb36b6d3aafbb578bd50920de5a69da..4b696dcb929ec212faec1e3e6d9a705def23bae4 100644 --- a/include/maxwell_interface.h +++ b/include/maxwell_interface.h @@ -76,6 +76,7 @@ public: bool has_analytical_solution(void) const; std::pair<vec3d, vec3d> eval_analytical_solution(int, const point_3d&, double t) const; + bool debug_dumpCellRanks(void) const; boundary_condition boundary_type(int tag) const; interface_condition interface_type(int tag) const; diff --git a/src/maxwell_common.cpp b/src/maxwell_common.cpp index 8c96b3249a35d9f171efa695b992b2c96e2da865..feb067e7c311ed687587202a3505a6f182f7b702 100644 --- a/src/maxwell_common.cpp +++ b/src/maxwell_common.cpp @@ -175,6 +175,27 @@ init_lax_milgram(const model& mod, const parameter_loader& mpl, } } +#ifdef USE_MPI +std::vector<double> +compute_cell_ranks(const model& mod) +{ + /* This is only for debug purposes: make a vector mapping from the + * cell number to the rank of the process to which it is assigned */ + std::vector<double> ret( mod.num_cells_world(), 999999999 ); + for (auto& etag : mod.world_entities_tags()) + { + auto& e = mod.entity_world_lookup(etag); + int er = mod.entity_rank(etag); + + for (size_t iT = 0; iT < e.num_cells(); iT++) + { + auto gi = e.cell_world_index_by_gmsh(iT); + ret[gi] = er; + } + } + return ret; +} +#endif /* USE_MPI */ static void export_vector_field_nodal(const model& mod, silo& sdb, const vecxd& Fx, @@ -316,256 +337,4 @@ export_vector_field(const model& mod, silo& sdb, const vecxd& Fx, const vecxd& F } } - - -void export_E_field_nodal(const model& mod, silo& sdb, const vecxd& Ex, - const vecxd& Ey, const vecxd& Ez, const parameter_loader&) -{ - std::vector<double> accum_Ex( sdb.num_nodes(), 0.0 ); - std::vector<double> accum_Ey( sdb.num_nodes(), 0.0 ); - 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_world_dof_offset(iT); - auto nodetags = pe.node_tags(); - for (size_t iD = 0; iD < 4; iD++) - { - size_t tag = nodetags[iD]; - size_t svofs = sdb.node_tag_offset(tag); - accum_Ex[svofs] += Ex[cgofs+iD]; - accum_Ey[svofs] += Ey[cgofs+iD]; - accum_Ez[svofs] += Ez[cgofs+iD]; - count[svofs]++; - } - } - } - - for (size_t i = 0; i < sdb.num_nodes(); i++) - { - accum_Ex[i] /= count[i]; - accum_Ey[i] /= count[i]; - accum_Ez[i] /= count[i]; - } - - sdb.write_nodal_variable("Ex", accum_Ex); - sdb.write_nodal_variable("Ey", accum_Ey); - sdb.write_nodal_variable("Ez", accum_Ez); - sdb.write_vector_expression("E", "{Ex, Ey, Ez}"); -} - -void export_H_field_nodal(const model& mod, silo& sdb, const vecxd& Hx, - const vecxd& Hy, const vecxd& Hz, const parameter_loader&) -{ - std::vector<double> accum_Hx( sdb.num_nodes(), 0.0 ); - std::vector<double> accum_Hy( sdb.num_nodes(), 0.0 ); - 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_world_dof_offset(iT); - auto nodetags = pe.node_tags(); - for (size_t iD = 0; iD < 4; iD++) - { - size_t tag = nodetags[iD]; - size_t svofs = sdb.node_tag_offset(tag); - accum_Hx[svofs] += Hx[cgofs+iD]; - accum_Hy[svofs] += Hy[cgofs+iD]; - accum_Hz[svofs] += Hz[cgofs+iD]; - count[svofs]++; - } - } - } - - for (size_t i = 0; i < sdb.num_nodes(); i++) - { - accum_Hx[i] /= count[i]; - accum_Hy[i] /= count[i]; - accum_Hz[i] /= count[i]; - } - - sdb.write_nodal_variable("Hx", accum_Hx); - sdb.write_nodal_variable("Hy", accum_Hy); - sdb.write_nodal_variable("Hz", accum_Hz); - sdb.write_vector_expression("H", "{Hx, Hy, Hz}"); -} - -void export_J_field_nodal(const model& mod, silo& sdb, const vecxd& Ex, - const vecxd& Ey, const vecxd& Ez, const parameter_loader& mpl) -{ - std::vector<double> accum_Jx( sdb.num_nodes(), 0.0 ); - std::vector<double> accum_Jy( sdb.num_nodes(), 0.0 ); - 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) - { -#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(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++) - { - size_t tag = nodetags[iD]; - size_t svofs = sdb.node_tag_offset(tag); - accum_Jx[svofs] += sigma*Ex[cgofs+iD]; - accum_Jy[svofs] += sigma*Ey[cgofs+iD]; - accum_Jz[svofs] += sigma*Ez[cgofs+iD]; - count[svofs]++; - } - } - } - - for (size_t i = 0; i < sdb.num_nodes(); i++) - { - accum_Jx[i] /= count[i]; - accum_Jy[i] /= count[i]; - accum_Jz[i] /= count[i]; - } - - sdb.write_nodal_variable("Jx", accum_Jx); - sdb.write_nodal_variable("Jy", accum_Jy); - sdb.write_nodal_variable("Jz", accum_Jz); - sdb.write_vector_expression("J", "{Jx, Jy, Jz}"); -} - - - -void export_E_field_zonal(const model& mod, silo& sdb, const vecxd& Ex, - const vecxd& Ey, const vecxd& Ez, const parameter_loader&) -{ - 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() ); - -#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& 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] = 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); - } - } - - 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}"); -} - -void export_H_field_zonal(const model& mod, silo& sdb, const vecxd& Hx, - const vecxd& Hy, const vecxd& Hz, const parameter_loader&) -{ - std::vector<double> out_Hx( mod.num_cells_world() ); - std::vector<double> out_Hy( mod.num_cells_world() ); - std::vector<double> out_Hz( mod.num_cells_world() ); - -#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& 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_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); - } - } - - sdb.write_zonal_variable("Hx", out_Hx); - sdb.write_zonal_variable("Hy", out_Hy); - sdb.write_zonal_variable("Hz", out_Hz); - sdb.write_vector_expression("H", "{Hx, Hy, Hz}"); -} - -void export_J_field_zonal(const model& mod, silo& sdb, const vecxd& Ex, - const vecxd& Ey, const vecxd& Ez, const parameter_loader& mpl) -{ - std::vector<double> out_Jx( mod.num_cells_world() ); - std::vector<double> out_Jy( mod.num_cells_world() ); - std::vector<double> out_Jz( mod.num_cells_world() ); - -#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& re = e.cell_refelem(pe); - auto bar = pe.barycenter(); - 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_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); - } - } - - sdb.write_zonal_variable("Jx", out_Jx); - sdb.write_zonal_variable("Jy", out_Jy); - sdb.write_zonal_variable("Jz", out_Jz); - sdb.write_vector_expression("J", "{Jx, Jy, Jz}"); -} - - } // namespace maxwell diff --git a/src/maxwell_cpu.cpp b/src/maxwell_cpu.cpp index 8c5c807ceb8adb5b36c5297c6759042677a31ed6..98aa9d1056bfb99ea3a91a4852cbd3dbe92fe363 100644 --- a/src/maxwell_cpu.cpp +++ b/src/maxwell_cpu.cpp @@ -9,6 +9,9 @@ namespace maxwell { +/************************************************************************** + * Solver initialization + */ void init_matparams(const model& mod, solver_state& state, const parameter_loader& mpl) @@ -49,10 +52,6 @@ init_matparams(const model& mod, solver_state& state, init_boundary_conditions(mod, mpl, state.matparams.bc_coeffs); } - - - - void init_from_model(const model& mod, solver_state& state) { @@ -97,6 +96,10 @@ init_from_model(const model& mod, solver_state& state) state.curr_timestep = 0; } + +/************************************************************************** + * Computational kernels: curls + */ static void compute_curls(solver_state& state, const field& curr, field& next) { @@ -149,6 +152,9 @@ compute_curls_H(solver_state& state, const field& curr, field& next) } +/************************************************************************** + * Computational kernels: jumps + */ static void compute_field_jumps(solver_state& state, const field& in) { @@ -406,6 +412,9 @@ exchange_boundary_data_H(const model& mod, solver_state& state) } #endif /* USE_MPI */ +/************************************************************************** + * Computational kernels: fluxes + */ static void compute_fluxes_planar(solver_state& state) { @@ -538,6 +547,9 @@ compute_fluxes_planar_H(solver_state& state) } } +/************************************************************************** + * Computational kernels: boundary terms + */ static void compute_fluxes(const model& mod, solver_state& state, const field& in, field& out) { @@ -598,6 +610,9 @@ compute_fluxes_H(const model& mod, solver_state& state, const field& in, field& } } +/************************************************************************** + * Computational kernels: time integration + */ static void compute_euler_update(solver_state& state, const field& y, const field& k, double dt, field& out) { @@ -640,6 +655,9 @@ compute_rk4_weighted_sum(solver_state& state, const field& in, double dt, field& } } +/************************************************************************** + * Computational kernels: H&W DG operator + */ static void apply_operator(const model& mod, solver_state& state, const field& curr, field& next) { @@ -647,6 +665,9 @@ apply_operator(const model& mod, solver_state& state, const field& curr, field& compute_fluxes(mod, state, curr, next); } +/************************************************************************** + * Computational kernels: Leapfrog DG + */ static void leapfrog(const model& mod, solver_state& state) { @@ -675,6 +696,9 @@ leapfrog(const model& mod, solver_state& state) } } +/************************************************************************** + * Computational kernels: Run a whole timestep + */ void timestep(const model& mod, solver_state& state, const parameter_loader&, time_integrator_type ti) { @@ -709,6 +733,9 @@ timestep(const model& mod, solver_state& state, const parameter_loader&, time_in state.curr_timestep += 1; } +/************************************************************************** + * Sources: volumetric + */ void eval_volume_sources(const model& mod, const parameter_loader& mpl, solver_state& state) { @@ -842,104 +869,11 @@ export_fields_to_silo(const model &mod, maxwell::solver_state &state, auto J_exportmode = mpl.postpro_fieldExportMode("J"); export_vector_field(mod, sdb, f.Ex, f.Ey, f.Ez, sigma, "J", J_exportmode); - std::vector<double> entranks( mod.num_cells_world(), 999999999 ); - for (auto& etag : mod.world_entities_tags()) - { - auto& e = mod.entity_world_lookup(etag); - int er = mod.entity_rank(etag); - - for (size_t iT = 0; iT < e.num_cells(); iT++) - { - auto gi = e.cell_world_index_by_gmsh(iT); - entranks[gi] = er; - } - } - sdb.write_zonal_variable("entity_ranks", entranks); - } - else - { - maxwell::field dummy; - gather_field(mod, state.emf_next, dummy, 0, MPI_COMM_WORLD); - } -} - -void -export_fields_to_silo(const model& mod, maxwell::solver_state& state, - const maxwell::parameter_loader& mpl) -{ - int rank; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - - if (rank == 0) - { - size_t gdnum = mod.num_dofs_world(); - maxwell::field f; - f.resize(gdnum); - gather_field(mod, state.emf_next, f, 0, MPI_COMM_WORLD); - - 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") ) + if ( mpl.debug_dumpCellRanks() ) { - 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; - - case field_export_mode::ZONAL: - export_E_field_zonal(mod, sdb, f.Ex, f.Ey, f.Ez, mpl); - break; - } - - switch( mpl.postpro_fieldExportMode("H") ) - { - 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; + auto entranks = compute_cell_ranks(mod); + sdb.write_zonal_variable("entity_ranks", entranks); } - - 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; - } - - std::vector<double> entranks( mod.num_cells_world(), 999999999 ); - for (auto& etag : mod.world_entities_tags()) - { - auto& e = mod.entity_world_lookup(etag); - int er = mod.entity_rank(etag); - - for (size_t iT = 0; iT < e.num_cells(); iT++) - { - auto gi = e.cell_world_index_by_gmsh(iT); - entranks[gi] = er; - } - } - sdb.write_zonal_variable("entity_ranks", entranks); } else { @@ -980,67 +914,6 @@ export_fields_to_silo(const model &mod, maxwell::solver_state &state, state.emf_next.Ez, sigma, "J", J_exportmode); } - -void -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")) - { - case field_export_mode::NONE: - break; - - case field_export_mode::NODAL: - export_E_field_nodal(mod, sdb, state.emf_next.Ex, state.emf_next.Ey, - state.emf_next.Ez, mpl); - break; - - case field_export_mode::ZONAL: - export_E_field_zonal(mod, sdb, state.emf_next.Ex, state.emf_next.Ey, - state.emf_next.Ez, mpl); - break; - } - - switch (mpl.postpro_fieldExportMode("H")) - { - case field_export_mode::NONE: - break; - - case field_export_mode::NODAL: - export_H_field_nodal(mod, sdb, state.emf_next.Hx, state.emf_next.Hy, - state.emf_next.Hz, mpl); - break; - - case field_export_mode::ZONAL: - export_H_field_zonal(mod, sdb, state.emf_next.Hx, state.emf_next.Hy, - state.emf_next.Hz, mpl); - break; - } - - switch (mpl.postpro_fieldExportMode("J")) - { - case field_export_mode::NONE: - break; - - case field_export_mode::NODAL: - export_J_field_nodal(mod, sdb, state.emf_next.Ex, state.emf_next.Ey, - state.emf_next.Ez, mpl); - break; - - case field_export_mode::ZONAL: - export_J_field_zonal(mod, sdb, state.emf_next.Ex, state.emf_next.Ey, - state.emf_next.Ez, mpl); - break; - } -} #endif /* USE_MPI */ } // namespace maxwell diff --git a/src/maxwell_gpu.cpp b/src/maxwell_gpu.cpp index 6756b64bbe831f2cb9c5d12a7dd456aa420c8357..b1d124803e5eea41b6ed7b786ea2e7d9169f42fa 100644 --- a/src/maxwell_gpu.cpp +++ b/src/maxwell_gpu.cpp @@ -570,11 +570,14 @@ export_fields_to_silo(const model& mod, maxwell::solver_state_gpu& state, void export_fields_to_silo(const model& mod, maxwell::solver_state_gpu& state, - const maxwell::parameter_loader& mpl) + const maxwell::parameter_loader& mpl, std::string basename) { + if (basename == "") + basename = "timestep"; + std::stringstream ss; - ss << mpl.sim_name() << "/timestep_" << state.curr_timestep << ".silo"; - + ss << mpl.sim_name() << "/" << basename << "_" << state.curr_timestep << ".silo"; + silo sdb; sdb.create_db(ss.str()); sdb.import_mesh_from_gmsh(); @@ -584,47 +587,16 @@ export_fields_to_silo(const model& mod, maxwell::solver_state_gpu& state, f.resize( mod.num_dofs() ); state.emf_next.copyout(f); - 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; - case field_export_mode::ZONAL: - export_E_field_zonal(mod, sdb, f.Ex, f.Ey, f.Ez, mpl); - break; - } + auto E_exportmode = mpl.postpro_fieldExportMode("E"); + export_vector_field(mod, sdb, f.Ex, f.Ey, f.Ez, "E", E_exportmode); - switch( mpl.postpro_fieldExportMode("H") ) - { - case field_export_mode::NONE: - break; + auto H_exportmode = mpl.postpro_fieldExportMode("H"); + export_vector_field(mod, sdb, f.Hx, f.Hy, f.Hz, "H", H_exportmode); - 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; - } - - 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; - } + auto sigma = [&](int tag, const point_3d& pt) -> double { return mpl.sigma(tag, pt); }; + auto J_exportmode = mpl.postpro_fieldExportMode("J"); + export_vector_field(mod, sdb, f.Ex, f.Ey, f.Ez, sigma, "J", J_exportmode); } #endif /* USE_MPI */ diff --git a/src/maxwell_interface.cpp b/src/maxwell_interface.cpp index 9bbaa66246b97c1199e5038b7040ff06ed184fbb..8b975b216507297c2efa05edc870b0db0fa5ad2b 100644 --- a/src/maxwell_interface.cpp +++ b/src/maxwell_interface.cpp @@ -706,4 +706,14 @@ parameter_loader::eval_analytical_solution(int tag, const point_3d& pt, double t return std::make_pair(E,H); } +bool +parameter_loader::debug_dumpCellRanks(void) const +{ + auto dcr = lua["debug"]["dump_cell_ranks"]; + if (not dcr.valid()) + return false; + + return (dcr == true); +} + } // namespace maxwell diff --git a/src/maxwell_solver.cpp b/src/maxwell_solver.cpp index 1dca331dec75864435b614612f21785a49d8d89e..63b92d5da852566d28934b8eb34b9f03aaeda18a 100644 --- a/src/maxwell_solver.cpp +++ b/src/maxwell_solver.cpp @@ -21,6 +21,9 @@ #include "param_loader.h" #include "timecounter.h" +#include "sgr.hpp" +using namespace sgr; + #if 0 static void make_geometry(int order, double mesh_h) @@ -227,8 +230,14 @@ maxwell_6ple sqrt(const maxwell_6ple& m) return ret; } +double hsum(const maxwell_6ple& m) +{ + return m.Ex + m.Ey + m.Ez + m.Hx + m.Hy + m.Hz; +} + static void -validate(const model& mod, maxwell::solver_state& state, maxwell::parameter_loader& mpl, std::ofstream& ofs) +validate(const model& mod, maxwell::solver_state& state, + maxwell::parameter_loader& mpl, std::ofstream& ofs) { maxwell_6ple err; maxwell_6ple energy; @@ -255,7 +264,8 @@ validate(const model& mod, maxwell::solver_state& state, maxwell::parameter_load { const auto& pqp = pqps[iQp]; const vecxd phi = re.basis_functions(iQp); - auto [E, H] = mpl.eval_analytical_solution(e.material_tag(), pqp.point(), state.curr_time); + auto [E, H] = mpl.eval_analytical_solution(e.material_tag(), + pqp.point(), state.curr_time); maxwell_6ple Fh; Fh.Ex = state.emf_next.Ex.segment(ofs, cbs).dot(phi); @@ -283,15 +293,15 @@ validate(const model& mod, maxwell::solver_state& state, maxwell::parameter_load } } - ofs << energy.Ex << " " << energy.Ey << " " << energy.Ez << " " << energy.Hx; - ofs << " " << energy.Hy << " " << energy.Hz << " "; - ofs << energy.Ex + energy.Ey + energy.Ez + energy.Hx + energy.Hy + energy.Hz;// << std::endl; - ofs << " " << sqrt(err) << std::endl; + ofs << energy << " " << hsum(energy) << " " << sqrt(err) << std::endl; } -//static void -//validate(const model& mod, maxwell::solver_state_gpu& state, maxwell::parameter_loader& mpl) -//{} +#ifdef ENABLE_GPU_SOLVER +static void +validate(const model& mod, maxwell::solver_state_gpu& state, + maxwell::parameter_loader& mpl, std::ofstream&) +{} +#endif /* ENABLE_GPU_SOLVER */ template<typename State> void solver_mainloop(const model& mod, State& state, maxwell::parameter_loader& mpl) @@ -327,6 +337,9 @@ void solver_mainloop(const model& mod, State& state, maxwell::parameter_loader& mpl.call_initialization_callback(); #ifdef ENABLE_EXP_GEOMETRIC_DIODE + #ifdef USE_MPI + #error "The geometric diode code is not compatible with MPI yet." + #endif auto relmat = [&](){ reinit_materials(mod, state, mpl); }; sol::state& lua = mpl.lua_state(); @@ -358,16 +371,19 @@ void solver_mainloop(const model& mod, State& state, maxwell::parameter_loader& MPI_Reduce(&dofs_s_proc, &dofs_s_total, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (proc_rank == 0) { - std::cout << "Cycle " << i << ": t = " << state.curr_time << " s"; - std::cout << ", DOFs/s: " << dofs_s_total << std::endl; + std::cout << hidecursor << clrline << "Cycle " << i << ": t = "; + std::cout << state.curr_time << " s" << ", DOFs/s: "; + std::cout << dofs_s_total << cr << std::flush; } #else /* USE_MPI */ - std::cout << "Cycle " << i << ": t = " << state.curr_time << " s"; - std::cout << ", DOFs/s: " << dofs_s_proc << std::endl; + std::cout << hidecursor << clrline << "Cycle " << i << ": t = "; + std::cout << state.curr_time << " s" << ", DOFs/s: "; + std::cout << dofs_s_proc << cr << std::flush; #endif /* USE_MPI */ tc.tic(); } } + std::cout << showcursor << std::endl; } static void @@ -483,6 +499,9 @@ int main(int argc, char *argv[]) if ( mpl.sim_usegpu() ) { #ifdef ENABLE_GPU_SOLVER + #ifdef USE_MPI + #error "The GPU solver is not compatible with MPI yet." + #endif maxwell::solver_state_gpu state_g; register_lua_usertypes_bystate(mpl, mod, state_g); solver_mainloop(mod, state_g, mpl);