diff --git a/include/libgmshdg/gmsh_io.h b/include/libgmshdg/gmsh_io.h index 81d959b50f647796988a042dad898b3a5a9f8453..c642d40f4dcd5dc6480d2f48407426ca516bcf8d 100644 --- a/include/libgmshdg/gmsh_io.h +++ b/include/libgmshdg/gmsh_io.h @@ -183,11 +183,8 @@ public: model(const char *, int, int); ~model(); - void build(void); - void build(double); + void build(); - void generate_mesh(void); - void generate_mesh(double); void partition_mesh(int); void populate_from_gmsh(void); diff --git a/include/libgmshdg/param_loader.h b/include/libgmshdg/param_loader.h index 7ca629455d77b287ecebedd1cc1b031cdb6dc507..4390e96258208fdac076bb74cc2b9bc6ad4b2c49 100644 --- a/include/libgmshdg/param_loader.h +++ b/include/libgmshdg/param_loader.h @@ -66,6 +66,8 @@ public: void call_timestep_callback(size_t); void call_initialization_callback(); + void call_finalization_callback(); + sol::state& lua_state(void) { return lua; } }; diff --git a/include/maxwell/maxwell_postpro.h b/include/maxwell/maxwell_postpro.h index fe345ade591e8aedd4380882c93e0db6768a4020..943bf50aedc0dc1c22e84ec334858d54653e0fea 100644 --- a/include/maxwell/maxwell_postpro.h +++ b/include/maxwell/maxwell_postpro.h @@ -8,5 +8,7 @@ field_values eval_field(const field&, size_t, size_t, const vecxd&); field_values compute_error(const model&, const solver_state&, const parameter_loader&); field_values compute_energy(const model&, const solver_state&, const parameter_loader&); +void compare_at_gauss_points(const model&, const solver_state&, const parameter_loader&); + } // namespace maxwell diff --git a/share/examples/capacitor/capacitor.geo b/share/examples/capacitor/capacitor.geo index 3a2306b212ef89647147b81b13ab669689d57781..b20a1d3c68b5d4940068f681f601063814b87ab2 100644 --- a/share/examples/capacitor/capacitor.geo +++ b/share/examples/capacitor/capacitor.geo @@ -11,4 +11,10 @@ Cylinder(3) = {0, 0, -d/2-t, 0, 0, t, R}; Sphere(4) = {0, 0, 0, 2*R, -Pi/2, Pi/2, 2*Pi}; Coherence; +Physical Volume(1000) = {1, 3}; +Physical Volume(1001) = {2}; +Physical Volume(1002) = {4}; + +Physical Surface(2000) = {1}; + MeshSize{ PointsOf{ Volume{2}; } } = 0.0003; diff --git a/share/examples/capacitor2/capacitor.geo b/share/examples/capacitor2/capacitor.geo index 3a2306b212ef89647147b81b13ab669689d57781..b20a1d3c68b5d4940068f681f601063814b87ab2 100644 --- a/share/examples/capacitor2/capacitor.geo +++ b/share/examples/capacitor2/capacitor.geo @@ -11,4 +11,10 @@ Cylinder(3) = {0, 0, -d/2-t, 0, 0, t, R}; Sphere(4) = {0, 0, 0, 2*R, -Pi/2, Pi/2, 2*Pi}; Coherence; +Physical Volume(1000) = {1, 3}; +Physical Volume(1001) = {2}; +Physical Volume(1002) = {4}; + +Physical Surface(2000) = {1}; + MeshSize{ PointsOf{ Volume{2}; } } = 0.0003; diff --git a/share/examples/capacitor2/params_capacitor.lua b/share/examples/capacitor2/params_capacitor.lua index c1bc00acb52754f87738f07d82ec3a2a78b86a51..6e7787a38ac3f97ebde149a1cc0421fa0cd150e8 100644 --- a/share/examples/capacitor2/params_capacitor.lua +++ b/share/examples/capacitor2/params_capacitor.lua @@ -1,11 +1,11 @@ sim.name = "capacitor" -- simulation name sim.dt = 1e-14 -- timestep size -sim.timesteps = 1001 -- num of iterations -sim.gmsh_model = "capacitor.geo" -- gmsh model filename +sim.timesteps = 101 -- num of iterations +sim.gmsh_model = "capacitor.msh" -- gmsh model filename sim.use_gpu = 0 -- 0: cpu, 1: gpu -sim.approx_order = 1 -- approximation order +sim.approx_order = 2 -- approximation order sim.time_integrator = "leapfrog" -- time integration method -postpro.silo_output_rate = 10 -- rate at which to write silo files +postpro.silo_output_rate = 100 -- rate at which to write silo files postpro.cycle_print_rate = 10 -- console print rate local diel_epsr = 10 -- Permittivity of the capacitor dielectric @@ -38,11 +38,11 @@ for i,v in ipairs(air) do end -- ** Boundary conditions ** -local absorbing_bcs = {1} -for i,v in ipairs(absorbing_bcs) do - bndconds[v] = {} - bndconds[v].kind = "impedance" -end +--local absorbing_bcs = {1} +--for i,v in ipairs(absorbing_bcs) do +-- bndconds[v] = {} +-- bndconds[v].kind = "impedance" +--end local R = 0.01 -- Capacitor disk radius (must match capacitor.geo) local d = 0.001 -- Dielectric thickness (must match capacitor.geo) @@ -103,6 +103,15 @@ end -- Apply the current source to entity 2 sources[2] = current_source + +function on_timestepping_finished() + if ( do_IO ) then + print("\x1b[32m*** GMSH-FEM COMPARISON DATA ***\x1b[0m") + --compare_at_gauss_points() -- NOT MPI SAFE + end +end + + -- Dump charging current profile for debug if ( do_IO ) then local file = io.open("current_profile.dat", "w") diff --git a/share/validation/params_resonator_gmshfem_comparison.lua b/share/validation/params_resonator_gmshfem_comparison.lua new file mode 100644 index 0000000000000000000000000000000000000000..7d8a785d3003b3b55a0d3a1c10d153b2eaf8d0cc --- /dev/null +++ b/share/validation/params_resonator_gmshfem_comparison.lua @@ -0,0 +1,97 @@ +-- Resonant cavity test. See Pozar, section 6.3 for theory. + +----------------------- +--[[ Problem setup ]]-- +sim.name = "test_maxwell_resonator" -- simulation name +sim.dt = 1e-11 -- timestep size +sim.timesteps = 11 -- num of iterations +sim.gmsh_model = "resonator.geo" -- gmsh model filename +sim.use_gpu = 0 -- 0: cpu, 1: gpu +sim.approx_order = 2 -- approximation order +sim.time_integrator = "leapfrog" +postpro.silo_output_rate = 100 +postpro.cycle_print_rate = 10 -- console print rate + +postpro["E"].silo_mode = "zonal" +postpro["H"].silo_mode = "none" +postpro["J"].silo_mode = "none" + +local epsr = 1 +local mur = 1 + +materials[1] = {} +materials[1].epsilon = epsr +materials[1].mu = mur +materials[1].sigma = 0 + +function electric_initial_condition(x, y, z) + local Ex = 0 + local Ey = math.sin(math.pi*x) * math.sin(math.pi*z) + local Ez = 0 + return Ex, Ey, Ez +end + +-------------------------- +--[[ Validation stuff ]]-- +debug = {} + +-- determine if we should do I/O +local do_IO = (not parallel) or (parallel and parallel.comm_rank == 0) + +local c0 = 1/math.sqrt(const.eps0*const.mu0) +-- Mode +local m = 1 -- along x +local n = 0 -- along y +local l = 1 -- along z +-- Cavity dimensions (must match sim.gmsh_model) +local a = 1 -- along x +local b = 0.1 -- along y +local d = 1 -- along z + +local u = m*math.pi/a +local v = n*math.pi/b +local w = l*math.pi/d +-- Compute resonant frequency +local omega = c0*math.sqrt(u*u + v*v + w*w)/math.sqrt(epsr*mur) +local resonance_f = omega/(2*math.pi) +local resonance_MHz = resonance_f/1e6 +local cycle_timesteps = 1/(resonance_f*sim.dt) +-- Compute impedance +local eps = materials[1].epsilon * const.eps0 +local mu = materials[1].mu * const.mu0 +local k_sq = (omega*mu)*(omega*eps) +local kc_sq = u*u + v*v +local beta = math.sqrt(k_sq - kc_sq) +local Zte = omega*mu/beta +local We = eps*a*b*d/16 + +if ( do_IO ) then + print("\x1b[1mANALYTICAL SOLUTION DATA:") + print(" Resonance frequency: " .. resonance_MHz .. " Mhz") + print(" Cavity impedance: " .. Zte .. " Ohm") + print(" Timesteps for 1 cycle: " .. cycle_timesteps) + print(" Expected energy " .. 2*We .. " J \x1b[0m") +end + +function ansol(tag, x, y, z, t) + local Ex = 0.0 + local Ey = math.cos(omega*t)*math.sin(math.pi*x)*math.sin(math.pi*z) + local Ez = 0.0 + local Hx = math.sin(omega*t)*math.sin(math.pi*x)*math.cos(math.pi*z)/Zte + local Hy = 0.0 + local Hz = -math.sin(omega*t)*math.cos(math.pi*x)*math.sin(math.pi*z)/Zte + + return Ex, Ey, Ez, Hx, Hy, Hz +end + +debug.analytical_solution = ansol +--debug.dump_cell_ranks = true + +function on_timestepping_finished() + err = compute_error() + if ( do_IO ) then + print("\x1b[32m*** GMSH-FEM COMPARISON DATA ***\x1b[0m") + print("Error on Ey: " .. err.Ey) + compare_at_gauss_points() -- NOT MPI SAFE + end +end diff --git a/share/validation/resonator.geo b/share/validation/resonator.geo index 3c3f82936d969c3b7a9a80eeb9c048c2b67cbfac..8c80fad0745ead4e1c2e54b635226b093822b3b7 100644 --- a/share/validation/resonator.geo +++ b/share/validation/resonator.geo @@ -1,4 +1,7 @@ SetFactory("OpenCASCADE"); -Box(1) = {0, 0, 0, 1, 0.1, 1}; +Box(1) = {0, 0, 0, 1, 1, 1}; + +Physical Volume(1000) = {1}; +Physical Surface(2000) = {1,2,3,4,5,6}; MeshSize{:} = 0.05; diff --git a/src/libgmshdg/gmsh_io.cpp b/src/libgmshdg/gmsh_io.cpp index 23f5fb7225fb0b35689990da4999362e00b1eb97..056aee4b9ed20cbbf31e1c81a18338462ee6df88 100644 --- a/src/libgmshdg/gmsh_io.cpp +++ b/src/libgmshdg/gmsh_io.cpp @@ -10,6 +10,9 @@ #include "common/mpi_helpers.h" #endif /* USE_MPI */ +#include "sgr.hpp" +using namespace sgr; + std::string quadrature_name(int order) { @@ -252,13 +255,14 @@ model::import_gmsh_entities_rank0(void) flux_base_world += e.num_fluxes(); index_base_world += e.num_cells(); - /* Send entity to the appropriate process */ assert(tag_partition > 0); int rank = tag_partition - 1; - e.mpi_send(rank, MPI_COMM_WORLD); #ifdef ENABLE_DEBUG_PRINT - std::cout << "Sending entity " << tag << " to " << rank << " " << e.num_dofs() << std::endl; + std::cout << "Sending entity " << tag << " to " << rank << ", "; + std::cout << e.num_dofs() << " DoFs" << std::endl; #endif /* ENABLE_DEBUG_PRINT */ + /* Send entity to the appropriate process */ + e.mpi_send(rank, MPI_COMM_WORLD); /* Save locally the entity */ remote_entities[tag_partition].push_back( std::move(e) ); all_entities_tags.push_back(tag); @@ -341,13 +345,14 @@ model::import_gmsh_entities_rankN(void) for (auto& rtag : partition_map.at(mp)) { entity e; - e.mpi_recv(0, MPI_COMM_WORLD); - #ifdef ENABLE_DEBUG_PRINT - std::cout << "Receiving " << rtag << ", rank " << mp-1 << " "; - std::cout << e.num_dofs() << std::endl; + std::cout << "Receiving " << rtag << ", rank " << mp-1 << ", "; #endif /* ENABLE_DEBUG_PRINT */ (void) rtag; + e.mpi_recv(0, MPI_COMM_WORLD); +#ifdef ENABLE_DEBUG_PRINT + std::cout << e.num_dofs() << " DoFs" << std::endl; +#endif /* ENABLE_DEBUG_PRINT */ for (size_t i = 0; i < e.num_cells(); i++) { @@ -405,17 +410,38 @@ model::get_facekey_tag_pairs(void) void model::map_boundaries(void) { -#ifdef USE_MPI - //ASSERT_MPI_RANK_0; -#endif /* USE_MPI */ std::vector<bfk_t> bfk = get_facekey_tag_pairs(); for (size_t i = 1; i < bfk.size(); i++) { if ( bfk[i-1].first == bfk[i].first ) { - std::cout << bfk[i-1].second << " " << bfk[i].second << std::endl; + std::cout << redfg << Bon << "WARNING: " << nofg << __FILE__; + std::cout << "(" << __LINE__ << "): Face identified by "; + std::cout << bfk[i].first << " was found on interfaces "; + std::cout << bfk[i-1].second; +#ifdef USE_MPI + if ( is_interprocess_boundary(bfk[i-1].second) ) + std::cout << " (IP)"; +#endif + std::cout << " and " << bfk[i].second; +#ifdef USE_MPI + if ( is_interprocess_boundary(bfk[i].second) ) + std::cout << " (IP)"; + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + std::cout << " [MPI rank " << rank << "]"; +#endif + std::cout << ". " << reset << std::endl; + /* +#ifdef USE_MPI + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + if (rank == 0) +#endif + gmsh::write("crash.msh"); throw 42; + */ } } @@ -668,7 +694,7 @@ void model::populate_from_gmsh_rank0() { #ifdef USE_MPI - ASSERT_MPI_RANK_0; + ASSERT_MPI_RANK_0; #endif /* USE_MPI */ gmm::setOrder( geometric_order ); @@ -764,36 +790,10 @@ model::populate_from_gmsh() void model::build() { - generate_mesh(); - make_boundary_to_faces_map(); + //make_boundary_to_faces_map(); populate_from_gmsh_rank0(); } -void -model::build(double sf) -{ - generate_mesh(sf); - make_boundary_to_faces_map(); - populate_from_gmsh_rank0(); -} - -void -model::generate_mesh() -{ - gmm::generate( DIMENSION(3) ); -} - -void -model::generate_mesh(double sf) -{ - gmm::generate( DIMENSION(3) ); - - std::vector<double> tr = {sf, 0, 0, 0, - 0, sf, 0, 0, - 0, 0, sf, 0 }; - gmm::affineTransform(tr); -} - #ifdef USE_MPI void model::partition_mesh(int parts) diff --git a/src/libgmshdg/param_loader.cpp b/src/libgmshdg/param_loader.cpp index 238da20ec851af53dad694de80ccb29394348196..831aec733bbb5265218b0c7b6df0ff5e7f231102 100644 --- a/src/libgmshdg/param_loader.cpp +++ b/src/libgmshdg/param_loader.cpp @@ -247,6 +247,21 @@ parameter_loader_base::call_initialization_callback() } } +void +parameter_loader_base::call_finalization_callback() +{ + if ( lua["on_timestepping_finished"].valid() ) + { + try { + lua["on_timestepping_finished"](); + } + catch (...) + { + std::cout << "An error was thrown calling on_timestepping_finished()" << std::endl; + } + } +} + bool parameter_loader_base::source_has_changed_state(void) const { diff --git a/src/libgmshdg/physical_element.cpp b/src/libgmshdg/physical_element.cpp index c9190fae938339f837f4051c0981179588681dc2..655c49cffdebad422c532a5e23ec22edf2f5b85d 100644 --- a/src/libgmshdg/physical_element.cpp +++ b/src/libgmshdg/physical_element.cpp @@ -1,5 +1,6 @@ #include <iostream> #include <cassert> +#include <fstream> #include "libgmshdg/physical_element.h" #include "libgmshdg/gmsh_io.h" diff --git a/src/maxwell/maxwell_postpro.cpp b/src/maxwell/maxwell_postpro.cpp index 2d162f6c88c5893fb7b0b9ecba87a9779bc9a5a7..7dc612f40e3a8717f46daf5592892b84a1925aec 100644 --- a/src/maxwell/maxwell_postpro.cpp +++ b/src/maxwell/maxwell_postpro.cpp @@ -1,4 +1,7 @@ +#include <fstream> +#include <fcntl.h> + #ifdef USE_MPI #include "common/mpi_helpers.h" #endif /* USE_MPI */ @@ -37,12 +40,10 @@ compute_error(const model& mod, const solver_state& state, const parameter_loade const auto& re = e.cell_refelem(pe); const auto pqps = pe.integration_points(); - const auto dets = pe.determinants(); const auto ofs = e.cell_model_dof_offset(iT); const auto cbs = re.num_basis_functions(); - assert(pqps.size() == dets.size()); for (size_t iQp = 0; iQp < pqps.size(); iQp++) { const auto& pqp = pqps[iQp]; @@ -78,12 +79,10 @@ compute_energy(const model& mod, const solver_state& state, const parameter_load const auto& re = e.cell_refelem(pe); const auto pqps = pe.integration_points(); - const auto dets = pe.determinants(); const auto ofs = e.cell_model_dof_offset(iT); const auto cbs = re.num_basis_functions(); - assert(pqps.size() == dets.size()); const auto bar = pe.barycenter(); auto eps = mpl.epsilon( e.material_tag(), bar ); auto mu = mpl.mu( e.material_tag(), bar ); @@ -113,5 +112,92 @@ validate(const model&, maxwell::solver_state_gpu&, {} #endif /* ENABLE_GPU_SOLVER */ + +void +compare_at_gauss_points(const model& mod, const solver_state& state, const parameter_loader& mpl) +{ + struct qpFval { double Fx, Fy, Fz; }; + + size_t point_id = 0; + std::ofstream pmap_ofs("pointmap.txt"); + + double errorsq_dg_vs_gmshfem = 0.0; + double errorsq_dg_vs_ana = 0.0; + double errorsq_gmshfem_vs_ana = 0.0; + double normsq_dg = 0.0; + double normsq_gmshfem = 0.0; + double normsq_ana = 0.0; + for (auto& e : mod) + { + std::stringstream ss; + ss << "e_" << e.gmsh_dim() << "_" << e.gmsh_tag() << ".dat"; + + std::cout << "Loading " << ss.str() << std::endl; + int fd = open(ss.str().c_str(), O_RDONLY); + if (fd < 0) + { + std::cout << "Can't open '" << ss.str() << "'" << std::endl; + return; + } + size_t num_vals; + read(fd, &num_vals, sizeof(size_t)); + std::cout << "Reading " << num_vals << " values" << std::endl; + std::vector<qpFval> qpFvals(num_vals); + read(fd, qpFvals.data(), num_vals*sizeof(qpFval)); + close(fd); + + std::cout << "Num of cells: " << e.num_cells() << std::endl; + for (size_t iT = 0; iT < e.num_cells(); iT++) + { + const auto& pe = e.cell(iT); + const auto& re = e.cell_refelem(pe); + const auto ofs = e.cell_model_dof_offset(iT); + const auto cbs = re.num_basis_functions(); + const auto pqps = pe.integration_points(); + + const auto gmsh_pos = e.cell_local_index_by_gmsh(iT); + const size_t num_qps = pqps.size(); + const size_t qps_pos_base = num_qps*gmsh_pos; + for (size_t iQp = 0; iQp < num_qps; iQp++) + { + const auto& pqp = pqps[iQp]; + const vecxd phi = re.basis_functions(iQp); + field_values Fh = eval_field(state.emf_curr, ofs, cbs, phi); + auto& qpFval = qpFvals.at(qps_pos_base+iQp); + auto Exd = Fh.Ex - qpFval.Fx; + auto Eyd = Fh.Ey - qpFval.Fy; + auto Ezd = Fh.Ez - qpFval.Fz; + errorsq_dg_vs_gmshfem += pqp.weight() * (Exd*Exd + Eyd*Eyd + Ezd*Ezd); + normsq_dg += pqp.weight() * (Fh.Ex*Fh.Ex + Fh.Ey*Fh.Ey + Fh.Ez*Fh.Ez); + normsq_gmshfem += pqp.weight() * (qpFval.Fx*qpFval.Fx + qpFval.Fy*qpFval.Fy + qpFval.Fz*qpFval.Fz); + + auto p = pqp.point(); + auto Ey_ana = std::sin(M_PI*p.x())*std::sin(M_PI*p.z())*std::cos(2.*M_PI*211.98528005809e6*state.curr_time); + normsq_ana += pqp.weight() * Ey_ana * Ey_ana; + errorsq_dg_vs_ana += pqp.weight() * ( (Fh.Ey - Ey_ana)*(Fh.Ey - Ey_ana) ); + errorsq_gmshfem_vs_ana += pqp.weight() * ( (qpFval.Fy - Ey_ana)*(qpFval.Fy - Ey_ana) ); + pmap_ofs << pe.element_tag() << " " << qps_pos_base+iQp << " " << p.x() << " " << p.y() << " " << p.z() << " " << point_id++ << std::endl; + } + } + } + + double norm_dg_error = 100.*(std::sqrt(normsq_dg) - std::sqrt(normsq_ana))/std::sqrt(normsq_ana); + double norm_gmshfem_error = 100.*(std::sqrt(normsq_gmshfem) - std::sqrt(normsq_ana))/std::sqrt(normsq_ana); + std::cout << sgr::Bredfg << "Errors and norms:" << sgr::reset << std::endl; + std::cout << " Analytic norm: " << std::sqrt(normsq_ana) << std::endl; + std::cout << " Computed norm (DG): " << std::sqrt(normsq_dg) << ", off by " << norm_dg_error << " %" << std::endl; + std::cout << sgr::BYellowfg; + std::cout << " Computed norm (FEM): " << std::sqrt(normsq_gmshfem) << ", off by " << norm_gmshfem_error << " %" << std::endl; + std::cout << sgr::reset; + + auto dgvsfem_percent = 100.*std::sqrt(errorsq_dg_vs_gmshfem)/std::sqrt(normsq_gmshfem); + std::cout << " DG vs. FEM: " << std::sqrt(errorsq_dg_vs_gmshfem) << ", " << dgvsfem_percent << " %" << std::endl; + std::cout << " DG vs. analytic: " << std::sqrt(errorsq_dg_vs_ana) << std::endl; + std::cout << sgr::BYellowfg; + std::cout << " FEM vs. analytic: " << std::sqrt(errorsq_gmshfem_vs_ana) << std::endl; + std::cout << sgr::reset; +} + + } // namespace maxwell diff --git a/src/maxwell/maxwell_solver.cpp b/src/maxwell/maxwell_solver.cpp index 179afbcb2d57edc34abeb1336b0eb06e23b92d42..514d2b73d2694fae782141a464cab9777d66c371 100644 --- a/src/maxwell/maxwell_solver.cpp +++ b/src/maxwell/maxwell_solver.cpp @@ -1,3 +1,5 @@ +#include <regex> + #ifdef DONT_USE_STD_FILESYSTEM #include <sys/stat.h> #include <sys/types.h> @@ -5,6 +7,9 @@ #include <filesystem> #endif +#include <sys/time.h> +#include <sys/resource.h> + #ifdef USE_MPI #pragma clang diagnostic push #pragma clang diagnostic ignored "-Weverything" @@ -191,13 +196,25 @@ void solver_mainloop(const model& mod, State& state, maxwell::parameter_loader& if (proc_rank == 0) { #endif /* USE_MPI */ std::cout << " BEGINNING SIMULATION" << std::endl; - std::cout << "I will do " << num_timesteps << " of " << state.delta_t; + std::cout << "I will do " << num_timesteps << " timesteps of " << state.delta_t; std::cout << "s each." << std::endl; std::cout << "Time integrator: " << mpl.sim_timeIntegratorName() << std::endl; #ifdef USE_MPI } #endif /* USE_MPI */ +#ifdef USE_MPI + size_t my_num_dofs = 6*mod.num_dofs(); + size_t num_dofs; + MPI_Reduce(&my_num_dofs, &num_dofs, 1, MPI_UNSIGNED_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD); + if (proc_rank == 0) + std::cout << "Model has " << num_dofs << " DoFs" << std::endl; +#else /* USE_MPI */ + size_t num_dofs = 6*mod.num_dofs(); + std::cout << "Model has " << num_dofs << " DoFs" << std::endl; +#endif /* USE_MPI */ + + mpl.call_initialization_callback(); #ifdef ENABLE_EXP_GEOMETRIC_DIODE #ifdef USE_MPI @@ -208,15 +225,22 @@ void solver_mainloop(const model& mod, State& state, maxwell::parameter_loader& sol::state& lua = mpl.lua_state(); lua["relmat"] = relmat; #endif /* ENABLE_EXP_GEOMETRIC_DIODE */ - timecounter tc; - tc.tic(); + + double total_iteration_time = 0.; + prepare_sources(mod, state, mpl); for(size_t i = 0; i < num_timesteps; i++) { + timecounter tc; + tc.tic(); + mpl.call_timestep_callback(i); timestep(mod, state, mpl, ti); do_sources(mod, state, mpl); + double time = tc.toc(); + total_iteration_time += time; + if ( (silo_output_rate != 0) and (i%silo_output_rate == 0) ) export_fields_to_silo(mod, state, mpl, ""); @@ -224,29 +248,44 @@ void solver_mainloop(const model& mod, State& state, maxwell::parameter_loader& if ( (cycle_print_rate != 0) and (i%cycle_print_rate == 0) ) { - double time = tc.toc(); - double dofs_s_proc = (mod.num_dofs()*6*cycle_print_rate)/(time); + double dofs_s_proc = (mod.num_dofs()*6)/time; #ifdef USE_MPI double dofs_s_total; MPI_Reduce(&dofs_s_proc, &dofs_s_total, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (proc_rank == 0) { - std::cout << hidecursor << clrline << "Cycle " << i << ": t = "; + std::cout << cr << clrline << "Cycle " << i << ": t = "; std::cout << state.curr_time << " s" << ", DOFs/s: "; - std::cout << dofs_s_total << cr << std::flush; + std::cout << dofs_s_total << std::flush; } #else /* USE_MPI */ - std::cout << hidecursor << clrline << "Cycle " << i << ": t = "; + std::cout << cr << clrline << "Cycle " << i << ": t = "; std::cout << state.curr_time << " s" << ", DOFs/s: "; - std::cout << dofs_s_proc << cr << std::flush; + std::cout << dofs_s_proc << ", time: " << time << " s" << std::flush; #endif /* USE_MPI */ - tc.tic(); } } - #ifdef USE_MPI + +#ifdef USE_MPI + if (proc_rank == 0) +#endif + std::cout << std::endl; + + mpl.call_finalization_callback(); + +#ifdef USE_MPI if (proc_rank == 0) - #endif /* USE_MPI */ - std::cout << showcursor << std::endl; +#endif + { + std::cout << Bon << greenfg; + std::cout << "Total iteration time = " << total_iteration_time << " s" << std::endl; + std::cout << "Avg iteration time = " << total_iteration_time/num_timesteps << " s" << std::endl; +#ifdef USE_MPI + std::cout << "Avg dofs/s = " << num_timesteps*(mod.num_dofs_world()*6)/total_iteration_time << reset << std::endl; +#else + std::cout << "Avg dofs/s = " << num_timesteps*(mod.num_dofs()*6)/total_iteration_time << reset << std::endl; +#endif + } } /****************************************************************************/ @@ -303,6 +342,11 @@ register_lua_usertypes_bystate(maxwell::parameter_loader& mpl, }; lua["compute_error"] = compute_error_lambda; + auto compare_at_gauss_points_lambda = [&]() { + compare_at_gauss_points(mod, state, mpl); + }; + lua["compare_at_gauss_points"] = compare_at_gauss_points_lambda; + #ifdef ENABLE_EXP_GEOMETRIC_DIODE lua["integrate_E"] = integrate_electric_field; #endif /*ENABLE_EXP_GEOMETRIC_DIODE */ @@ -323,6 +367,9 @@ register_lua_usertypes_bystate(maxwell::parameter_loader& mpl, */ int main(int argc, char *argv[]) { + struct rusage ru_start, ru_end; + + getrusage(RUSAGE_SELF, &ru_start); #ifdef USE_MPI MPI_Init(&argc, &argv); @@ -358,38 +405,48 @@ int main(int argc, char *argv[]) gmsh::initialize(); gmsh::option::setNumber("General.Terminal", 0); gmsh::open( mpl.sim_gmshmodel() ); + bool generate = std::regex_match(mpl.sim_gmshmodel(), std::regex(".*\\.geo$") ); + + if (generate) + { + std::cout << "Generating mesh..." << std::flush; + gmm::generate( DIMENSION(3) ); + std::cout << "done" << std::endl; + } + + auto [scaled, sf] = mpl.mesh_scalefactor(); + if (scaled) + { + std::vector<double> tr = {sf, 0, 0, 0, + 0, sf, 0, 0, + 0, 0, sf, 0 }; + gmm::affineTransform(tr); + } + #ifdef USE_MPI } #endif /* USE_MPI */ model mod( mpl.sim_geomorder(), mpl.sim_approxorder() ); - auto [scaled, sf] = mpl.mesh_scalefactor(); #ifdef USE_MPI if (comm_rank == 0) - { - if (scaled) - mod.generate_mesh(sf); - else - mod.generate_mesh(); - + { if (comm_size > 1) mod.partition_mesh(comm_size); - + std::cout << "Distributing mesh partitions..." << std::flush; mod.populate_from_gmsh(); + std::cout << "done" << std::endl; } else { mod.populate_from_gmsh(); } #else /* USE_MPI */ - if (scaled) - mod.build(sf); - else - mod.build(); + mod.populate_from_gmsh(); #endif /* USE_MPI */ - + if ( not mpl.validate_model_params(mod) ) @@ -438,5 +495,9 @@ int main(int argc, char *argv[]) MPI_Finalize(); #endif + getrusage(RUSAGE_SELF, &ru_end); + + std::cout << "Max RSS: " << (ru_end.ru_maxrss - ru_start.ru_maxrss) << std::endl; + return 0; } diff --git a/tests/test_basics.cpp b/tests/test_basics.cpp index ff3818958e5ae379ad76732ea13bff9b741ec0fe..5fcd85317c8bd07edfdd0dfc922cf73baea685bf 100644 --- a/tests/test_basics.cpp +++ b/tests/test_basics.cpp @@ -39,6 +39,7 @@ int test_basics(int geometric_order, int approximation_order) { make_geometry(0, 0.1); + gmm::generate( DIMENSION(3) ); model mod(geometric_order, approximation_order); mod.build(); @@ -163,6 +164,8 @@ int test_normals(int geometric_order, int approximation_order) { make_geometry(0, 0.1); + gmm::generate( DIMENSION(3) ); + model mod(geometric_order, approximation_order); mod.build(); @@ -247,6 +250,8 @@ int test_normals_2() { make_geometry(0, 0.1); + gmm::generate( DIMENSION(3) ); + model mod(1, 1); mod.build(); diff --git a/tests/test_differentiation.cpp b/tests/test_differentiation.cpp index 00c7675645c839ec1d58cec1284b4a38df200d32..9c7d56b1aec8070ea1b768898c804ade99097a6f 100644 --- a/tests/test_differentiation.cpp +++ b/tests/test_differentiation.cpp @@ -69,6 +69,8 @@ int test_differentiation_convergence(int geometric_order, int approximation_orde { double h = sizes[i]; make_geometry(0,h); + gmm::generate( DIMENSION(3) ); + model mod(geometric_order, approximation_order); mod.build(); diff --git a/tests/test_differentiation_gpu.cpp b/tests/test_differentiation_gpu.cpp index 607d631385eebdb6074b85c9130714113c134a94..5d60e3d2595ad0cc3b51bb969d7524697470642b 100644 --- a/tests/test_differentiation_gpu.cpp +++ b/tests/test_differentiation_gpu.cpp @@ -70,6 +70,8 @@ int test_differentiation_convergence(int geometric_order, int approximation_orde { double h = sizes[i]; make_geometry(0,h); + gmm::generate( DIMENSION(3) ); + model mod(geometric_order, approximation_order); mod.build(); diff --git a/tests/test_lifting.cpp b/tests/test_lifting.cpp index 609e48552174ecd9344f99cd8c970ced46caa5a4..28f79089a670c4ab69cb6140bd3fb352ba290bb1 100644 --- a/tests/test_lifting.cpp +++ b/tests/test_lifting.cpp @@ -81,6 +81,8 @@ int test_lifting(int geometric_order, int approximation_order) { double h = sizes[sz]; make_geometry(0,h); + gmm::generate( DIMENSION(3) ); + model mod(geometric_order, approximation_order); mod.build(); diff --git a/tests/test_lifting_gpu.cpp b/tests/test_lifting_gpu.cpp index cb82338d6e627079d6572308b737d59c55d9b97a..a88892151eaea4b448da36e9ba54b5460b5321f0 100644 --- a/tests/test_lifting_gpu.cpp +++ b/tests/test_lifting_gpu.cpp @@ -82,8 +82,9 @@ int test_lifting(int geometric_order, int approximation_order) { double h = sizes[sz]; make_geometry(0,h); + gmm::generate( DIMENSION(3) ); model mod(geometric_order, approximation_order); - mod.build(); + mod.populate_from_gmsh(); #ifdef WRITE_TEST_OUTPUTS std::stringstream ss; diff --git a/tests/test_mass.cpp b/tests/test_mass.cpp index 72fcbb29b8a19345c12ca6e2412defc657b14653..7d7f90404c889c5c15c3535246a136537f896a83 100644 --- a/tests/test_mass.cpp +++ b/tests/test_mass.cpp @@ -39,6 +39,8 @@ int test_mass_convergence(int geometric_order, int approximation_order) { double h = sizes[i]; make_geometry(0,h); + gmm::generate( DIMENSION(3) ); + model mod(geometric_order, approximation_order); mod.build();