From d167dfca59ed3ef004ced79fe198c57ea50b441e Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Thu, 2 May 2019 19:09:06 +0200 Subject: [PATCH 01/10] rewritten mesh creator to support more general creation --- examples/cahn_hilliard.cc | 2 + src/amdis/CMakeLists.txt | 2 +- src/amdis/Mesh.hpp | 183 --------------------------------- src/amdis/MeshCreator.hpp | 185 ++++++++++++++++++++++++++++++++++ src/amdis/ProblemStat.hpp | 2 +- src/amdis/common/Concepts.hpp | 14 +++ 6 files changed, 203 insertions(+), 185 deletions(-) delete mode 100644 src/amdis/Mesh.hpp create mode 100644 src/amdis/MeshCreator.hpp diff --git a/examples/cahn_hilliard.cc b/examples/cahn_hilliard.cc index a26e9ccf..fe37bdd7 100644 --- a/examples/cahn_hilliard.cc +++ b/examples/cahn_hilliard.cc @@ -6,6 +6,8 @@ #include #include +#include + using namespace AMDiS; using Grid = Dune::AlbertaGrid; diff --git a/src/amdis/CMakeLists.txt b/src/amdis/CMakeLists.txt index ceaf0b69..1237bbc9 100644 --- a/src/amdis/CMakeLists.txt +++ b/src/amdis/CMakeLists.txt @@ -50,7 +50,7 @@ install(FILES LocalOperators.hpp Marker.hpp Marker.inc.hpp - Mesh.hpp + MeshCreator.hpp Operations.hpp OperatorList.hpp Output.hpp diff --git a/src/amdis/Mesh.hpp b/src/amdis/Mesh.hpp deleted file mode 100644 index d4524bf3..00000000 --- a/src/amdis/Mesh.hpp +++ /dev/null @@ -1,183 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -namespace AMDiS -{ - namespace tag - { - struct albertagrid {}; - struct uggrid {}; - struct yaspgrid {}; - struct unknowngrid {}; - - } // end namespace tag - - namespace Impl - { - template - struct MeshTag - { - using type = tag::unknowngrid; - }; - - // specialization for some grid types from DUNE -#if HAVE_ALBERTA - template - struct MeshTag> - { - using type = tag::albertagrid; - }; -#endif - -#if HAVE_UG - template - struct MeshTag> - { - using type = tag::uggrid; - }; -#endif - - template - struct MeshTag> - { - using type = tag::yaspgrid; - }; - - } // end namespace Impl - - template - using MeshTag_t = typename Impl::MeshTag::type; - - - /// A creator class for meshes. Each mesh needs different way of initialization - template - struct MeshCreator - { - static std::unique_ptr create(std::string const& meshName) - { - error_exit("Creator not yet implemented for this mesh type."); - return {}; - } - }; - -#if HAVE_ALBERTA - template - struct MeshCreator> - { - using Grid = Dune::AlbertaGrid; - - static std::unique_ptr create(std::string const& meshName) - { - std::string macro_filename = ""; - Parameters::get(meshName + "->macro file name", macro_filename); - - // TODO: if filename_extension is ".2d" or ".3d" read it directly from file - // otherwise use a factory method - - return std::make_unique(macro_filename); - } - }; -#endif - - -#if HAVE_UG - template - struct MeshCreator> - { - using Grid = Dune::UGGrid; - - static std::unique_ptr create(std::string const& meshName) - { - - std::string filename = ""; - Parameters::get(meshName + "->macro file name", filename); - - test_exit(!filename.empty(), - "Construction of UGGrid without filename not yet implemented!"); - - filesystem::path fn(filename); - auto ext = fn.extension(); - - if (ext == ".msh") { - Dune::GmshReader reader; - return std::unique_ptr{reader.read(filename)}; - } -// #if HAVE_ALBERTA -// else if (ext == ".1d" || ext == ".2d" || ext == ".3d") { -// Dune::Hybrid::ifElse(bool_t{}, -// [&](auto id) { -// Dune::GridFactory factory; -// Dune::AlbertaReader reader; -// id(reader).readGrid(filename, id(factory)); -// return std::unique_ptr{factory.createGrid()}; -// }); - -// warning("WORLDDIM must be given in Alberta flags."); -// } -// #endif - - error_exit("No way to construct UG-Grid found"); - return {}; - } - }; -#endif - - template - struct MeshCreator>> - { - using Grid = Dune::YaspGrid>; - - static std::unique_ptr create(std::string const& meshName) - { - Dune::FieldVector L; L = 1.0; // extension of the domain - Parameters::get(meshName + "->dimension", L); - - auto s = Dune::filledArray(1); // number of cells on coarse mesh in each direction - Parameters::get(meshName + "->num cells", s); - - // TODO: add more parameters for yasp-grid (see constructor) - - return std::make_unique(L, s); - } - }; - - - template - struct MeshCreator>> - { - using Grid = Dune::YaspGrid>; - - static std::unique_ptr create(std::string const& meshName) - { - Dune::FieldVector lowerleft; lowerleft = 0.0; // Lower left corner of the domain - Dune::FieldVector upperright; upperright = 1.0; // Upper right corner of the domain - Parameters::get(meshName + "->min corner", lowerleft); - Parameters::get(meshName + "->max corner", upperright); - - auto s = Dune::filledArray(1); // number of cells on coarse mesh in each direction - Parameters::get(meshName + "->num cells", s); - - // TODO: add more parameters for yasp-grid (see constructor) - - return std::make_unique(lowerleft, upperright, s); - } - }; - -} // end namespace AMDiS diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp new file mode 100644 index 00000000..8fae2ac7 --- /dev/null +++ b/src/amdis/MeshCreator.hpp @@ -0,0 +1,185 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +#if HAVE_ALBERTA +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace AMDiS +{ + /// A creator class for meshes. + template + struct MeshCreator + { + enum { dimension = Grid::dimension }; + enum { dimworld = Grid::dimensionworld }; + + using ctype = typename Grid::ctype; + + /// Create a new grid by inspecting the intifile parameters `[meshName]->...` + /** + * Reads first the parameter `[meshName]->structured` and if set, creates: + * - cube: a structured cube grid + * - simplex: a structured simplex grid + * + * Otherwise an unstructured grid is read from file `[meshName]->macro file name`. + **/ + static std::unique_ptr create(std::string const& meshName) + { + auto structured = Parameters::get(meshName + "->structured"); + if (structured && structured.value() == "cube") { + return create_cube_grid(meshName); + } else if (structured && structured.value() == "simplex") { + return create_simplex_grid(meshName); + } else { + return create_unstructured_grid(meshName); + } + } + + /// Create a structured cube grid + static std::unique_ptr create_cube_grid(std::string const& meshName) + { + return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) + { + return Dune::StructuredGridFactory::createCubeGrid(lower, upper, numCells); + }); + } + + /// Create a structured simplex grid + static std::unique_ptr create_simplex_grid(std::string const& meshName) + { + return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) + { + return Dune::StructuredGridFactory::createSimplexGrid(lower, upper, numCells); + }); + } + + private: + // use the structured grid factory to create the grid + template + static std::unique_ptr create_structured_grid(std::string const& meshName, Factory factory) + { + Dune::FieldVector lower(0); // Lower left corner of the domain + Dune::FieldVector upper(1); // Upper right corner of the domain + auto numCells = Dune::filledArray(1); + + auto lower_opt = Parameters::get(meshName + "->min corner"); + auto upper_opt = Parameters::get(meshName + "->max corner"); + auto dim_opt = Parameters::get(meshName + "->dimension"); + if (lower_opt && upper_opt) { + lower = *lower_opt; + upper = *upper_opt; + } else if (dim_opt) { + upper = *dim_opt; + } + + Parameters::get(meshName + "->num cells", numCells); + return factory(lower, upper, numCells); + } + + // read a filename from `macro file name` and determine from the extension the fileformat + static std::unique_ptr create_unstructured_grid(std::string const& meshName) + { + std::string filename = ""; + Parameters::get(meshName + "->macro file name", filename); + + test_exit(!filename.empty(), "Expect a `macro file name` or the flags `structured->[cube|simplex]` to be set!"); + + filesystem::path fn(filename); + auto ext = fn.extension(); + + if (ext == ".msh") { + Dune::GmshReader reader; + return std::unique_ptr{reader.read(filename)}; + } + else if (ext == ".1d" || ext == ".2d" || ext == ".3d" || ext == ".amc") { + return read_alberta_file(filename, Dune::PriorityTag<42>{}); + } + else if (ext == ".dgf") { + return read_dgf_file(filename, Dune::PriorityTag<42>{}); + } + else { + error_exit("Can not read grid file. Unknown file extension."); + return {}; + } + } + + // read from Alberta file + +#if HAVE_ALBERTA + template + using IsAlbertaGrid = decltype(std::declval().alberta2dune(0,0)); + + // construct the albertagrid directly from a filename + template ::value)> + static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) + { + return std::make_unique(filename); + } + + // use a gridfactory and the generic AlbertaReader + template + static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) + { + Dune::GridFactory factory; + Dune::AlbertaReader reader; + reader.readGrid(filename, factory); + return std::unique_ptr{factory.createGrid()}; + } + + // error if WORLDDIM not the same as Grid::dimensionworld + template + static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<1>) + { + error_exit("Alberta (and AlbertaReader) require WORLDDIM == Grid::dimensionworld. Change the cmake parameters!"); + return {}; + } +#else + // fallback if no Alberta is available + template + static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<0>) + { + error_exit("Alberta (and AlbertaReader) not available. Set AlbertaFlags to your executable in cmake!"); + return {}; + } +#endif + + template >)> + static std::unique_ptr read_dgf_file(std::string const& filename, Dune::PriorityTag<1>) + { + Dune::GridPtr reader(filename); + return std::unique_ptr{reader.release()}; + } + + template + static std::unique_ptr read_dgf_file(std::string const& filename, Dune::PriorityTag<0>) + { + error_exit("DGFParser for GridType not defined. Maybe include the corresponding grid header file."); + return {}; + } + + }; + + +} // end namespace AMDiS diff --git a/src/amdis/ProblemStat.hpp b/src/amdis/ProblemStat.hpp index 005cf68e..faf6a342 100644 --- a/src/amdis/ProblemStat.hpp +++ b/src/amdis/ProblemStat.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/amdis/common/Concepts.hpp b/src/amdis/common/Concepts.hpp index fc4aba7a..3a43c784 100644 --- a/src/amdis/common/Concepts.hpp +++ b/src/amdis/common/Concepts.hpp @@ -53,6 +53,17 @@ namespace AMDiS struct IsReferenceWrapper> : std::true_type {}; + + template + struct IsDefined + : std::false_type {}; + + template + struct IsDefined::value && + !std::is_pointer::value && + (sizeof(T) > 0)> > + : std::true_type {}; + } // end namespace Traits namespace Concepts @@ -117,6 +128,9 @@ namespace AMDiS template constexpr bool MultiIndex = models; + template + constexpr bool Defined = Traits::IsDefined::value; + /** @} **/ } // end namespace Concepts -- GitLab From 301fbd7bf3f32dceaa32dc461277fbf11b8379b5 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Thu, 2 May 2019 19:35:40 +0200 Subject: [PATCH 02/10] add a mode to decide on gridtype how to create the grid --- src/amdis/MeshCreator.hpp | 66 ++++++++++++++++++++++++++++++++------- test/MarkerTest.cpp | 2 ++ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 8fae2ac7..5537fba2 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -42,13 +42,24 @@ namespace AMDiS **/ static std::unique_ptr create(std::string const& meshName) { + auto filename = Parameters::get(meshName + "->macro file name"); auto structured = Parameters::get(meshName + "->structured"); - if (structured && structured.value() == "cube") { - return create_cube_grid(meshName); - } else if (structured && structured.value() == "simplex") { - return create_simplex_grid(meshName); + if (filename) { + // read a macro file + return create_unstructured_grid(filename.value()); + } else if (structured) { + // create structured grids + if (structured.value() == "cube") { + return create_cube_grid(meshName); + } else if (structured && structured.value() == "simplex") { + return create_simplex_grid(meshName); + } else { + error_exit("Unknown structured grid type. Must be either `cube` or `simplex` in parameter [meshName]->structured."); + return {}; + } } else { - return create_unstructured_grid(meshName); + // decide by inspecting the grid type how to create the grid + return create_by_gridtype(meshName, Dune::PriorityTag<42>{}); } } @@ -94,13 +105,8 @@ namespace AMDiS } // read a filename from `macro file name` and determine from the extension the fileformat - static std::unique_ptr create_unstructured_grid(std::string const& meshName) + static std::unique_ptr create_unstructured_grid(std::string const& filename) { - std::string filename = ""; - Parameters::get(meshName + "->macro file name", filename); - - test_exit(!filename.empty(), "Expect a `macro file name` or the flags `structured->[cube|simplex]` to be set!"); - filesystem::path fn(filename); auto ext = fn.extension(); @@ -179,6 +185,44 @@ namespace AMDiS return {}; } +#if HAVE_ALBERTA + // albertagrid + template ::value)> + static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<3>) + { + return create_simplex_grid(meshName); + } +#endif + + // yasp grid + template + static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<2>) + { + return create_cube_grid(meshName); + } + + // spgrid + template + static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<1>) + { + return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) + { + std::array cells(numCells); + typename GridType::MultiIndex multiIndex(cells); + return std::make_unique(lower, upper, multiIndex); + }); + } + + template + static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<0>) + { + error_exit("Don't know how to create the grid."); + return {}; + } }; diff --git a/test/MarkerTest.cpp b/test/MarkerTest.cpp index a120ce9a..6ae27b0d 100644 --- a/test/MarkerTest.cpp +++ b/test/MarkerTest.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include "Tests.hpp" using namespace AMDiS; -- GitLab From af477ce466673c01b6817359b0ab0ae375d2a8fd Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Fri, 3 May 2019 13:21:10 +0200 Subject: [PATCH 03/10] removed parameter [meshName]->dimension in favour of --- examples/init/heat.dat.2d | 3 +-- examples/init/stokes.dat.2d | 2 +- src/amdis/MeshCreator.hpp | 45 +++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/init/heat.dat.2d b/examples/init/heat.dat.2d index 31836835..e938b21c 100644 --- a/examples/init/heat.dat.2d +++ b/examples/init/heat.dat.2d @@ -1,9 +1,8 @@ heatMesh->macro file name: ./macro/macro.stand.2d heatMesh->global refinements: 4 heatMesh->min corner: 0 0 -heatMesh->max corner: 1 1 +heatMesh->max corner: 2 2 heatMesh->num cells: 2 2 -heatMesh->dimension: 2 2 heat->mesh: heatMesh heat->names: u diff --git a/examples/init/stokes.dat.2d b/examples/init/stokes.dat.2d index 54542825..ded25d60 100644 --- a/examples/init/stokes.dat.2d +++ b/examples/init/stokes.dat.2d @@ -1,5 +1,5 @@ stokesMesh->global refinements: 0 -stokesMesh->dimension: 1.0 1.0 +stokesMesh->max corner: 1.0 1.0 stokesMesh->num cells: 4 4 stokes->mesh: stokesMesh diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 5537fba2..76b21efe 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -23,7 +23,7 @@ namespace AMDiS { - /// A creator class for meshes. + /// A creator class for dune grids. template struct MeshCreator { @@ -32,13 +32,16 @@ namespace AMDiS using ctype = typename Grid::ctype; - /// Create a new grid by inspecting the intifile parameters `[meshName]->...` + /// Create a new grid by inspecting the intifile parameter group `[meshName]` /** - * Reads first the parameter `[meshName]->structured` and if set, creates: + * Reads first the parameter `[meshName]->macro file name` and if set + * - reads the grid from file + * + * Otherwise reads the parameter `[meshName]->structured` and if set, creates: * - cube: a structured cube grid * - simplex: a structured simplex grid * - * Otherwise an unstructured grid is read from file `[meshName]->macro file name`. + * Otherwise tries to create a grid depending on the grid type. **/ static std::unique_ptr create(std::string const& meshName) { @@ -86,25 +89,20 @@ namespace AMDiS template static std::unique_ptr create_structured_grid(std::string const& meshName, Factory factory) { - Dune::FieldVector lower(0); // Lower left corner of the domain - Dune::FieldVector upper(1); // Upper right corner of the domain + // Lower left corner of the domain + FieldVector lower(0); + // Upper right corner of the domain + FieldVector upper(1); + // number of blocks in each coordinate direction auto numCells = Dune::filledArray(1); - auto lower_opt = Parameters::get(meshName + "->min corner"); - auto upper_opt = Parameters::get(meshName + "->max corner"); - auto dim_opt = Parameters::get(meshName + "->dimension"); - if (lower_opt && upper_opt) { - lower = *lower_opt; - upper = *upper_opt; - } else if (dim_opt) { - upper = *dim_opt; - } - - Parameters::get(meshName + "->num cells", numCells); + Parameters::get(meshName + "->min corner", lower); + Parameters::get(meshName + "->max corner", upper); + Parameters::get(meshName + "->num cells", numCells); return factory(lower, upper, numCells); } - // read a filename from `macro file name` and determine from the extension the fileformat + // read a filename from `[meshName]->macro file name` and determine from the extension the fileformat static std::unique_ptr create_unstructured_grid(std::string const& filename) { filesystem::path fn(filename); @@ -126,7 +124,6 @@ namespace AMDiS } } - // read from Alberta file #if HAVE_ALBERTA template @@ -170,6 +167,7 @@ namespace AMDiS } #endif + // use the dgf parser of a corresponding dgf grid factory is defined for the grid type template >)> static std::unique_ptr read_dgf_file(std::string const& filename, Dune::PriorityTag<1>) @@ -178,6 +176,7 @@ namespace AMDiS return std::unique_ptr{reader.release()}; } + // fallback if no dgf parser is available template static std::unique_ptr read_dgf_file(std::string const& filename, Dune::PriorityTag<0>) { @@ -185,8 +184,9 @@ namespace AMDiS return {}; } + #if HAVE_ALBERTA - // albertagrid + // albertagrid -> simplex template ::value)> static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<3>) @@ -195,7 +195,7 @@ namespace AMDiS } #endif - // yasp grid + // yasp grid -> cube template static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<2>) @@ -203,7 +203,7 @@ namespace AMDiS return create_cube_grid(meshName); } - // spgrid + // spgrid -> cube template @@ -217,6 +217,7 @@ namespace AMDiS }); } + // final fallback template static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<0>) { -- GitLab From 3b2d97ff96b5e9a2df2e1d9255e60a665d6e233e Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Fri, 3 May 2019 14:55:12 +0200 Subject: [PATCH 04/10] add missing namespace qualifier --- src/amdis/MeshCreator.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 76b21efe..99a8557f 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -90,9 +90,9 @@ namespace AMDiS static std::unique_ptr create_structured_grid(std::string const& meshName, Factory factory) { // Lower left corner of the domain - FieldVector lower(0); + Dune::FieldVector lower(0); // Upper right corner of the domain - FieldVector upper(1); + Dune::FieldVector upper(1); // number of blocks in each coordinate direction auto numCells = Dune::filledArray(1); -- GitLab From 82ec47a68de1a291dd6faaafb1230cf2794f410a Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Wed, 8 May 2019 16:00:11 +0200 Subject: [PATCH 05/10] add fallback implementation for gmsh reader --- src/amdis/MeshCreator.hpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 99a8557f..1a93e737 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -109,8 +109,7 @@ namespace AMDiS auto ext = fn.extension(); if (ext == ".msh") { - Dune::GmshReader reader; - return std::unique_ptr{reader.read(filename)}; + return read_gmsh_file(filename, Dune::PriorityTag<42>{}); } else if (ext == ".1d" || ext == ".2d" || ext == ".3d" || ext == ".amc") { return read_alberta_file(filename, Dune::PriorityTag<42>{}); @@ -124,6 +123,29 @@ namespace AMDiS } } + template + using SupportsGmshReader = decltype(std::declval>().insertBoundarySegment( + std::declval>(), + std::declval >>()) ); + + // use GmshReader if GridFactory supports insertBoundarySegments + template ::value)> + static std::unique_ptr read_gmsh_file(std::string const& filename, Dune::PriorityTag<2>) + { + Dune::GmshReader reader; + return std::unique_ptr{reader.read(filename)}; + } + + // fallback if GmshReader cannot be used + template + static std::unique_ptr read_gmsh_file(std::string const& filename, Dune::PriorityTag<0>) + { + error_exit("Gmsh reader not supported for this grid type!"); + return {}; + } + + // read from Alberta file #if HAVE_ALBERTA template @@ -133,7 +155,7 @@ namespace AMDiS template ::value)> - static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) + static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) { return std::make_unique(filename); } @@ -141,7 +163,7 @@ namespace AMDiS // use a gridfactory and the generic AlbertaReader template - static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) + static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) { Dune::GridFactory factory; Dune::AlbertaReader reader; -- GitLab From c9628b0f55e01101532cb81b156aef3514c5b8c5 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Thu, 9 May 2019 18:06:38 +0200 Subject: [PATCH 06/10] rebase to master --- src/amdis/MeshCreator.hpp | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 1a93e737..796f1070 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -114,9 +115,6 @@ namespace AMDiS else if (ext == ".1d" || ext == ".2d" || ext == ".3d" || ext == ".amc") { return read_alberta_file(filename, Dune::PriorityTag<42>{}); } - else if (ext == ".dgf") { - return read_dgf_file(filename, Dune::PriorityTag<42>{}); - } else { error_exit("Can not read grid file. Unknown file extension."); return {}; @@ -153,7 +151,7 @@ namespace AMDiS // construct the albertagrid directly from a filename template ::value)> static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) { @@ -162,7 +160,7 @@ namespace AMDiS // use a gridfactory and the generic AlbertaReader template + REQUIRES(GridType::dimensionworld == DIM_OF_WORLD)> static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) { Dune::GridFactory factory; @@ -173,7 +171,7 @@ namespace AMDiS // error if WORLDDIM not the same as Grid::dimensionworld template + REQUIRES(GridType::dimensionworld != DIM_OF_WORLD)> static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<1>) { error_exit("Alberta (and AlbertaReader) require WORLDDIM == Grid::dimensionworld. Change the cmake parameters!"); @@ -189,23 +187,6 @@ namespace AMDiS } #endif - // use the dgf parser of a corresponding dgf grid factory is defined for the grid type - template >)> - static std::unique_ptr read_dgf_file(std::string const& filename, Dune::PriorityTag<1>) - { - Dune::GridPtr reader(filename); - return std::unique_ptr{reader.release()}; - } - - // fallback if no dgf parser is available - template - static std::unique_ptr read_dgf_file(std::string const& filename, Dune::PriorityTag<0>) - { - error_exit("DGFParser for GridType not defined. Maybe include the corresponding grid header file."); - return {}; - } - #if HAVE_ALBERTA // albertagrid -> simplex @@ -233,7 +214,8 @@ namespace AMDiS { return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) { - std::array cells(numCells); + std::array cells; + std::copy(std::begin(numCells), std::end(numCells), std::begin(cells)); typename GridType::MultiIndex multiIndex(cells); return std::make_unique(lower, upper, multiIndex); }); -- GitLab From d7c47aa52d9c18a276d8f44dd1b7439334e69452 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Thu, 9 May 2019 18:39:29 +0200 Subject: [PATCH 07/10] add possibility to read boundary and element ids from gmsh files --- src/amdis/BoundaryManager.hpp | 7 +++ src/amdis/MeshCreator.hpp | 81 ++++++++++++++++++++++------------- src/amdis/ProblemStat.inc.hpp | 5 ++- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/amdis/BoundaryManager.hpp b/src/amdis/BoundaryManager.hpp index 9e9191eb..1b435839 100644 --- a/src/amdis/BoundaryManager.hpp +++ b/src/amdis/BoundaryManager.hpp @@ -154,6 +154,13 @@ namespace AMDiS } } + template + void setBoundaryIds(std::vector const& ids) + { + test_exit(ids.size() == boundaryIds_.size(), "Number of boundary IDs does not match!"); + std::copy(ids.begin(), ids.end(), boundaryIds_.begin()); + } + private: std::shared_ptr grid_; using Super::boundaryIds_; diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 796f1070..4af81689 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -33,6 +33,14 @@ namespace AMDiS using ctype = typename Grid::ctype; + /// Construct a new MEshCreator + /** + * \param name The name of the mesh used in the initifile + **/ + MeshCreator(std::string const& name) + : name_(name) + {} + /// Create a new grid by inspecting the intifile parameter group `[meshName]` /** * Reads first the parameter `[meshName]->macro file name` and if set @@ -44,51 +52,61 @@ namespace AMDiS * * Otherwise tries to create a grid depending on the grid type. **/ - static std::unique_ptr create(std::string const& meshName) + std::unique_ptr create() const { - auto filename = Parameters::get(meshName + "->macro file name"); - auto structured = Parameters::get(meshName + "->structured"); + auto filename = Parameters::get(name_ + "->macro file name"); + auto structured = Parameters::get(name_ + "->structured"); if (filename) { // read a macro file return create_unstructured_grid(filename.value()); } else if (structured) { // create structured grids if (structured.value() == "cube") { - return create_cube_grid(meshName); + return create_cube_grid(); } else if (structured && structured.value() == "simplex") { - return create_simplex_grid(meshName); + return create_simplex_grid(); } else { error_exit("Unknown structured grid type. Must be either `cube` or `simplex` in parameter [meshName]->structured."); return {}; } } else { // decide by inspecting the grid type how to create the grid - return create_by_gridtype(meshName, Dune::PriorityTag<42>{}); + return create_by_gridtype(Dune::PriorityTag<42>{}); } } /// Create a structured cube grid - static std::unique_ptr create_cube_grid(std::string const& meshName) + std::unique_ptr create_cube_grid() const { - return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) + return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells) { return Dune::StructuredGridFactory::createCubeGrid(lower, upper, numCells); }); } /// Create a structured simplex grid - static std::unique_ptr create_simplex_grid(std::string const& meshName) + std::unique_ptr create_simplex_grid() const { - return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) + return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells) { return Dune::StructuredGridFactory::createSimplexGrid(lower, upper, numCells); }); } + std::vector const& boundaryIds() const + { + return boundaryIds_; + } + + std::vector const& elementIds() const + { + return elementIds_; + } + private: // use the structured grid factory to create the grid template - static std::unique_ptr create_structured_grid(std::string const& meshName, Factory factory) + std::unique_ptr create_structured_grid(Factory factory) const { // Lower left corner of the domain Dune::FieldVector lower(0); @@ -97,14 +115,14 @@ namespace AMDiS // number of blocks in each coordinate direction auto numCells = Dune::filledArray(1); - Parameters::get(meshName + "->min corner", lower); - Parameters::get(meshName + "->max corner", upper); - Parameters::get(meshName + "->num cells", numCells); + Parameters::get(name_ + "->min corner", lower); + Parameters::get(name_ + "->max corner", upper); + Parameters::get(name_ + "->num cells", numCells); return factory(lower, upper, numCells); } // read a filename from `[meshName]->macro file name` and determine from the extension the fileformat - static std::unique_ptr create_unstructured_grid(std::string const& filename) + std::unique_ptr create_unstructured_grid(std::string const& filename) const { filesystem::path fn(filename); auto ext = fn.extension(); @@ -129,15 +147,15 @@ namespace AMDiS // use GmshReader if GridFactory supports insertBoundarySegments template ::value)> - static std::unique_ptr read_gmsh_file(std::string const& filename, Dune::PriorityTag<2>) + std::unique_ptr read_gmsh_file(std::string const& filename, Dune::PriorityTag<2>) const { Dune::GmshReader reader; - return std::unique_ptr{reader.read(filename)}; + return std::unique_ptr{reader.read(filename, boundaryIds_, elementIds_)}; } // fallback if GmshReader cannot be used template - static std::unique_ptr read_gmsh_file(std::string const& filename, Dune::PriorityTag<0>) + std::unique_ptr read_gmsh_file(std::string const& filename, Dune::PriorityTag<0>) const { error_exit("Gmsh reader not supported for this grid type!"); return {}; @@ -153,7 +171,7 @@ namespace AMDiS template ::value)> - static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) + std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) const { return std::make_unique(filename); } @@ -161,7 +179,7 @@ namespace AMDiS // use a gridfactory and the generic AlbertaReader template - static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) + std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) const { Dune::GridFactory factory; Dune::AlbertaReader reader; @@ -172,7 +190,7 @@ namespace AMDiS // error if WORLDDIM not the same as Grid::dimensionworld template - static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<1>) + std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<1>) const { error_exit("Alberta (and AlbertaReader) require WORLDDIM == Grid::dimensionworld. Change the cmake parameters!"); return {}; @@ -180,7 +198,7 @@ namespace AMDiS #else // fallback if no Alberta is available template - static std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<0>) + std::unique_ptr read_alberta_file(std::string const& filename, Dune::PriorityTag<0>) const { error_exit("Alberta (and AlbertaReader) not available. Set AlbertaFlags to your executable in cmake!"); return {}; @@ -192,27 +210,27 @@ namespace AMDiS // albertagrid -> simplex template ::value)> - static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<3>) + std::unique_ptr create_by_gridtype(Dune::PriorityTag<3>) const { - return create_simplex_grid(meshName); + return create_simplex_grid(); } #endif // yasp grid -> cube template - static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<2>) + std::unique_ptr create_by_gridtype(Dune::PriorityTag<2>) const { - return create_cube_grid(meshName); + return create_cube_grid(); } // spgrid -> cube template - static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<1>) + std::unique_ptr create_by_gridtype(Dune::PriorityTag<1>) const { - return create_structured_grid(meshName, [](auto&& lower, auto&& upper, auto&& numCells) + return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells) { std::array cells; std::copy(std::begin(numCells), std::end(numCells), std::begin(cells)); @@ -223,11 +241,16 @@ namespace AMDiS // final fallback template - static std::unique_ptr create_by_gridtype(std::string const& meshName, Dune::PriorityTag<0>) + std::unique_ptr create_by_gridtype(Dune::PriorityTag<0>) const { error_exit("Don't know how to create the grid."); return {}; } + + private: + std::string name_; + mutable std::vector boundaryIds_; + mutable std::vector elementIds_; }; diff --git a/src/amdis/ProblemStat.inc.hpp b/src/amdis/ProblemStat.inc.hpp index 0a942639..34d552a6 100644 --- a/src/amdis/ProblemStat.inc.hpp +++ b/src/amdis/ProblemStat.inc.hpp @@ -126,8 +126,11 @@ template void ProblemStat::createGrid() { Parameters::get(name_ + "->mesh", gridName_); - grid_ = MeshCreator::create(gridName_); + MeshCreator creator(gridName_); + grid_ = creator.create(); boundaryManager_ = std::make_shared>(grid_); + if (!creator.boundaryIds().empty()) + boundaryManager_->setBoundaryIds(creator.boundaryIds()); msg("Create grid:"); msg("#elements = {}" , grid_->size(0)); -- GitLab From b9ef5b00e22ba02197694412f00587b27f2ccef8 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Fri, 3 May 2019 13:21:10 +0200 Subject: [PATCH 08/10] removed parameter [meshName]->dimension in favour of --- src/amdis/MeshCreator.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 4af81689..1e1114a8 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -206,6 +206,7 @@ namespace AMDiS #endif + #if HAVE_ALBERTA // albertagrid -> simplex template Date: Thu, 9 May 2019 18:06:38 +0200 Subject: [PATCH 09/10] rebase to master --- src/amdis/MeshCreator.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 1e1114a8..4af81689 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -206,7 +206,6 @@ namespace AMDiS #endif - #if HAVE_ALBERTA // albertagrid -> simplex template Date: Wed, 22 May 2019 15:29:38 +0200 Subject: [PATCH 10/10] Added MacroGridFactory for an alternative structured grid creation compatible with AlbertaGrid --- src/amdis/MeshCreator.hpp | 10 +- src/amdis/utility/CMakeLists.txt | 1 + src/amdis/utility/MacroGridFactory.hpp | 150 +++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 src/amdis/utility/MacroGridFactory.hpp diff --git a/src/amdis/MeshCreator.hpp b/src/amdis/MeshCreator.hpp index 4af81689..2dc00df3 100644 --- a/src/amdis/MeshCreator.hpp +++ b/src/amdis/MeshCreator.hpp @@ -13,7 +13,6 @@ #include #endif #include -#include #include #include @@ -21,6 +20,7 @@ #include #include #include +#include namespace AMDiS { @@ -33,7 +33,7 @@ namespace AMDiS using ctype = typename Grid::ctype; - /// Construct a new MEshCreator + /// Construct a new MeshCreator /** * \param name The name of the mesh used in the initifile **/ @@ -89,15 +89,17 @@ namespace AMDiS { return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells) { - return Dune::StructuredGridFactory::createSimplexGrid(lower, upper, numCells); + return MacroGridFactory::createSimplexGrid(lower, upper, numCells); }); } + /// Return the filled vector of boundary ids. NOTE: not all creators support reading this. std::vector const& boundaryIds() const { return boundaryIds_; } + /// Return the filled vector of element ids. NOTE: not all creators support reading this. std::vector const& elementIds() const { return elementIds_; @@ -224,6 +226,7 @@ namespace AMDiS return create_cube_grid(); } +#if HAVE_DUNE_SPGRID // spgrid -> cube template (lower, upper, multiIndex); }); } +#endif // final fallback template diff --git a/src/amdis/utility/CMakeLists.txt b/src/amdis/utility/CMakeLists.txt index f9300e39..870230af 100644 --- a/src/amdis/utility/CMakeLists.txt +++ b/src/amdis/utility/CMakeLists.txt @@ -2,5 +2,6 @@ install(FILES AssembleOperators.hpp LocalBasisCache.hpp LocalToGlobalAdapter.hpp + MacroGridFactory.hpp QuadratureFactory.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/utility) diff --git a/src/amdis/utility/MacroGridFactory.hpp b/src/amdis/utility/MacroGridFactory.hpp new file mode 100644 index 00000000..26b0eae6 --- /dev/null +++ b/src/amdis/utility/MacroGridFactory.hpp @@ -0,0 +1,150 @@ +#pragma once + +#include +#include +#include + +#if ! DUNE_VERSION_GT(DUNE_GRID,2,6) + #include +#endif + +namespace Dune +{ + template + struct CubedWrapper : public GridType {}; + + + template + class GridFactory> + : public GridFactoryInterface + { + using Self = GridFactory; + using ctype = typename GridType::ctype; + + enum { dim = GridType::dimension }; + enum { dimworld = GridType::dimensionworld }; + + public: + template = 0> + GridFactory (Args&&... args) + : factory_(std::make_shared>(std::forward(args)...)) + {} + + GridFactory (GridFactory& factory) + : factory_(stackobject_to_shared_ptr(factory)) + {} + + /// \brief Insert a vertex into the coarse grid + void insertVertex (const FieldVector& pos) override + { + factory_->insertVertex(pos); + } + + /// \brief Insert simplex elements into the coarse grid + /** + * Creates a simplex subdividion of the cube element. + * + * \param type The GeometryType of the box grid + * \param vertices Indices of the cube corners + **/ + void insertElement (const GeometryType& type, + const std::vector& vertices) override + { + // triangulation of reference cube + static const auto reference_cubes = std::make_tuple( + std::array, 1>{std::array{0,1}}, + std::array, 2>{std::array{3,0,1}, std::array{0,3,2}}, + std::array, 6>{std::array{0,7,3,1}, std::array{0,7,5,1}, + std::array{0,7,5,4}, std::array{0,7,3,2}, + std::array{0,7,6,2}, std::array{0,7,6,4}} ); + + assert(type == GeometryTypes::cube(dim)); + + auto const& simplices = std::get(reference_cubes); + thread_local std::vector corners(dim+1); + for (auto const& simplex : simplices) { + for (std::size_t i = 0; i < simplex.size(); ++i) + corners[i] = vertices[simplex[i]]; + + factory_->insertElement(GeometryTypes::simplex(dim), corners); + } + } + + /// \brief insert a boundary segment + // TODO: maybe split boundary segment in simplices + void insertBoundarySegment (const std::vector& vertices) override + { + factory_->insertBoundarySegment(vertices); + } + + /// \brief Finalize grid creation and hand over the grid +#if DUNE_VERSION_GT(DUNE_GRID,2,6) + ToUniquePtr createGrid () override +#else + GridType* createGrid () override +#endif + { + return factory_->createGrid(); + } + + private: + std::shared_ptr> factory_; + }; + +} // end namespace Dune + + +namespace AMDiS +{ + template + class MacroGridFactory + { + using ctype = typename GridType::ctype; + + enum { dim = GridType::dimension }; + enum { dimworld = GridType::dimensionworld }; + + public: +#if DUNE_VERSION_GT(DUNE_GRID,2,6) + /// \brief insert structured simplex grid into grid factory + static std::unique_ptr createSimplexGrid (Dune::GridFactory& originalFactory, + const Dune::FieldVector& lowerLeft, + const Dune::FieldVector& upperRight, + const std::array& numElements) + { + Dune::GridFactory> factory(originalFactory); + Dune::StructuredGridFactory>::createCubeGrid(factory, lowerLeft, upperRight, numElements); + return std::unique_ptr(factory.createGrid()); + } +#endif + + /// \brief Create a structured simplex grid + static std::unique_ptr createSimplexGrid (const Dune::FieldVector& lowerLeft, + const Dune::FieldVector& upperRight, + const std::array& numElements) + { + Dune::GridFactory> factory; +#if DUNE_VERSION_GT(DUNE_GRID,2,6) + Dune::StructuredGridFactory>::createCubeGrid(factory, lowerLeft, upperRight, numElements); +#else + // fallback implementation using temporary YaspGrid + using TempGrid = Dune::YaspGrid>; + auto grid = Dune::StructuredGridFactory::createCubeGrid(lowerLeft, upperRight, numElements); + for (auto const& v : vertices(grid->leafGridView())) + factory.insertVertex(v.geometry().corner(0)); + + auto const& indexSet = grid->leafIndexSet(); + for (auto const& e : elements(grid->leafGridView())) + { + thread_local std::vector vertices; + vertices.resize(e.subEntities(dim)); + for (unsigned int i = 0; i < e.subEntities(dim); ++i) + vertices[i] = indexSet.subIndex(e,i,dim); + factory.insertElement(Dune::GeometryTypes::cube(dim), vertices); + } +#endif + return std::unique_ptr(factory.createGrid()); + } + }; + +} // end namespace AMDiS -- GitLab