diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b198235669b73e991f17b2107f91a28b22eb7db..e3b1b3be6fa2fd70eaf82d98b7c0625ef0c2c74f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ if (OPT_ENABLE_GPU_SOLVER) if (CUDAToolkit_FOUND) set(CMAKE_CUDA_COMPILER ${CUDAToolkit_NVCC_EXECUTABLE}) enable_language(CUDA) - set(CMAKE_CUDA_STANDARD 14) + set(CMAKE_CUDA_STANDARD 17) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) #set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -lineinfo --resource-usage -Xptxas -dlcm=ca") set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -lineinfo --resource-usage -prec-div=true") diff --git a/include/entity.h b/include/entity.h index 11296407ebe781bf037af16ce785dfa4d3ef78f9..70df6223d9fc821190368363cd348e6508f37c76 100644 --- a/include/entity.h +++ b/include/entity.h @@ -66,6 +66,8 @@ public: void project(const scalar_function&, vecxd&) const; void project(const vector_function&, vecxd&, vecxd&, vecxd&) const; + matxd project_on_face(size_t iF, const vector_function&) const; + size_t num_cells(void) const; size_t num_cell_orientations(void) const; std::vector<size_t> num_cells_per_orientation(void) const; diff --git a/include/maxwell_interface.h b/include/maxwell_interface.h index 0d2910907c8d9fa305f379f1a43b936c2ec6a47e..0c6a57a66078443657ab31645185f66a267cf1e1 100644 --- a/include/maxwell_interface.h +++ b/include/maxwell_interface.h @@ -54,6 +54,8 @@ public: bool initial_Hfield_defined(void) const; vec3d initial_Hfield(const point_3d&) const; + vec3d eval_plane_wave_E(int, const point_3d&, double) const; + boundary_condition boundary_type(int tag) const; }; #endif /* HIDE_THIS_FROM_NVCC */ @@ -208,6 +210,8 @@ struct solver_state field k3; field k4; field tmp; + + field bndsrcs; }; #ifdef ENABLE_GPU_SOLVER @@ -256,6 +260,7 @@ void timestep(solver_state_gpu&); void init_boundary_conditions(const model&, const parameter_loader&, vecxd&); void init_lax_milgram(const model&, const parameter_loader&, vecxd&, vecxd&, vecxd&, vecxd&); +void eval_boundary_sources(const model&, const parameter_loader&, solver_state&, field&); #endif /* HIDE_THIS_FROM_NVCC */ template<typename Function> diff --git a/src/entity.cpp b/src/entity.cpp index 73f60ee0dd8a05f6b3cce9c29a5194bd8b59a47b..17c42013e74235d65bba756fe8b56ea2c8e84b48 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -165,6 +165,45 @@ entity::project(const vector_function& function, vecxd& pfx, vecxd& pfy, vecxd& } } +matxd +entity::project_on_face(size_t iF, const vector_function& function) const +{ + assert(iF < physical_faces.size()); + + const auto& pf = physical_faces[iF]; + assert( pf.orientation() < reference_faces.size() ); + const auto& rf = reference_faces[pf.orientation()]; + const auto pqps = pf.integration_points(); + const auto dets = pf.determinants(); + + assert(pqps.size() == dets.size()); + + size_t num_bf = rf.num_basis_functions(); + + matxd mass = matxd::Zero(num_bf, num_bf); + vecxd rhs_x = vecxd::Zero(num_bf); + vecxd rhs_y = vecxd::Zero(num_bf); + vecxd rhs_z = vecxd::Zero(num_bf); + for (size_t iQp = 0; iQp < pqps.size(); iQp++) + { + const auto& pqp = pqps[iQp]; + const vecxd phi = rf.basis_functions(iQp); + mass += pqp.weight() * phi * phi.transpose(); + vec3d fval = function(pqp.point()); + rhs_x += pqp.weight() * fval(0) * phi; + rhs_y += pqp.weight() * fval(1) * phi; + rhs_z += pqp.weight() * fval(2) * phi; + } + + matxd ret(num_bf, 3); + + Eigen::LDLT<matxd> mass_ldlt(mass); + ret.col(0) = mass_ldlt.solve(rhs_x); + ret.col(1) = mass_ldlt.solve(rhs_y); + ret.col(2) = mass_ldlt.solve(rhs_z); + return ret; +} + const reference_element& entity::cell_refelem(size_t iO) const { diff --git a/src/maxwell_common.cpp b/src/maxwell_common.cpp index d1fd40bd05be8d3ea4a46bae3a236b91b4fc68b4..7a4ff6924c83ff6a8bd8c865c83c45fa4770556d 100644 --- a/src/maxwell_common.cpp +++ b/src/maxwell_common.cpp @@ -138,8 +138,8 @@ init_lax_milgram(const model& mod, const parameter_loader& mpl, parameter_loader::parameter_loader() { - lua["const"]["eps-1"] = 8.8541878128e-12; - lua["const"]["mu-1"] = 4e-7*M_PI; + lua["const"]["eps0"] = 8.8541878128e-12; + lua["const"]["mu0"] = 4e-7*M_PI; } bool @@ -297,4 +297,13 @@ parameter_loader::boundary_type(int tag) const return boundary_condition::UNSPECIFIED; } +vec3d +parameter_loader::eval_plane_wave_E(int tag, const point_3d& pt, double t) const +{ + vec3d ret; + sol::tie(ret(0), ret(1), ret(2)) = + lua["bndconds"][tag]["source"](tag, pt.x(), pt.y(), pt.z(), t); + return ret; +} + } // namespace maxwell \ No newline at end of file diff --git a/src/maxwell_cpu.cpp b/src/maxwell_cpu.cpp index d47639f050be418546a999922e0de444f550799b..3ce0b419e730f915811fc697888f3cba91ccf195 100644 --- a/src/maxwell_cpu.cpp +++ b/src/maxwell_cpu.cpp @@ -48,6 +48,74 @@ init_matparams(const model& mod, solver_state& state, init_boundary_conditions(mod, mpl, state.matparams.bc_coeffs); } +void +eval_boundary_sources(const model& mod, const parameter_loader& mpl, + solver_state& state, field& srcfield) +{ + auto& bds = mod.boundary_descriptors(); + assert( srcfield.num_dofs == mod.num_fluxes() ); + + size_t face_num_base = 0; + for (auto& e : mod) + { + for (size_t iF = 0; iF < e.num_faces(); iF++) + { + auto& pf = e.face(iF); + auto bar = pf.barycenter(); + auto eps = mpl.epsilon(e.gmsh_tag(), bar); + auto mu = mpl.mu(e.gmsh_tag(), bar); + auto Z = std::sqrt(mu/eps); + + vec3d n = state.eds[e.number()].normals.row(iF); + + auto gfnum = face_num_base + iF; + auto bd = bds[gfnum]; + if (bd.type == face_type::NONE or bd.type == face_type::INTERFACE) + continue; + + switch ( mpl.boundary_type(bd.gmsh_entity) ) + { + case boundary_condition::E_FIELD: + break; + + case boundary_condition::PLANE_WAVE_E: { + auto fE = [&](const point_3d& pt) -> vec3d { + return mpl.eval_plane_wave_E(bd.gmsh_entity, pt, state.curr_time); + }; + auto fH = [&](const point_3d& pt) -> vec3d { + vec3d E = mpl.eval_plane_wave_E(bd.gmsh_entity, pt, state.curr_time); + return n.cross(E)/Z; + }; + matxd prjE = e.project_on_face(iF, fE); + auto num_bf = prjE.rows(); + srcfield.Ex.segment(gfnum*num_bf, num_bf) = prjE.col(0); + srcfield.Ey.segment(gfnum*num_bf, num_bf) = prjE.col(1); + srcfield.Ez.segment(gfnum*num_bf, num_bf) = prjE.col(2); + + matxd prjH = e.project_on_face(iF, fH); + srcfield.Hx.segment(gfnum*num_bf, num_bf) = prjH.col(0); + srcfield.Hy.segment(gfnum*num_bf, num_bf) = prjH.col(1); + srcfield.Hz.segment(gfnum*num_bf, num_bf) = prjH.col(2); + } break; + + case boundary_condition::PLANE_WAVE_H: + break; + + case boundary_condition::SURFACE_CURRENT: + break; + + case boundary_condition::H_FIELD: + break; + + default: + break; + } + } + + face_num_base += e.num_faces(); + } +} + void init_from_model(const model& mod, solver_state& state) { @@ -56,7 +124,6 @@ void init_from_model(const model& mod, solver_state& state) state.dx.resize( mod.num_dofs() ); state.dy.resize( mod.num_dofs() ); state.dz.resize( mod.num_dofs() ); - state.k1.resize( mod.num_dofs() ); state.k2.resize( mod.num_dofs() ); @@ -67,7 +134,7 @@ void init_from_model(const model& mod, solver_state& state) state.jumps.resize( mod.num_fluxes() ); state.fluxes.resize( mod.num_fluxes() ); - state.matparams.bc_coeffs = 2*vecxd::Ones( mod.num_fluxes() ); + state.bndsrcs.resize( mod.num_fluxes() ); for (auto& e : mod) { @@ -158,12 +225,12 @@ compute_fluxes_planar(solver_state& state) auto gofs = ed.flux_base + lofs; /* Sources are imposed on jumps */ - auto jEx = state.jumps.Ex[gofs];// - boundary_sources.Ex[g_flofs]; - auto jEy = state.jumps.Ey[gofs];// - boundary_sources.Ey[g_flofs]; - auto jEz = state.jumps.Ez[gofs];// - boundary_sources.Ez[g_flofs]; - auto jHx = state.jumps.Hx[gofs];// + boundary_sources.Hx[g_flofs]; - auto jHy = state.jumps.Hy[gofs];// + boundary_sources.Hy[g_flofs]; - auto jHz = state.jumps.Hz[gofs];// + boundary_sources.Hz[g_flofs]; + auto jEx = state.jumps.Ex[gofs] - state.bndsrcs.Ex[gofs]; + auto jEy = state.jumps.Ey[gofs] - state.bndsrcs.Ey[gofs]; + auto jEz = state.jumps.Ez[gofs] - state.bndsrcs.Ez[gofs]; + auto jHx = state.jumps.Hx[gofs] + state.bndsrcs.Hx[gofs]; + auto jHy = state.jumps.Hy[gofs] + state.bndsrcs.Hy[gofs]; + auto jHz = state.jumps.Hz[gofs] + state.bndsrcs.Hz[gofs]; auto ndotE = nx*jEx + ny*jEy + nz*jEz; auto ndotH = nx*jHx + ny*jHy + nz*jHz; @@ -246,7 +313,7 @@ compute_rk4_weighted_sum(solver_state& state, const field& in, double dt, field& void apply_operator(solver_state& state, const field& curr, field& next) -{ +{ compute_curls(state, curr, next); compute_fluxes(state, curr, next); } diff --git a/src/maxwell_solver.cpp b/src/maxwell_solver.cpp index b85bd2478832ec965d67d8f80a9ffeb6edac2e6a..68e43718658239dbdba7bfd003cd84810f765b27 100644 --- a/src/maxwell_solver.cpp +++ b/src/maxwell_solver.cpp @@ -64,6 +64,7 @@ void test_it(const model& mod, State& state, const maxwell::parameter_loader& mp for(size_t i = 0; i < num_timesteps; i++) { + maxwell::eval_boundary_sources(mod, mpl, state, state.bndsrcs); timestep(state); std::stringstream ss; ss << "maxwell_" << i << ".silo"; @@ -111,8 +112,8 @@ int main(int argc, const char *argv[]) #ifdef ENABLE_GPU_SOLVER if ( mpl.sim_usegpu() ) { - maxwell::solver_state_gpu state_g; - test_it(mod, state_g, mpl); + //maxwell::solver_state_gpu state_g; + //test_it(mod, state_g, mpl); } else {