diff --git a/doc/lua_api.md b/doc/lua_api.md index d74839f0d9b10cdf2905ff889d9b0c4ee0cb0a05..67c03cca57ed28f74775bc29e649c3cf5fbcab86 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -27,6 +27,9 @@ This document describes the API available on the version v0.1 of the solver. - `postpro.silo_output_rate` (integer): - `postpro.cycle_print_rate` (integer): +### Mesh variables +- `mesh.scalefactor` (real): apply a scaling factor to the mesh. + ### Callable functions - `enable_boundary_sources()`: takes a boolean parameter that specifies if boundary sources should be enabled or not - `enable_interface_sources()`: takes a boolean parameter that specifies if the sources applied on internal interfaces should be enabled or not diff --git a/include/gmsh_io.h b/include/gmsh_io.h index 7585f304322d8c578dc530c39c87aa35b9b8d060..0824294ad5f41df66b74ac9dd2fd91aacb61348b 100644 --- a/include/gmsh_io.h +++ b/include/gmsh_io.h @@ -66,10 +66,15 @@ class model std::vector<boundary_descriptor> bnd_descriptors; element_connectivity<element_key> conn; + using entofs_pair = std::pair<size_t, size_t>; + std::map<size_t, entofs_pair> etag_to_entity_offset; + void map_boundaries(void); void import_gmsh_entities(void); void update_connectivity(const entity&, size_t); + void build_priv(void); + public: model(); model(int, int); @@ -77,8 +82,8 @@ public: model(const char *, int, int); ~model(); - void remesh(void); - void remesh(int); + void build(void); + void build(double); const element_connectivity<element_key>& connectivity() const { @@ -109,5 +114,5 @@ public: entity& entity_at(size_t); const entity& entity_at(size_t) const; + entofs_pair lookup_tag(size_t tag) const; }; - diff --git a/src/gmsh_io.cpp b/src/gmsh_io.cpp index 5e2e23cb5ef29783f0204c7ffdbdeb78026d3170..bdddb6e911c5067c8cb38389327dacfd209962a6 100644 --- a/src/gmsh_io.cpp +++ b/src/gmsh_io.cpp @@ -35,24 +35,19 @@ basis_grad_name(int order) model::model() : geometric_order(1), approximation_order(1) -{ - remesh(geometric_order); -} +{} model::model(int pgo, int pao) : geometric_order(pgo), approximation_order(pao) { assert(geometric_order > 0); assert(approximation_order > 0); - - remesh(geometric_order); } model::model(const char *filename) : geometric_order(1), approximation_order(1) { gmsh::open( std::string(filename) ); - remesh(geometric_order); } model::model(const char *filename, int pgo, int pao) @@ -62,7 +57,6 @@ model::model(const char *filename, int pgo, int pao) assert(approximation_order > 0); gmsh::open( std::string(filename) ); - remesh(geometric_order); } model::~model() @@ -71,9 +65,8 @@ model::~model() } void -model::remesh() +model::build_priv() { - gmm::generate( DIMENSION(3) ); gmm::setOrder( geometric_order ); gvp_t gmsh_entities; @@ -103,10 +96,22 @@ model::remesh() } void -model::remesh(int pgo) +model::build() { - geometric_order = pgo; - remesh(); + gmm::generate( DIMENSION(3) ); + build_priv(); +} + +void +model::build(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); + build_priv(); } std::vector<entity>::const_iterator @@ -231,6 +236,17 @@ model::import_gmsh_entities(void) .gorder = geometric_order, .aorder = approximation_order}); e.sort_by_orientation(); + + for (size_t i = 0; i < e.num_cells(); i++) + { + const auto& pe = e.cell(i); + auto eitor = etag_to_entity_offset.find( pe.element_tag() ); + if ( eitor != etag_to_entity_offset.end() ) + throw std::logic_error("Duplicate tag"); + + etag_to_entity_offset[ pe.element_tag() ] = std::make_pair(entity_index, i); + } + e.base(dof_base, flux_base, index_base); e.number(entity_index); dof_base += e.num_dofs(); @@ -313,3 +329,9 @@ model::map_boundaries(void) std::cout << normal << " " << interface << " " << boundary << std::endl; */ } + +model::entofs_pair +model::lookup_tag(size_t tag) const +{ + return etag_to_entity_offset.at(tag); +} diff --git a/src/maxwell_solver.cpp b/src/maxwell_solver.cpp index c40793b34c72d20372709c9c8cc2e1699bb8e135..aee2197fbfc8f0e985ac98199b8c36f5fb58ae57 100644 --- a/src/maxwell_solver.cpp +++ b/src/maxwell_solver.cpp @@ -66,6 +66,54 @@ void initialize_solver(const model& mod, State& state, const maxwell::parameter_ init_matparams(mod, state, mpl); } +class line_integrator +{ + std::vector<size_t> element_tags; + std::vector<point_3d> sampling_points_phys; + std::vector<point_3d> sampling_points_ref; + point_3d increment; + +public: + line_integrator(const point_3d& start, + const point_3d& end, size_t samples) + { + increment = (end - start)/samples; + for (size_t i = 0; i < samples; i++) + { + point_3d sp = start + increment*(i+0.5); + sampling_points_phys.push_back(sp); + + size_t etag; + int etype; + std::vector<size_t> ntags; + double u, v, w; + gmsh::model::mesh::getElementByCoordinates(sp.x(), sp.y(), sp.z(), + etag, etype, ntags, u, v, w, 3, true); + + element_tags.push_back(etag); + sampling_points_ref.push_back( point_3d(u,v,w) ); + } + } + + double integrate(const model& mod, const vecxd& dofs) + { + double integral_val = 0.0; + for (size_t i = 0; i < sampling_points_phys.size(); i++) + { + auto [entnum, ofs] = mod.lookup_tag(element_tags.at(i)); + auto& e = mod.entity_at(entnum); + auto& pe = e.cell(ofs); + auto& re = e.cell_refelem(pe); + auto dof_ofs = e.cell_global_dof_offset(ofs); + auto dof_num = re.num_basis_functions(); + vecxd phi = re.basis_functions( sampling_points_ref[i] ); + vecxd sol = dofs.segment(dof_ofs, dof_num); + integral_val += sol.dot(phi) * increment.x(); + } + + return integral_val; + } +}; template<typename State> void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl) @@ -87,6 +135,10 @@ void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl) std::cout << "s each." << std::endl; std::cout << "Time integrator: " << mpl.sim_timeIntegratorName() << std::endl; + point_3d start(-46e-9, 0.0, 38e-9); + point_3d end(46e-9, 0.0, 38e-9); + line_integrator lint(start, end, 50); + timecounter tc; tc.tic(); prepare_sources(mod, state, mpl); @@ -108,6 +160,7 @@ void test_it(const model& mod, State& state, maxwell::parameter_loader& mpl) std::cout << "Cycle " << i << ": t = " << state.curr_time << " s"; std::cout << ", DOFs/s: " << (mod.num_dofs()*6*cycle_print_rate)/(time) << std::endl; tc.tic(); + std::cout << "Voltage = " << lint.integrate(mod, state.emf_curr.Ex) << std::endl; } } } @@ -141,26 +194,19 @@ int main(int argc, const char *argv[]) gmsh::open( mpl.sim_gmshmodel() ); model mod( mpl.sim_geomorder(), mpl.sim_approxorder() ); + + auto [scaled, sf] = mpl.mesh_scalefactor(); + if (scaled) + mod.build(sf); + else + mod.build(); + if ( not mpl.validate_model_params(mod) ) { std::cout << "Configuration problem, exiting" << std::endl; return 1; } - /* - //must be after gmm::generate() and before gmm::setOrder() :( - - auto [scaled, sf] = mpl.mesh_scalefactor(); - if (scaled) - { - std::vector<double> tr = {sf, 0, 0, 0, - 0, sf, 0, 0, - 0, 0, sf, 0 }; - - gmsh::model::mesh::affineTransform(tr); - } - */ - if ( mpl.sim_usegpu() ) { #ifdef ENABLE_GPU_SOLVER diff --git a/tests/profile_differentiation_gpu.cpp b/tests/profile_differentiation_gpu.cpp index 132650196d09965e0bb3d47a7f59a8528a1122a0..501a8af1894c3afa284f345c2fedf0ca6b453460 100644 --- a/tests/profile_differentiation_gpu.cpp +++ b/tests/profile_differentiation_gpu.cpp @@ -48,6 +48,7 @@ int profile_differentiation(int geometric_order, int approximation_order) double h = 0.04; make_geometry(0,h); model mod(geometric_order, approximation_order); + mod.build(); auto& e0 = mod.entity_at(0); e0.sort_by_orientation(); diff --git a/tests/test_basics.cpp b/tests/test_basics.cpp index 5afd04561f9e86f8c0c60c1f4c0a25b151e5c156..3b3a0e9b58d41585abb600ccf88c01870a44f584 100644 --- a/tests/test_basics.cpp +++ b/tests/test_basics.cpp @@ -41,6 +41,7 @@ test_basics(int geometric_order, int approximation_order) make_geometry(0, 0.1); model mod(geometric_order, approximation_order); + mod.build(); auto idx = geometric_order - 1; @@ -163,6 +164,7 @@ test_normals(int geometric_order, int approximation_order) { make_geometry(0, 0.1); model mod(geometric_order, approximation_order); + mod.build(); gmsh::vectorpair pgs; gm::getPhysicalGroups(pgs); @@ -246,6 +248,7 @@ test_normals_2() { make_geometry(0, 0.1); model mod(1, 1); + mod.build(); vec3d totflux = vec3d::Zero(); double tf = 0.0; diff --git a/tests/test_differentiation.cpp b/tests/test_differentiation.cpp index 4bb0b36f78252f42c289a7db728e68704c621434..884d8f56f95c364f34e08b780a0abf3302a85c86 100644 --- a/tests/test_differentiation.cpp +++ b/tests/test_differentiation.cpp @@ -70,6 +70,7 @@ int test_differentiation_convergence(int geometric_order, int approximation_orde double h = sizes[i]; make_geometry(0,h); model mod(geometric_order, approximation_order); + mod.build(); std::stringstream ss; ss << "diff_go_" << geometric_order << "_ao_" << approximation_order; diff --git a/tests/test_differentiation_gpu.cpp b/tests/test_differentiation_gpu.cpp index 3f00c3d802f2cd5f64ab2d0f1f755abb5f83aa1f..c9afbd298d2a3cf870712fb8bfb71544efaf74a9 100644 --- a/tests/test_differentiation_gpu.cpp +++ b/tests/test_differentiation_gpu.cpp @@ -72,6 +72,7 @@ int test_differentiation_convergence(int geometric_order, int approximation_orde double h = sizes[i]; make_geometry(0,h); model mod(geometric_order, approximation_order); + mod.build(); #ifdef WRITE_TEST_OUTPUTS std::stringstream ss; diff --git a/tests/test_lifting.cpp b/tests/test_lifting.cpp index 3cb36f25d58a44b14146f207e32e1171d56de8b9..a543f9080da4d427ec9c61a3f47678f526bb281a 100644 --- a/tests/test_lifting.cpp +++ b/tests/test_lifting.cpp @@ -82,6 +82,7 @@ int test_lifting(int geometric_order, int approximation_order) double h = sizes[sz]; make_geometry(0,h); model mod(geometric_order, approximation_order); + mod.build(); #ifdef WRITE_TEST_OUTPUTS std::stringstream ss; diff --git a/tests/test_lifting_gpu.cpp b/tests/test_lifting_gpu.cpp index cf8fe0ba9559612ae996fdec132813a8e67ac3ff..cd289c8390a77cf7cc933f8672bde94d7861e48e 100644 --- a/tests/test_lifting_gpu.cpp +++ b/tests/test_lifting_gpu.cpp @@ -83,6 +83,7 @@ int test_lifting(int geometric_order, int approximation_order) double h = sizes[sz]; make_geometry(0,h); model mod(geometric_order, approximation_order); + mod.build(); #ifdef WRITE_TEST_OUTPUTS std::stringstream ss; diff --git a/tests/test_mass.cpp b/tests/test_mass.cpp index fcd49b79ec32dc24909e0f062d9ad1dc71721104..9e93b8f55ba5057e1bb5458d990d2ccaeadf7f54 100644 --- a/tests/test_mass.cpp +++ b/tests/test_mass.cpp @@ -40,6 +40,7 @@ int test_mass_convergence(int geometric_order, int approximation_order) double h = sizes[i]; make_geometry(0,h); model mod(geometric_order, approximation_order); + mod.build(); auto& e0 = mod.entity_at(0); e0.sort_by_orientation();