From ef6d9c844008a762e4cbe164dba99cf8ec4690a2 Mon Sep 17 00:00:00 2001 From: Anthony Royer <anthony.royer@uliege.be> Date: Fri, 29 Oct 2021 20:05:41 +0200 Subject: [PATCH] Cleaning repo --- CMakeLists.txt | 6 + demos/helmholtz/scattering/pml/main.cpp | 853 ------------------ .../scattering/testWithoutGInPML/main.cpp | 767 ---------------- demos/helmholtzflow/freefield/runTests.sh | 19 - demos/navier/scattering/CMakeLists.txt | 8 - examples/.clang-format | 112 +++ examples/CMakeLists.txt | 14 + examples/README.md | 4 + examples/README_template.md | 23 + demos/demos.cmake => examples/example.cmake | 3 +- .../checkerboard_bcgs}/CMakeLists.txt | 2 +- .../helmholtz/checkerboard_bcgs/conv_test.txt | 0 .../helmholtz/checkerboard_bcgs/main.cpp | 56 +- .../scattering/planeWaveDisk/CMakeLists.txt | 2 +- .../scattering/planeWaveDisk/main.cpp | 118 +-- .../helmholtzflow/freefield}/CMakeLists.txt | 2 +- .../helmholtzflow/freefield/main.cpp | 191 ++-- examples/helmholtzflow/freefield/runTests.sh | 7 + .../helmholtzflow/waveguide}/CMakeLists.txt | 2 +- .../helmholtzflow/waveguide/main.cpp | 217 +++-- {demos => examples}/maxwell/CMakeLists.txt | 2 +- {demos => examples}/maxwell/main.cpp | 160 ++-- .../navier/scattering}/CMakeLists.txt | 2 +- .../navier/scattering/main.cpp | 89 +- tutorials/.clang-format | 112 +++ tutorials/CMakeLists.txt | 11 + tutorials/README.md | 3 + tutorials/helmholtz/waveguide/CMakeLists.txt | 8 + .../helmholtz/waveguide/main.cpp | 56 +- tutorials/maxwell/main.cpp | 359 ++++++++ tutorials/maxwell/waveguide/CMakeLists.txt | 8 + tutorials/maxwell/waveguide/main.cpp | 213 +++++ tutorials/tutorial.cmake | 98 ++ 33 files changed, 1426 insertions(+), 2101 deletions(-) delete mode 100644 demos/helmholtz/scattering/pml/main.cpp delete mode 100644 demos/helmholtz/scattering/testWithoutGInPML/main.cpp delete mode 100644 demos/helmholtzflow/freefield/runTests.sh delete mode 100755 demos/navier/scattering/CMakeLists.txt create mode 100644 examples/.clang-format create mode 100644 examples/CMakeLists.txt create mode 100644 examples/README.md create mode 100644 examples/README_template.md rename demos/demos.cmake => examples/example.cmake (97%) rename {demos/helmholtz/waveguide => examples/helmholtz/checkerboard_bcgs}/CMakeLists.txt (73%) rename {demos => examples}/helmholtz/checkerboard_bcgs/conv_test.txt (100%) rename {demos => examples}/helmholtz/checkerboard_bcgs/main.cpp (82%) rename {demos => examples}/helmholtz/scattering/planeWaveDisk/CMakeLists.txt (72%) rename {demos => examples}/helmholtz/scattering/planeWaveDisk/main.cpp (70%) rename {demos/helmholtz/checkerboard_bcgs => examples/helmholtzflow/freefield}/CMakeLists.txt (73%) rename {demos => examples}/helmholtzflow/freefield/main.cpp (63%) create mode 100644 examples/helmholtzflow/freefield/runTests.sh rename {demos/helmholtzflow/freefield => examples/helmholtzflow/waveguide}/CMakeLists.txt (73%) rename {demos => examples}/helmholtzflow/waveguide/main.cpp (64%) rename {demos => examples}/maxwell/CMakeLists.txt (74%) rename {demos => examples}/maxwell/main.cpp (70%) rename {demos/helmholtzflow/waveguide => examples/navier/scattering}/CMakeLists.txt (73%) mode change 100644 => 100755 rename {demos => examples}/navier/scattering/main.cpp (68%) create mode 100644 tutorials/.clang-format create mode 100644 tutorials/CMakeLists.txt create mode 100644 tutorials/README.md create mode 100644 tutorials/helmholtz/waveguide/CMakeLists.txt rename {demos => tutorials}/helmholtz/waveguide/main.cpp (78%) create mode 100644 tutorials/maxwell/main.cpp create mode 100644 tutorials/maxwell/waveguide/CMakeLists.txt create mode 100644 tutorials/maxwell/waveguide/main.cpp create mode 100644 tutorials/tutorial.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 75934f7c..c5988306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(gmshddm CXX) +include(CTest) +enable_testing() + set(GMSHDDM_MAJOR_VERSION 1) set(GMSHDDM_MINOR_VERSION 0) set(GMSHDDM_PATCH_VERSION 0) @@ -142,6 +145,9 @@ add_subdirectory(src/problem) include_directories(src/common src/domain src/field src/problem) include_directories(contrib/eigen) +add_subdirectory(examples) +add_subdirectory(tutorials) + #---------------------------------- # # O T H E R L I B S diff --git a/demos/helmholtz/scattering/pml/main.cpp b/demos/helmholtz/scattering/pml/main.cpp deleted file mode 100644 index 33d688d3..00000000 --- a/demos/helmholtz/scattering/pml/main.cpp +++ /dev/null @@ -1,853 +0,0 @@ -#include "GmshDdm.h" - -#include "FormulationDDM.h" - -#include "Message.h" -#include "AnalyticalFunction.h" - -#include "gmsh.h" - -using namespace gmshddm; -using namespace gmshddm::common; -using namespace gmshddm::domain; -using namespace gmshddm::problem; -using namespace gmshddm::field; - -using namespace gmshfem; -using namespace gmshfem::analytics; -using namespace gmshfem::domain; -using namespace gmshfem::problem; -using namespace gmshfem::field; -using namespace gmshfem::function; -using namespace gmshfem::post; - -gmshfem::function::TensorFunction< std::complex< double > > getPmlDParameter(const double k, const double pmlSize, const double pos, const bool onX); -gmshfem::function::ScalarFunction< std::complex< double > > getPmlEParameter(const double k, const double pmlSize, const double pos, const bool onX); - -void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const double xSize, const double ySize, const double circleSize, const double pmlSize, const double lc, const bool pml = true, const unsigned int circlePosX = 0, const unsigned int circlePosY = 0) -{ - std::vector< std::vector< int > > omega(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - omega[i].resize(nDomY); - } - - // ****************** - // borders - // ****************** - - // ****(2)**** - // * * - // (3) (1) - // * * - // ****(0)**** - std::vector< std::vector< std::vector< int > > > borders(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - borders[i].resize(nDomY); - for(unsigned int j = 0; j < nDomY; ++j) { - borders[i][j].resize(4); - } - } - - // ****************** - // pmls - // ****************** - - // 1 0 - // 0 ****(2)**** 1 - // * * - // (3) (1) - // * * - // 1 ****(0)**** 0 - // 0 1 - - std::vector< std::vector< std::vector< int > > > pmls(nDomX); - std::vector< std::vector< std::vector< int > > > pmlsInf(nDomX); - std::vector< std::vector< std::vector< std::vector< int > > > > pmlsBnd(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - pmls[i].resize(nDomY); - pmlsInf[i].resize(nDomY); - pmlsBnd[i].resize(nDomY); - for(unsigned int j = 0; j < nDomY; ++j) { - pmls[i][j].resize(4); - pmlsInf[i][j].resize(4); - pmlsBnd[i][j].resize(4); - for(unsigned int k = 0; k < 4; ++k) { - pmlsBnd[i][j][k].resize(2); - } - } - } - - // ****************** - // pmlsSquare - // ****************** - - // (2)*******(1) - // * * - // * * - // * * - // (3)*******(0) - - std::vector< std::vector< std::vector< int > > > pmlsSquare(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - pmlsSquare[i].resize(nDomY); - for(unsigned int j = 0; j < nDomY; ++j) { - pmlsSquare[i][j].resize(4); - } - } - - std::vector< int > left(nDomY); - int bottom = 0; - for(unsigned int i = 0; i < nDomX; ++i) { - for(unsigned int j = 0; j < nDomY; ++j) { - int p[4]; - p[0] = gmsh::model::geo::addPoint(i * xSize, j * ySize, 0., lc); - p[1] = gmsh::model::geo::addPoint((i + 1) * xSize, j * ySize, 0., lc); - p[2] = gmsh::model::geo::addPoint((i + 1) * xSize, (j + 1) * ySize, 0., lc); - p[3] = gmsh::model::geo::addPoint(i * xSize, (j + 1) * ySize, 0., lc); - - int l[4]; - borders[i][j][0] = l[0] = gmsh::model::geo::addLine(p[0], p[1]); - borders[i][j][1] = l[1] = gmsh::model::geo::addLine(p[1], p[2]); - borders[i][j][2] = l[2] = gmsh::model::geo::addLine(p[2], p[3]); - borders[i][j][3] = l[3] = gmsh::model::geo::addLine(p[3], p[0]); - - if(i == 0) { - left[j] = l[1]; - } - else { - borders[i][j][3] = left[j]; - left[j] = l[1]; - } - - if(j == 0) { - bottom = l[2]; - } - else { - borders[i][j][0] = bottom; - bottom = l[2]; - } - - int ll = gmsh::model::geo::addCurveLoop({l[0], l[1], l[2], l[3]}); - - int surface = 0; - if(i == circlePosX && j == circlePosY) { - // circle - int pC[5]; - pC[0] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2., circlePosY * j + ySize / 2., 0., lc); - pC[1] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2. + circleSize, circlePosY * j + ySize / 2., 0., lc); - pC[2] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2., circlePosY * j + ySize / 2. + circleSize, 0., lc); - pC[3] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2. - circleSize, circlePosY * j + ySize / 2., 0., lc); - pC[4] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2., circlePosY * j + ySize / 2. - circleSize, 0., lc); - - int lC[4]; - lC[0] = gmsh::model::geo::addCircleArc(pC[1], pC[0], pC[2]); - lC[1] = gmsh::model::geo::addCircleArc(pC[2], pC[0], pC[3]); - lC[2] = gmsh::model::geo::addCircleArc(pC[3], pC[0], pC[4]); - lC[3] = gmsh::model::geo::addCircleArc(pC[4], pC[0], pC[1]); - - // surface - int llC; - llC = gmsh::model::geo::addCurveLoop({lC[0], lC[1], lC[2], lC[3]}); - - surface = gmsh::model::geo::addPlaneSurface({ll, llC}); - - gmsh::model::addPhysicalGroup(1, {lC[0], lC[1], lC[2], lC[3]}, 1); - gmsh::model::setPhysicalName(1, 1, "gammaScat"); - } - else { - surface = gmsh::model::geo::addPlaneSurface({ll}); - } - omega[i][j] = surface; - - if(pml) { - // pmls - double extrudeX[4] = {0., pmlSize, 0., -pmlSize}; - double extrudeY[4] = {-pmlSize, 0., pmlSize, 0.}; - for(unsigned int k = 0; k < 4; ++k) { - std::vector< std::pair< int, int > > extrudeEntities; - gmsh::model::geo::extrude({std::make_pair(1, ((k == 3 && i != 0) || (k == 0 && j != 0) ? 1 : -1) * borders[i][j][k])}, extrudeX[k], extrudeY[k], 0., extrudeEntities, {static_cast< int >(pmlSize / lc)}, std::vector< double >(), true); - pmlsInf[i][j][k] = extrudeEntities[0].second; - pmls[i][j][k] = extrudeEntities[1].second; - if((k == 3 && i != 0) || (k == 0 && j != 0)) { - pmlsBnd[i][j][k][0] = extrudeEntities[2].second; - pmlsBnd[i][j][k][1] = extrudeEntities[3].second; - } - else { - pmlsBnd[i][j][k][0] = extrudeEntities[3].second; - pmlsBnd[i][j][k][1] = extrudeEntities[4].second; - } - } - - // pmlsSquare - double extrudeSquareX[4] = {pmlSize, pmlSize, -pmlSize, -pmlSize}; - int side[4] = {0, 2, 2, 0}; - int sideBnd[4] = {1, 0, 1, 0}; - for(unsigned int k = 0; k < 4; ++k) { - std::vector< std::pair< int, int > > extrudeEntities; - gmsh::model::geo::extrude({std::make_pair(1, -pmlsBnd[i][j][side[k]][sideBnd[k]])}, extrudeSquareX[k], 0., 0., extrudeEntities, {static_cast< int >(pmlSize / lc)}, std::vector< double >(), true); - pmlsSquare[i][j][k] = extrudeEntities[1].second; - } - } - } - } - - gmsh::model::geo::synchronize(); - - // ****************** - // physicals - // ****************** - - for(unsigned int i = 0; i < nDomX; ++i) { - for(unsigned int j = 0; j < nDomY; ++j) { - gmsh::model::addPhysicalGroup(2, {omega[i][j]}, i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, i * nDomY + j + 1, "omega_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][0]}, 10000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 10000 + i * nDomY + j + 1, "sigmaS_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][1]}, 20000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 20000 + i * nDomY + j + 1, "sigmaE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][2]}, 30000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 30000 + i * nDomY + j + 1, "sigmaN_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][3]}, 40000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 40000 + i * nDomY + j + 1, "sigmaW_" + std::to_string(i) + "_" + std::to_string(j)); - - if(pml) { - // PMLs - gmsh::model::addPhysicalGroup(2, {pmls[i][j][0]}, 10000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 10000 + i * nDomY + j + 1, "pmlS_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmls[i][j][1]}, 20000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 20000 + i * nDomY + j + 1, "pmlE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmls[i][j][2]}, 30000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 30000 + i * nDomY + j + 1, "pmlN_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmls[i][j][3]}, 40000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 40000 + i * nDomY + j + 1, "pmlW_" + std::to_string(i) + "_" + std::to_string(j)); - - // PMLs square - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][0]}, 100000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 100000 + i * nDomY + j + 1, "pmlSE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][1]}, 200000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 200000 + i * nDomY + j + 1, "pmlNE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][2]}, 300000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 300000 + i * nDomY + j + 1, "pmlNW_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][3]}, 400000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 400000 + i * nDomY + j + 1, "pmlSW_" + std::to_string(i) + "_" + std::to_string(j)); - - // Sigmas in PMLs - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][3][1]}, 100000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 100000 + i * nDomY + j + 1, "sigmaS_W_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][1][0]}, 150000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 150000 + i * nDomY + j + 1, "sigmaS_E_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][0][1]}, 200000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 200000 + i * nDomY + j + 1, "sigmaE_S_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][2][0]}, 250000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 250000 + i * nDomY + j + 1, "sigmaE_N_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][1][1]}, 300000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 300000 + i * nDomY + j + 1, "sigmaN_E_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][3][0]}, 350000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 350000 + i * nDomY + j + 1, "sigmaN_W_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][2][1]}, 400000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 400000 + i * nDomY + j + 1, "sigmaW_N_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][0][0]}, 450000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 450000 + i * nDomY + j + 1, "sigmaW_S_" + std::to_string(i) + "_" + std::to_string(j)); - - } - } - } - - gmsh::model::addPhysicalGroup(0, {3}, 1); - gmsh::model::setPhysicalName(0, 1, "crossPoint"); - - gmsh::model::geo::synchronize(); - gmsh::model::mesh::generate(); -} - -int main(int argc, char **argv) -{ - GmshDdm gmshDdm(argc, argv); - - double pi = 3.14159265359; - - int nDomX = 2, nDomY = 2; - gmshDdm.userDefinedParameter(nDomX, "nDomX"); - gmshDdm.userDefinedParameter(nDomY, "nDomY"); - double xSize = 1., ySize = 1.; - gmshDdm.userDefinedParameter(xSize, "xSize"); - gmshDdm.userDefinedParameter(ySize, "ySize"); - double circleSize = 0.1; - gmshDdm.userDefinedParameter(circleSize, "circleSize"); - double pmlSize = 0.1; - gmshDdm.userDefinedParameter(pmlSize, "pmlSize"); - double k = 10. * pi + 0.3; - gmshDdm.userDefinedParameter(k, "k"); - double lc = 0.02; - gmshDdm.userDefinedParameter(lc, "lc"); - std::string gauss = "Gauss3"; - gmshDdm.userDefinedParameter(gauss, "gauss"); - int circlePosX = 0, circlePosY = 0; - gmshDdm.userDefinedParameter(circlePosX, "circlePosX"); - gmshDdm.userDefinedParameter(circlePosY, "circlePosY"); - bool errorMono = false; - gmshDdm.userDefinedParameter(errorMono, "errorMono"); - bool withSquarePML = true; - gmshDdm.userDefinedParameter(withSquarePML, "withSquarePML"); - - // Build geometry and mesh using gmsh API - checkerboard(nDomX, nDomY, xSize, ySize, circleSize, pmlSize, lc, true, circlePosX, circlePosY); - - unsigned int nDom = nDomX * nDomY; - - // | | - // NW | N | NE - // ----**************---- - // * * - // * * - // W * * E - // * * - // * * - // ----**************---- - // SW | S | SE - // | | - - // Define domain - Subdomain omega(nDom); - Subdomain gammaDir(nDom); - - Subdomain pmlS(nDom); - Subdomain pmlE(nDom); - Subdomain pmlN(nDom); - Subdomain pmlW(nDom); - - Subdomain pmlSE(nDom); - Subdomain pmlNE(nDom); - Subdomain pmlNW(nDom); - Subdomain pmlSW(nDom); - - InterfaceDomain sigmaS(nDom); - InterfaceDomain sigmaE(nDom); - InterfaceDomain sigmaN(nDom); - InterfaceDomain sigmaW(nDom); - - InterfaceDomain sigmaS_W(nDom); - InterfaceDomain sigmaS_E(nDom); - InterfaceDomain sigmaE_S(nDom); - InterfaceDomain sigmaE_N(nDom); - InterfaceDomain sigmaN_E(nDom); - InterfaceDomain sigmaN_W(nDom); - InterfaceDomain sigmaW_N(nDom); - InterfaceDomain sigmaW_S(nDom); - - InterfaceDomain pmlS_W(nDom); - InterfaceDomain pmlS_E(nDom); - InterfaceDomain pmlE_S(nDom); - InterfaceDomain pmlE_N(nDom); - InterfaceDomain pmlN_E(nDom); - InterfaceDomain pmlN_W(nDom); - InterfaceDomain pmlW_N(nDom); - InterfaceDomain pmlW_S(nDom); - - InterfaceDomain crossPoint(nDom); - - // Define topology - std::vector< std::vector< unsigned int > > topology(nDom); - for(unsigned int i = 0; i < static_cast< unsigned int >(nDomX); ++i) { - for(unsigned int j = 0; j < static_cast< unsigned int >(nDomY); ++j) { - unsigned int index = i * nDomY + j; - - omega(index) = Domain(2, index + 1); - - pmlS(index) = Domain(2, 10000 + index + 1); - pmlE(index) = Domain(2, 20000 + index + 1); - pmlN(index) = Domain(2, 30000 + index + 1); - pmlW(index) = Domain(2, 40000 + index + 1); - - if(withSquarePML || i == static_cast< unsigned int >(nDomX) - 1 || j == 0) { - pmlSE(index) = Domain(2, 100000 + index + 1); - } - - if(withSquarePML || i == static_cast< unsigned int >(nDomX) - 1 || j == static_cast< unsigned int >(nDomY) - 1) { - pmlNE(index) = Domain(2, 200000 + index + 1); - } - - if(withSquarePML || i == 0 || j == static_cast< unsigned int >(nDomY) - 1) { - pmlNW(index) = Domain(2, 300000 + index + 1); - } - - if(withSquarePML || i == 0 || j == 0) { - pmlSW(index) = Domain(2, 400000 + index + 1); - } - - if(i == circlePosX && j == circlePosY) { - gammaDir(index) = Domain(1, 1); - } - - if(i != 0) { - sigmaW(index, (i-1) * nDomY + j) = Domain(1, 40000 + i * nDomY + j + 1); - - crossPoint(index, (i-1) * nDomY + j) = Domain(0, 1); - - if(withSquarePML || j == static_cast< unsigned int >(nDomY) - 1) sigmaW_N(index, (i-1) * nDomY + j) = Domain(1, 400000 + i * nDomY + j + 1); - if(withSquarePML || j == 0) sigmaW_S(index, (i-1) * nDomY + j) = Domain(1, 450000 + i * nDomY + j + 1); - - if(j != static_cast< unsigned int >(nDomY) - 1) pmlW_N(index, (i-1) * nDomY + j) = Domain(1, 350000 + i * nDomY + j + 1); - if(j != 0) pmlW_S(index, (i-1) * nDomY + j) = Domain(1, 100000 + i * nDomY + j + 1); - - topology[index].push_back((i-1) * nDomY + j); - } - if(i != static_cast< unsigned int >(nDomX) - 1) { - sigmaE(index, (i+1) * nDomY + j) = Domain(1, 20000 + i * nDomY + j + 1); - - crossPoint(index, (i+1) * nDomY + j) = Domain(0, 1); - - if(withSquarePML || j == 0) sigmaE_S(index, (i+1) * nDomY + j) = Domain(1, 200000 + i * nDomY + j + 1); - if(withSquarePML || j == static_cast< unsigned int >(nDomY) - 1) sigmaE_N(index, (i+1) * nDomY + j) = Domain(1, 250000 + i * nDomY + j + 1); - - if(j != 0) pmlE_S(index, (i+1) * nDomY + j) = Domain(1, 150000 + i * nDomY + j + 1); - if(j != static_cast< unsigned int >(nDomY) - 1) pmlE_N(index, (i+1) * nDomY + j) = Domain(1, 300000 + i * nDomY + j + 1); - - topology[index].push_back((i+1) * nDomY + j); - } - - if(j != 0) { - sigmaS(index, i * nDomY + (j-1)) = Domain(1, 10000 + i * nDomY + j + 1); - - crossPoint(index, i * nDomY + (j-1)) = Domain(0, 1); - - if(withSquarePML || i == 0) sigmaS_W(index, i * nDomY + (j-1)) = Domain(1, 100000 + i * nDomY + j + 1); - if(withSquarePML || i == static_cast< unsigned int >(nDomX) - 1) sigmaS_E(index, i * nDomY + (j-1)) = Domain(1, 150000 + i * nDomY + j + 1); - - if(i != 0) pmlS_W(index, i * nDomY + (j-1)) = Domain(1, 450000 + i * nDomY + j + 1); - if(i != static_cast< unsigned int >(nDomX) - 1) pmlS_E(index, i * nDomY + (j-1)) = Domain(1, 200000 + i * nDomY + j + 1); - - topology[index].push_back(i * nDomY + (j-1)); - } - if(j != static_cast< unsigned int >(nDomY) - 1) { - sigmaN(index, i * nDomY + (j+1)) = Domain(1, 30000 + i * nDomY + j + 1); - - crossPoint(index, i * nDomY + (j+1)) = Domain(0, 1); - - if(withSquarePML || i == static_cast< unsigned int >(nDomX) - 1) sigmaN_E(index, i * nDomY + (j+1)) = Domain(1, 300000 + i * nDomY + j + 1); - if(withSquarePML || i == 0) sigmaN_W(index, i * nDomY + (j+1)) = Domain(1, 350000 + i * nDomY + j + 1); - - if(i != static_cast< unsigned int >(nDomX) - 1) pmlN_E(index, i * nDomY + (j+1)) = Domain(1, 250000 + i * nDomY + j + 1); - if(i != 0) pmlN_W(index, i * nDomY + (j+1)) = Domain(1, 400000 + i * nDomY + j + 1); - - topology[index].push_back(i * nDomY + (j+1)); - } - } - } - - // Create resolution - Resolution< std::complex< double > > resolution("DDM"); - - // Create DDM formulation - FormulationDDM< std::complex< double > > formulation("Helmholtz", resolution, topology); - - // Create fields - SubdomainField< std::complex< double >, Form::Form0 > u(resolution, "u", omega | gammaDir | pmlS | pmlE | pmlN | pmlW | pmlSE | pmlNE | pmlNW | pmlSW, FunctionSpaceType::Lagrange); - SubdomainField< std::complex< double >, Form::Form0 > lambda(resolution, "lambda", gammaDir, FunctionSpaceType::Lagrange); - - InterfaceField< std::complex< double >, Form::Form0 > gS(resolution, "gS", sigmaS | sigmaS_W | sigmaS_E, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > &gS_W = gS; - InterfaceField< std::complex< double >, Form::Form0 > &gS_E = gS; -// InterfaceField< std::complex< double >, Form::Form0 > gS_W(resolution, "gS_W", sigmaS_W, FunctionSpaceType::Lagrange); -// InterfaceField< std::complex< double >, Form::Form0 > gS_E(resolution, "gS_E", sigmaS_E, FunctionSpaceType::Lagrange); - - InterfaceField< std::complex< double >, Form::Form0 > gE(resolution, "gE", sigmaE | sigmaE_S | sigmaE_N, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > &gE_S = gE; - InterfaceField< std::complex< double >, Form::Form0 > &gE_N = gE; -// InterfaceField< std::complex< double >, Form::Form0 > gE_S(resolution, "gE_S", sigmaE_S, FunctionSpaceType::Lagrange); -// InterfaceField< std::complex< double >, Form::Form0 > gE_N(resolution, "gE_N", sigmaE_N, FunctionSpaceType::Lagrange); - - InterfaceField< std::complex< double >, Form::Form0 > gN(resolution, "gN", sigmaN | sigmaN_E | sigmaN_W, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > &gN_E = gN; - InterfaceField< std::complex< double >, Form::Form0 > &gN_W = gN; -// InterfaceField< std::complex< double >, Form::Form0 > gN_E(resolution, "gN_E", sigmaN_E, FunctionSpaceType::Lagrange); -// InterfaceField< std::complex< double >, Form::Form0 > gN_W(resolution, "gN_W", sigmaN_W, FunctionSpaceType::Lagrange); - - InterfaceField< std::complex< double >, Form::Form0 > gW(resolution, "gW", sigmaW | sigmaW_N | sigmaW_S, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > &gW_N = gW; - InterfaceField< std::complex< double >, Form::Form0 > &gW_S = gW; -// InterfaceField< std::complex< double >, Form::Form0 > gW_N(resolution, "gW_N", sigmaW_N, FunctionSpaceType::Lagrange); -// InterfaceField< std::complex< double >, Form::Form0 > gW_S(resolution, "gW_S", sigmaW_S, FunctionSpaceType::Lagrange); - - std::complex< double > im(0., 1.); - AnalyticalFunction< helmholtz2D::SoftScatteringByACylinder< std::complex< double > > > solution(k, circleSize, xSize / 2., ySize / 2., 2 * k); - - // Tell to the formulation that g is field that have to be exchanged between subdomains - formulation.addInterfaceField(gS); -// formulation.addInterfaceField(gS_W); -// formulation.addInterfaceField(gS_E); - - formulation.addInterfaceField(gE); -// formulation.addInterfaceField(gE_S); -// formulation.addInterfaceField(gE_N); - - formulation.addInterfaceField(gN); -// formulation.addInterfaceField(gN_E); -// formulation.addInterfaceField(gN_W); - - formulation.addInterfaceField(gW); -// formulation.addInterfaceField(gW_N); -// formulation.addInterfaceField(gW_S); - - // Add terms to the formulation - for(unsigned int i = 0; i < nDom; ++i) { - // Compute PML parameters - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaS = abs(y< std::complex< double > >() - (y< std::complex< double > >(omega(i)) - ySize / 2.)); - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaE = abs(x< std::complex< double > >() - (x< std::complex< double > >(omega(i)) + xSize / 2.)); - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaN = abs(y< std::complex< double > >() - (y< std::complex< double > >(omega(i)) + ySize / 2.)); - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaW = abs(x< std::complex< double > >() - (x< std::complex< double > >(omega(i)) - xSize / 2.)); - - gmshfem::function::ScalarFunction< std::complex< double > > sigS = 1. / (pmlSize - distSigmaS) - 1./ pmlSize; - gmshfem::function::ScalarFunction< std::complex< double > > sigE = 1. / (pmlSize - distSigmaE) - 1./ pmlSize; - gmshfem::function::ScalarFunction< std::complex< double > > sigN = 1. / (pmlSize - distSigmaN) - 1./ pmlSize; - gmshfem::function::ScalarFunction< std::complex< double > > sigW = 1. / (pmlSize - distSigmaW) - 1./ pmlSize; - - gmshfem::function::ScalarFunction< std::complex< double > > kyS = 1. + im * sigS / k; - gmshfem::function::ScalarFunction< std::complex< double > > kxE = 1. + im * sigE / k; - gmshfem::function::ScalarFunction< std::complex< double > > kyN = 1. + im * sigN / k; - gmshfem::function::ScalarFunction< std::complex< double > > kxW = 1. + im * sigW / k; - - gmshfem::function::TensorFunction< std::complex< double > > DS = tensorDiag< std::complex< double > >(kyS, 1. / kyS, kyS); - gmshfem::function::ScalarFunction< std::complex< double > > ES = kyS; - - gmshfem::function::TensorFunction< std::complex< double > > DE = tensorDiag< std::complex< double > >(1. / kxE, kxE, kxE); - gmshfem::function::ScalarFunction< std::complex< double > > EE = kxE; - - gmshfem::function::TensorFunction< std::complex< double > > DN = tensorDiag< std::complex< double > >(kyN, 1. / kyN, kyN); - gmshfem::function::ScalarFunction< std::complex< double > > EN = kyN; - - gmshfem::function::TensorFunction< std::complex< double > > DW = tensorDiag< std::complex< double > >(1. / kxW, kxW, kxW); - gmshfem::function::ScalarFunction< std::complex< double > > EW = kxW; - - // VOLUME TERMS - - formulation(i).integral(grad(dof(u(i))), grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(- k * k * dof(u(i)), tf(u(i)), omega(i), gauss); - - // Physical source - formulation(i).integral(dof(lambda(i)), tf(u(i)), gammaDir(i), gauss); - formulation(i).integral(dof(u(i)), tf(lambda(i)), gammaDir(i), gauss); - formulation(i).integral(formulation.physicalSource(-solution), tf(lambda(i)), gammaDir(i), gauss); - - // S - formulation(i).integral(DS * grad(dof(u(i))), grad(tf(u(i))), pmlS(i), gauss); - formulation(i).integral(- ES * k * k * dof(u(i)), tf(u(i)), pmlS(i), gauss); - - // E - formulation(i).integral(DE * grad(dof(u(i))), grad(tf(u(i))), pmlE(i), gauss); - formulation(i).integral(- EE * k * k * dof(u(i)), tf(u(i)), pmlE(i), gauss); - - // N - formulation(i).integral(DN * grad(dof(u(i))), grad(tf(u(i))), pmlN(i), gauss); - formulation(i).integral(- EN * k * k * dof(u(i)), tf(u(i)), pmlN(i), gauss); - - // W - formulation(i).integral(DW * grad(dof(u(i))), grad(tf(u(i))), pmlW(i), gauss); - formulation(i).integral(- EW * k * k * dof(u(i)), tf(u(i)), pmlW(i), gauss); - - // SE - formulation(i).integral(DS * DE * grad(dof(u(i))), grad(tf(u(i))), pmlSE(i), gauss); - formulation(i).integral(- ES * EE * k * k * dof(u(i)), tf(u(i)), pmlSE(i), gauss); - - // NE - formulation(i).integral(DN * DE * grad(dof(u(i))), grad(tf(u(i))), pmlNE(i), gauss); - formulation(i).integral(- EN * EE * k * k * dof(u(i)), tf(u(i)), pmlNE(i), gauss); - - // NW - formulation(i).integral(DN * DW * grad(dof(u(i))), grad(tf(u(i))), pmlNW(i), gauss); - formulation(i).integral(- EN * EW * k * k * dof(u(i)), tf(u(i)), pmlNW(i), gauss); - - // SW - formulation(i).integral(DS * DW * grad(dof(u(i))), grad(tf(u(i))), pmlSW(i), gauss); - formulation(i).integral(- ES * EW * k * k * dof(u(i)), tf(u(i)), pmlSW(i), gauss); - - // Artificial sources - for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { - const unsigned int j = topology[i][jj]; - if(!sigmaS(i,j).isEmpty()) { - formulation(i).integral(formulation.artificialSource( -gN(j,i) ), tf(u(i)), sigmaS(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gN_W(j,i) ), tf(u(i)), sigmaS_W(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gN_E(j,i) ), tf(u(i)), sigmaS_E(i,j), gauss); - } - if(!sigmaE(i,j).isEmpty()) { - formulation(i).integral(formulation.artificialSource( -gW(j,i) ), tf(u(i)), sigmaE(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gW_S(j,i) ), tf(u(i)), sigmaE_S(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gW_N(j,i) ), tf(u(i)), sigmaE_N(i,j), gauss); - } - if(!sigmaN(i,j).isEmpty()) { - formulation(i).integral(formulation.artificialSource( -gS(j,i) ), tf(u(i)), sigmaN(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gS_E(j,i) ), tf(u(i)), sigmaN_E(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gS_W(j,i) ), tf(u(i)), sigmaN_W(i,j), gauss); - } - if(!sigmaW(i,j).isEmpty()) { - formulation(i).integral(formulation.artificialSource( -gE(j,i) ), tf(u(i)), sigmaW(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gE_N(j,i) ), tf(u(i)), sigmaW_N(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gE_S(j,i) ), tf(u(i)), sigmaW_S(i,j), gauss); - } - } - - // INTERFACE TERMS - for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { - const unsigned int j = topology[i][jj]; - // S - if(!sigmaS(i,j).isEmpty()) { - formulation(i,j).integral(dof(gS(i,j)), tf(gS(i,j)), sigmaS(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gN(j,i) ), tf(gS(i,j)), sigmaS(i,j), gauss); - - formulation(i,j).integral(dof(gS_W(i,j)), tf(gS_W(i,j)), sigmaS_W(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gN_W(j,i) ), tf(gS_W(i,j)), sigmaS_W(i,j), gauss); - - formulation(i,j).integral(dof(gS_E(i,j)), tf(gS_E(i,j)), sigmaS_E(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gN_E(j,i) ), tf(gS_E(i,j)), sigmaS_E(i,j), gauss); - - if(!pmlS_W(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gE_S(i - nDomY,i) ), tf(gS(i,j)), pmlS_W(i,j), gauss); - if(!pmlS_E(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gW_S(i + nDomY,i) ), tf(gS(i,j)), pmlS_E(i,j), gauss); - - formulation(i,j).integral(- 2. * DS * grad(u(i)), grad(tf(gS(i,j))), pmlS(i), gauss); - formulation(i,j).integral(2. * ES * k * k * u(i), tf(gS(i,j)), pmlS(i), gauss); - - formulation(i,j).integral(- 2. * DS * DW * grad(u(i)), grad(tf(gS_W(i,j))), pmlSW(i), gauss); - formulation(i,j).integral(2. * ES * EW * k * k * u(i), tf(gS_W(i,j)), pmlSW(i), gauss); - - formulation(i,j).integral(- 2. * DS * DE * grad(u(i)), grad(tf(gS_E(i,j))), pmlSE(i), gauss); - formulation(i,j).integral(2. * ES * EE * k * k * u(i), tf(gS_E(i,j)), pmlSE(i), gauss); - } - - // E - if(!sigmaE(i,j).isEmpty()) { - formulation(i,j).integral(dof(gE(i,j)), tf(gE(i,j)), sigmaE(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gW(j,i) ), tf(gE(i,j)), sigmaE(i,j), gauss); - - formulation(i,j).integral(dof(gE_S(i,j)), tf(gE_S(i,j)), sigmaE_S(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gW_S(j,i) ), tf(gE_S(i,j)), sigmaE_S(i,j), gauss); - - formulation(i,j).integral(dof(gE_N(i,j)), tf(gE_N(i,j)), sigmaE_N(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gW_N(j,i) ), tf(gE_N(i,j)), sigmaE_N(i,j), gauss); - - if(!pmlE_S(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gN_E(i - 1,i) ), tf(gE(i,j)), pmlE_S(i,j), gauss); - if(!pmlE_N(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gS_E(i + 1,i) ), tf(gE(i,j)), pmlE_N(i,j), gauss); - - formulation(i,j).integral(- 2. * DE * grad(u(i)), grad(tf(gE(i,j))), pmlE(i), gauss); - formulation(i,j).integral(2. * EE * k * k * u(i), tf(gE(i,j)), pmlE(i), gauss); - - formulation(i,j).integral(- 2. * DS * DE * grad(u(i)), grad(tf(gE_S(i,j))), pmlSE(i), gauss); - formulation(i,j).integral(2. * ES * EE * k * k * u(i), tf(gE_S(i,j)), pmlSE(i), gauss); - - formulation(i,j).integral(- 2. * DN * DE * grad(u(i)), grad(tf(gE_N(i,j))), pmlNE(i), gauss); - formulation(i,j).integral(2. * EN * EE * k * k * u(i), tf(gE_N(i,j)), pmlNE(i), gauss); - } - - // N - if(!sigmaN(i,j).isEmpty()) { - formulation(i,j).integral(dof(gN(i,j)), tf(gN(i,j)), sigmaN(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gS(j,i) ), tf(gN(i,j)), sigmaN(i,j), gauss); - - formulation(i,j).integral(dof(gN_E(i,j)), tf(gN_E(i,j)), sigmaN_E(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gS_E(j,i) ), tf(gN_E(i,j)), sigmaN_E(i,j), gauss); - - formulation(i,j).integral(dof(gN_W(i,j)), tf(gN_W(i,j)), sigmaN_W(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gS_W(j,i) ), tf(gN_W(i,j)), sigmaN_W(i,j), gauss); - - if(!pmlN_E(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gW_N(i + nDomY,i) ), tf(gN(i,j)), pmlN_E(i,j), gauss); - if(!pmlN_W(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gE_N(i - nDomY,i) ), tf(gN(i,j)), pmlN_W(i,j), gauss); - - formulation(i,j).integral(- 2. * DN * grad(u(i)), grad(tf(gN(i,j))), pmlN(i), gauss); - formulation(i,j).integral(2. * EN * k * k * u(i), tf(gN(i,j)), pmlN(i), gauss); - - formulation(i,j).integral(- 2. * DN * DE * grad(u(i)), grad(tf(gN_E(i,j))), pmlNE(i), gauss); - formulation(i,j).integral(2. * EN * EE * k * k * u(i), tf(gN_E(i,j)), pmlNE(i), gauss); - - formulation(i,j).integral(- 2. * DN * DW * grad(u(i)), grad(tf(gN_W(i,j))), pmlNW(i), gauss); - formulation(i,j).integral(2. * EN * EW * k * k * u(i), tf(gN_W(i,j)), pmlNW(i), gauss); - } - - // W - if(!sigmaW(i,j).isEmpty()) { - formulation(i,j).integral(dof(gW(i,j)), tf(gW(i,j)), sigmaW(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gE(j,i) ), tf(gW(i,j)), sigmaW(i,j), gauss); - - formulation(i,j).integral(dof(gW_N(i,j)), tf(gW_N(i,j)), sigmaW_N(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gE_N(j,i) ), tf(gW_N(i,j)), sigmaW_N(i,j), gauss); - - formulation(i,j).integral(dof(gW_S(i,j)), tf(gW_S(i,j)), sigmaW_S(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gE_S(j,i) ), tf(gW_S(i,j)), sigmaW_S(i,j), gauss); - - if(!pmlW_N(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gS_W(i + 1,i) ), tf(gW(i,j)), pmlW_N(i,j), gauss); - if(!pmlW_S(i,j).isEmpty() && withSquarePML) formulation(i,j).integral(formulation.artificialSource( 2. * gN_W(i - 1,i) ), tf(gW(i,j)), pmlW_S(i,j), gauss); - - formulation(i,j).integral(- 2. * DW * grad(u(i)), grad(tf(gW(i,j))), pmlW(i), gauss); - formulation(i,j).integral(2. * EW * k * k * u(i), tf(gW(i,j)), pmlW(i), gauss); - - formulation(i,j).integral(- 2. * DN * DW * grad(u(i)), grad(tf(gW_N(i,j))), pmlNW(i), gauss); - formulation(i,j).integral(2. * EN * EW * k * k * u(i), tf(gW_N(i,j)), pmlNW(i), gauss); - - formulation(i,j).integral(- 2. * DS * DW * grad(u(i)), grad(tf(gW_S(i,j))), pmlSW(i), gauss); - formulation(i,j).integral(2. * ES * EW * k * k * u(i), tf(gW_S(i,j)), pmlSW(i), gauss); - } - } - } - - // Solve the DDM formulation - formulation.pre(); - formulation.solve("gmres", 1e-6, 1000); - - if(errorMono) { - gmshfem::domain::Domain omegaMono, pmlSMono, pmlEMono, pmlNMono, pmlWMono, pmlSEMono, pmlNEMono, pmlNWMono, pmlSWMono; - for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { - omegaMono |= omega(i); - } - - for(unsigned int i = 0; i < static_cast< unsigned int >(nDomX); ++i) { - pmlSMono |= pmlS(i * nDomY + 0); - pmlNMono |= pmlN(i * nDomY + nDomY - 1); - } - for(unsigned int j = 0; j < static_cast< unsigned int >(nDomY); ++j) { - pmlEMono |= pmlE((nDomX - 1) * nDomY + j); - pmlWMono |= pmlW(0 * nDomY + j); - } - pmlSEMono = pmlSE((nDomX - 1) * nDomY + 0); - pmlNEMono = pmlNE((nDomX - 1) * nDomY + nDomY - 1); - pmlNWMono = pmlNW(0 * nDomY + nDomY - 1); - pmlSWMono = pmlSW(0); - - gmshfem::function::TensorFunction< std::complex< double > > DSmono = getPmlDParameter(k, pmlSize, 0., false); - gmshfem::function::TensorFunction< std::complex< double > > DEmono = getPmlDParameter(k, pmlSize, nDomX * xSize, true); - gmshfem::function::TensorFunction< std::complex< double > > DNmono = getPmlDParameter(k, pmlSize, nDomY * ySize, false); - gmshfem::function::TensorFunction< std::complex< double > > DWmono = getPmlDParameter(k, pmlSize, 0., true); - - gmshfem::function::ScalarFunction< std::complex< double > > ESmono = getPmlEParameter(k, pmlSize, 0., false); - gmshfem::function::ScalarFunction< std::complex< double > > EEmono = getPmlEParameter(k, pmlSize, nDomX * xSize, true); - gmshfem::function::ScalarFunction< std::complex< double > > ENmono = getPmlEParameter(k, pmlSize, nDomY * ySize, false); - gmshfem::function::ScalarFunction< std::complex< double > > EWmono = getPmlEParameter(k, pmlSize, 0., true); - - gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > uMono(resolution, "uMono", gammaDir(circlePosX * nDomY + circlePosY) | omegaMono | pmlSMono | pmlEMono | pmlNMono | pmlWMono | pmlSEMono | pmlNEMono | pmlNWMono | pmlSWMono, FunctionSpaceType::Lagrange); - gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambdaMono(resolution, "lambdaMono", gammaDir(circlePosX * nDomY + circlePosY), FunctionSpaceType::Lagrange); - - Formulation< std::complex< double > > monodomain("HelmholtzMono", resolution); - - monodomain.integral(grad(dof(uMono)), grad(tf(uMono)), omegaMono, gauss); - monodomain.integral(- k * k * dof(uMono), tf(uMono), omegaMono, gauss); - - monodomain.integral(dof(lambdaMono), tf(uMono), gammaDir(circlePosX * nDomY + circlePosY), gauss); - monodomain.integral(dof(uMono), tf(lambdaMono), gammaDir(circlePosX * nDomY + circlePosY), gauss); - monodomain.integral(- solution, tf(lambdaMono), gammaDir(circlePosX * nDomY + circlePosY), gauss); - - monodomain.integral(DSmono * grad(dof(uMono)), grad(tf(uMono)), pmlSMono, gauss); - monodomain.integral(- k * k * ESmono * dof(uMono), tf(uMono), pmlSMono, gauss); - - monodomain.integral(DEmono * grad(dof(uMono)), grad(tf(uMono)), pmlEMono, gauss); - monodomain.integral(- k * k * EEmono * dof(uMono), tf(uMono), pmlEMono, gauss); - - monodomain.integral(DNmono * grad(dof(uMono)), grad(tf(uMono)), pmlNMono, gauss); - monodomain.integral(- k * k * ENmono * dof(uMono), tf(uMono), pmlNMono, gauss); - - monodomain.integral(DWmono * grad(dof(uMono)), grad(tf(uMono)), pmlWMono, gauss); - monodomain.integral(- k * k * EWmono * dof(uMono), tf(uMono), pmlWMono, gauss); - - monodomain.integral(DSmono * DEmono * grad(dof(uMono)), grad(tf(uMono)), pmlSEMono, gauss); - monodomain.integral(- k * k * ESmono * EEmono * dof(uMono), tf(uMono), pmlSEMono, gauss); - - monodomain.integral(DNmono * DEmono * grad(dof(uMono)), grad(tf(uMono)), pmlNEMono, gauss); - monodomain.integral(- k * k * ENmono * EEmono * dof(uMono), tf(uMono), pmlNEMono, gauss); - - monodomain.integral(DNmono * DWmono * grad(dof(uMono)), grad(tf(uMono)), pmlNWMono, gauss); - monodomain.integral(- k * k * ENmono * EWmono * dof(uMono), tf(uMono), pmlNWMono, gauss); - - monodomain.integral(DSmono * DWmono * grad(dof(uMono)), grad(tf(uMono)), pmlSWMono, gauss); - monodomain.integral(- k * k * ESmono * EWmono * dof(uMono), tf(uMono), pmlSWMono, gauss); - - monodomain.pre(); - monodomain.assemble(); - monodomain.solve(); - - save(uMono); - - for(unsigned int i = 0; i < nDom; ++i) { - save(uMono - u(i), omega(i), "eMono_" + std::to_string(i)); - } - - // L2 error - double num = 0., den = 0.; - for(unsigned int i = 0; i < nDom; ++i) { - std::complex< double > denLocal = integrate(pow(abs(uMono), 2), omega(i), gauss); - std::complex< double > numLocal = integrate(pow(abs(uMono - u(i)), 2), omega(i), gauss); - num += numLocal.real(); - den += denLocal.real(); - } - msg::info << "L2 mono domain error = " << std::sqrt(num / den) << msg::endl; - } - - for(unsigned int i = 0; i < nDom; ++i) { - save(+u(i), omega(i), "u_" + std::to_string(i)); - //save(u(i)); - save(solution - u(i), omega(i), "e_" + std::to_string(i)); - for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { - const unsigned int j = topology[i][jj]; - if(!sigmaS(i,j).isEmpty()) save(gS(i,j)); - if(!sigmaE(i,j).isEmpty()) save(gE(i,j)); - if(!sigmaN(i,j).isEmpty()) save(gN(i,j)); - if(!sigmaW(i,j).isEmpty()) save(gW(i,j)); - } - } - - return 0; -} - -gmshfem::function::TensorFunction< std::complex< double > > getPmlDParameter(const double k, const double pmlSize, const double pos, const bool onX) -{ - gmshfem::function::ScalarFunction< std::complex< double > > kx = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > ky = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > kz = 1.; - - std::complex< double > I(0., 1.); - if(onX) { - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(x< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaX = 1. / (pmlSize - distSigma) - 1./ pmlSize; - kx = 1. + I * sigmaX / k; - } - else { // onY - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(y< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaY = 1. / (pmlSize - distSigma) - 1./ pmlSize; - ky = 1. + I * sigmaY / k; - } - - return tensorDiag< std::complex< double > >(ky * kz / kx, kx * kz / ky, kx * ky / kz); -} - -gmshfem::function::ScalarFunction< std::complex< double > > getPmlEParameter(const double k, const double pmlSize, const double pos, const bool onX) -{ - gmshfem::function::ScalarFunction< std::complex< double > > kx = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > ky = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > kz = 1.; - - std::complex< double > I(0., 1.); - if(onX) { - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(x< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaX = 1. / (pmlSize - distSigma) - 1./ pmlSize; - kx = 1. + I * sigmaX / k; - } - else { // onY - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(y< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaY = 1. / (pmlSize - distSigma) - 1./ pmlSize; - ky = 1. + I * sigmaY / k; - } - - return kx * ky * kz; -} diff --git a/demos/helmholtz/scattering/testWithoutGInPML/main.cpp b/demos/helmholtz/scattering/testWithoutGInPML/main.cpp deleted file mode 100644 index 8a356351..00000000 --- a/demos/helmholtz/scattering/testWithoutGInPML/main.cpp +++ /dev/null @@ -1,767 +0,0 @@ -#include "GmshDdm.h" - -#include "FormulationDDM.h" - -#include "Message.h" -#include "AnalyticalFunction.h" - -#include "gmsh.h" - -using namespace gmshddm; -using namespace gmshddm::common; -using namespace gmshddm::domain; -using namespace gmshddm::problem; -using namespace gmshddm::field; - -using namespace gmshfem; -using namespace gmshfem::analytics; -using namespace gmshfem::domain; -using namespace gmshfem::problem; -using namespace gmshfem::field; -using namespace gmshfem::function; -using namespace gmshfem::post; - -gmshfem::function::TensorFunction< std::complex< double > > getPmlDParameter(const double k, const double pmlSize, const double pos, const bool onX); -gmshfem::function::ScalarFunction< std::complex< double > > getPmlEParameter(const double k, const double pmlSize, const double pos, const bool onX); - -void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const double xSize, const double ySize, const double circleSize, const double pmlSize, const double lc, const bool pml = true, const unsigned int circlePosX = 0, const unsigned int circlePosY = 0) -{ - std::vector< std::vector< int > > omega(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - omega[i].resize(nDomY); - } - - // ****************** - // borders - // ****************** - - // ****(2)**** - // * * - // (3) (1) - // * * - // ****(0)**** - std::vector< std::vector< std::vector< int > > > borders(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - borders[i].resize(nDomY); - for(unsigned int j = 0; j < nDomY; ++j) { - borders[i][j].resize(4); - } - } - - // ****************** - // pmls - // ****************** - - // 1 0 - // 0 ****(2)**** 1 - // * * - // (3) (1) - // * * - // 1 ****(0)**** 0 - // 0 1 - - std::vector< std::vector< std::vector< int > > > pmls(nDomX); - std::vector< std::vector< std::vector< int > > > pmlsInf(nDomX); - std::vector< std::vector< std::vector< std::vector< int > > > > pmlsBnd(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - pmls[i].resize(nDomY); - pmlsInf[i].resize(nDomY); - pmlsBnd[i].resize(nDomY); - for(unsigned int j = 0; j < nDomY; ++j) { - pmls[i][j].resize(4); - pmlsInf[i][j].resize(4); - pmlsBnd[i][j].resize(4); - for(unsigned int k = 0; k < 4; ++k) { - pmlsBnd[i][j][k].resize(2); - } - } - } - - // ****************** - // pmlsSquare - // ****************** - - // (2)*******(1) - // * * - // * * - // * * - // (3)*******(0) - - std::vector< std::vector< std::vector< int > > > pmlsSquare(nDomX); - for(unsigned int i = 0; i < nDomX; ++i) { - pmlsSquare[i].resize(nDomY); - for(unsigned int j = 0; j < nDomY; ++j) { - pmlsSquare[i][j].resize(4); - } - } - - std::vector< int > left(nDomY); - int bottom = 0; - for(unsigned int i = 0; i < nDomX; ++i) { - for(unsigned int j = 0; j < nDomY; ++j) { - int p[4]; - p[0] = gmsh::model::geo::addPoint(i * xSize, j * ySize, 0., lc); - p[1] = gmsh::model::geo::addPoint((i + 1) * xSize, j * ySize, 0., lc); - p[2] = gmsh::model::geo::addPoint((i + 1) * xSize, (j + 1) * ySize, 0., lc); - p[3] = gmsh::model::geo::addPoint(i * xSize, (j + 1) * ySize, 0., lc); - - int l[4]; - borders[i][j][0] = l[0] = gmsh::model::geo::addLine(p[0], p[1]); - borders[i][j][1] = l[1] = gmsh::model::geo::addLine(p[1], p[2]); - borders[i][j][2] = l[2] = gmsh::model::geo::addLine(p[2], p[3]); - borders[i][j][3] = l[3] = gmsh::model::geo::addLine(p[3], p[0]); - - if(i == 0) { - left[j] = l[1]; - } - else { - borders[i][j][3] = left[j]; - left[j] = l[1]; - } - - if(j == 0) { - bottom = l[2]; - } - else { - borders[i][j][0] = bottom; - bottom = l[2]; - } - - int ll = gmsh::model::geo::addCurveLoop({l[0], l[1], l[2], l[3]}); - - int surface = 0; - if(i == circlePosX && j == circlePosY) { - // circle - int pC[5]; - pC[0] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2., circlePosY * j + ySize / 2., 0., lc); - pC[1] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2. + circleSize, circlePosY * j + ySize / 2., 0., lc); - pC[2] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2., circlePosY * j + ySize / 2. + circleSize, 0., lc); - pC[3] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2. - circleSize, circlePosY * j + ySize / 2., 0., lc); - pC[4] = gmsh::model::geo::addPoint(circlePosX * i + xSize / 2., circlePosY * j + ySize / 2. - circleSize, 0., lc); - - int lC[4]; - lC[0] = gmsh::model::geo::addCircleArc(pC[1], pC[0], pC[2]); - lC[1] = gmsh::model::geo::addCircleArc(pC[2], pC[0], pC[3]); - lC[2] = gmsh::model::geo::addCircleArc(pC[3], pC[0], pC[4]); - lC[3] = gmsh::model::geo::addCircleArc(pC[4], pC[0], pC[1]); - - // surface - int llC; - llC = gmsh::model::geo::addCurveLoop({lC[0], lC[1], lC[2], lC[3]}); - - surface = gmsh::model::geo::addPlaneSurface({ll, llC}); - - gmsh::model::addPhysicalGroup(1, {lC[0], lC[1], lC[2], lC[3]}, 1); - gmsh::model::setPhysicalName(1, 1, "gammaScat"); - } - else { - surface = gmsh::model::geo::addPlaneSurface({ll}); - } - omega[i][j] = surface; - - if(pml) { - // pmls - double extrudeX[4] = {0., pmlSize, 0., -pmlSize}; - double extrudeY[4] = {-pmlSize, 0., pmlSize, 0.}; - for(unsigned int k = 0; k < 4; ++k) { - std::vector< std::pair< int, int > > extrudeEntities; - gmsh::model::geo::extrude({std::make_pair(1, ((k == 3 && i != 0) || (k == 0 && j != 0) ? 1 : -1) * borders[i][j][k])}, extrudeX[k], extrudeY[k], 0., extrudeEntities, {static_cast< int >(pmlSize / lc)}, std::vector< double >(), true); - pmlsInf[i][j][k] = extrudeEntities[0].second; - pmls[i][j][k] = extrudeEntities[1].second; - if((k == 3 && i != 0) || (k == 0 && j != 0)) { - pmlsBnd[i][j][k][0] = extrudeEntities[2].second; - pmlsBnd[i][j][k][1] = extrudeEntities[3].second; - } - else { - pmlsBnd[i][j][k][0] = extrudeEntities[3].second; - pmlsBnd[i][j][k][1] = extrudeEntities[4].second; - } - } - - // pmlsSquare - double extrudeSquareX[4] = {pmlSize, pmlSize, -pmlSize, -pmlSize}; - int side[4] = {0, 2, 2, 0}; - int sideBnd[4] = {1, 0, 1, 0}; - for(unsigned int k = 0; k < 4; ++k) { - std::vector< std::pair< int, int > > extrudeEntities; - gmsh::model::geo::extrude({std::make_pair(1, -pmlsBnd[i][j][side[k]][sideBnd[k]])}, extrudeSquareX[k], 0., 0., extrudeEntities, {static_cast< int >(pmlSize / lc)}, std::vector< double >(), true); - pmlsSquare[i][j][k] = extrudeEntities[1].second; - } - } - } - } - - gmsh::model::geo::synchronize(); - - // ****************** - // physicals - // ****************** - - for(unsigned int i = 0; i < nDomX; ++i) { - for(unsigned int j = 0; j < nDomY; ++j) { - gmsh::model::addPhysicalGroup(2, {omega[i][j]}, i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, i * nDomY + j + 1, "omega_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][0]}, 10000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 10000 + i * nDomY + j + 1, "sigmaS_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][1]}, 20000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 20000 + i * nDomY + j + 1, "sigmaE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][2]}, 30000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 30000 + i * nDomY + j + 1, "sigmaN_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {borders[i][j][3]}, 40000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 40000 + i * nDomY + j + 1, "sigmaW_" + std::to_string(i) + "_" + std::to_string(j)); - - if(pml) { - // PMLs - gmsh::model::addPhysicalGroup(2, {pmls[i][j][0]}, 10000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 10000 + i * nDomY + j + 1, "pmlS_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmls[i][j][1]}, 20000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 20000 + i * nDomY + j + 1, "pmlE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmls[i][j][2]}, 30000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 30000 + i * nDomY + j + 1, "pmlN_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmls[i][j][3]}, 40000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 40000 + i * nDomY + j + 1, "pmlW_" + std::to_string(i) + "_" + std::to_string(j)); - - // PMLs square - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][0]}, 100000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 100000 + i * nDomY + j + 1, "pmlSE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][1]}, 200000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 200000 + i * nDomY + j + 1, "pmlNE_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][2]}, 300000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 300000 + i * nDomY + j + 1, "pmlNW_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(2, {pmlsSquare[i][j][3]}, 400000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(2, 400000 + i * nDomY + j + 1, "pmlSW_" + std::to_string(i) + "_" + std::to_string(j)); - - // Sigmas in PMLs - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][3][1]}, 100000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 100000 + i * nDomY + j + 1, "sigmaS_W_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][1][0]}, 150000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 150000 + i * nDomY + j + 1, "sigmaS_E_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][0][1]}, 200000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 200000 + i * nDomY + j + 1, "sigmaE_S_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][2][0]}, 250000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 250000 + i * nDomY + j + 1, "sigmaE_N_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][1][1]}, 300000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 300000 + i * nDomY + j + 1, "sigmaN_E_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][3][0]}, 350000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 350000 + i * nDomY + j + 1, "sigmaN_E_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][2][1]}, 400000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 400000 + i * nDomY + j + 1, "sigmaW_N_" + std::to_string(i) + "_" + std::to_string(j)); - - gmsh::model::addPhysicalGroup(1, {pmlsBnd[i][j][0][0]}, 450000 + i * nDomY + j + 1); - gmsh::model::setPhysicalName(1, 450000 + i * nDomY + j + 1, "sigmaW_S_" + std::to_string(i) + "_" + std::to_string(j)); - - } - } - } - - gmsh::model::geo::synchronize(); - gmsh::model::mesh::generate(); -} - -int main(int argc, char **argv) -{ - GmshDdm gmshDdm(argc, argv); - - double pi = 3.14159265359; - - int nDomX = 2, nDomY = 2; - gmshDdm.userDefinedParameter(nDomX, "nDomX"); - gmshDdm.userDefinedParameter(nDomY, "nDomY"); - double xSize = 1., ySize = 1.; - gmshDdm.userDefinedParameter(xSize, "xSize"); - gmshDdm.userDefinedParameter(ySize, "ySize"); - double circleSize = 0.1; - gmshDdm.userDefinedParameter(circleSize, "circleSize"); - double pmlSize = 0.1; - gmshDdm.userDefinedParameter(pmlSize, "pmlSize"); - double k = 10. * pi; - gmshDdm.userDefinedParameter(k, "k"); - double lc = 0.02; - gmshDdm.userDefinedParameter(lc, "lc"); - std::string gauss = "Gauss3"; - gmshDdm.userDefinedParameter(gauss, "gauss"); - int circlePosX = 0, circlePosY = 0; - gmshDdm.userDefinedParameter(circlePosX, "circlePosX"); - gmshDdm.userDefinedParameter(circlePosY, "circlePosY"); - bool errorMono = false; - gmshDdm.userDefinedParameter(errorMono, "errorMono"); - - // Build geometry and mesh using gmsh API - checkerboard(nDomX, nDomY, xSize, ySize, circleSize, pmlSize, lc, true, circlePosX, circlePosY); - - unsigned int nDom = nDomX * nDomY; - - // | | - // NW | N | NE - // ----**************---- - // * * - // * * - // W * * E - // * * - // * * - // ----**************---- - // SW | S | SE - // | | - - // Define domain - Subdomain omega(nDom); - Subdomain gammaDir(nDom); - - Subdomain pmlS(nDom); - Subdomain pmlE(nDom); - Subdomain pmlN(nDom); - Subdomain pmlW(nDom); - - Subdomain pmlSE(nDom); - Subdomain pmlNE(nDom); - Subdomain pmlNW(nDom); - Subdomain pmlSW(nDom); - - Interface sigmaS(nDom); - Interface sigmaE(nDom); - Interface sigmaN(nDom); - Interface sigmaW(nDom); - - Interface sigmaS_W(nDom); - Interface sigmaS_E(nDom); - Interface sigmaE_S(nDom); - Interface sigmaE_N(nDom); - Interface sigmaN_E(nDom); - Interface sigmaN_W(nDom); - Interface sigmaW_N(nDom); - Interface sigmaW_S(nDom); - - Interface pmlS_W(nDom); - Interface pmlS_E(nDom); - Interface pmlE_S(nDom); - Interface pmlE_N(nDom); - Interface pmlN_E(nDom); - Interface pmlN_W(nDom); - Interface pmlW_N(nDom); - Interface pmlW_S(nDom); - - // Define topology - std::vector< std::vector< unsigned int > > topology(nDom); - for(unsigned int i = 0; i < static_cast< unsigned int >(nDomX); ++i) { - for(unsigned int j = 0; j < static_cast< unsigned int >(nDomY); ++j) { - unsigned int index = i * nDomY + j; - - omega(index) = Domain(2, index + 1); - - pmlS(index) = Domain(2, 10000 + index + 1); - pmlE(index) = Domain(2, 20000 + index + 1); - pmlN(index) = Domain(2, 30000 + index + 1); - pmlW(index) = Domain(2, 40000 + index + 1); - - if(i == static_cast< unsigned int >(nDomX) - 1 || j == 0) pmlSE(index) = Domain(2, 100000 + index + 1); - if(i == static_cast< unsigned int >(nDomX) - 1 || j == static_cast< unsigned int >(nDomY) - 1) pmlNE(index) = Domain(2, 200000 + index + 1); - if(i == 0 || j == static_cast< unsigned int >(nDomY) - 1) pmlNW(index) = Domain(2, 300000 + index + 1); - if(i == 0 || j == 0) pmlSW(index) = Domain(2, 400000 + index + 1); - - if(i == circlePosX && j == circlePosY) { - gammaDir(index) = Domain(1, 1); - } - - if(i != 0) { - sigmaW(index, (i-1) * nDomY + j) = Domain(1, 40000 + i * nDomY + j + 1); - - if(j == static_cast< unsigned int >(nDomY) - 1) sigmaW_N(index, (i-1) * nDomY + j) = Domain(1, 400000 + i * nDomY + j + 1); - if(j == 0) sigmaW_S(index, (i-1) * nDomY + j) = Domain(1, 450000 + i * nDomY + j + 1); - - if(j != static_cast< unsigned int >(nDomY) - 1) pmlW_N(index, (i-1) * nDomY + j) = Domain(1, 350000 + i * nDomY + j + 1); - if(j != 0) pmlW_S(index, (i-1) * nDomY + j) = Domain(1, 100000 + i * nDomY + j + 1); - - topology[index].push_back((i-1) * nDomY + j); - } - if(i != static_cast< unsigned int >(nDomX) - 1) { - sigmaE(index, (i+1) * nDomY + j) = Domain(1, 20000 + i * nDomY + j + 1); - - if(j == 0) sigmaE_S(index, (i+1) * nDomY + j) = Domain(1, 200000 + i * nDomY + j + 1); - if(j == static_cast< unsigned int >(nDomY) - 1) sigmaE_N(index, (i+1) * nDomY + j) = Domain(1, 250000 + i * nDomY + j + 1); - - if(j != 0) pmlE_S(index, (i+1) * nDomY + j) = Domain(1, 150000 + i * nDomY + j + 1); - if(j != static_cast< unsigned int >(nDomY) - 1) pmlE_N(index, (i+1) * nDomY + j) = Domain(1, 300000 + i * nDomY + j + 1); - - topology[index].push_back((i+1) * nDomY + j); - } - - if(j != 0) { - sigmaS(index, i * nDomY + (j-1)) = Domain(1, 10000 + i * nDomY + j + 1); - - if(i == 0) sigmaS_W(index, i * nDomY + (j-1)) = Domain(1, 100000 + i * nDomY + j + 1); - if(i == static_cast< unsigned int >(nDomX) - 1) sigmaS_E(index, i * nDomY + (j-1)) = Domain(1, 150000 + i * nDomY + j + 1); - - if(i != 0) pmlS_W(index, i * nDomY + (j-1)) = Domain(1, 450000 + i * nDomY + j + 1); - if(i != static_cast< unsigned int >(nDomX) - 1) pmlS_E(index, i * nDomY + (j-1)) = Domain(1, 200000 + i * nDomY + j + 1); - - topology[index].push_back(i * nDomY + (j-1)); - } - if(j != static_cast< unsigned int >(nDomY) - 1) { - sigmaN(index, i * nDomY + (j+1)) = Domain(1, 30000 + i * nDomY + j + 1); - - if(i == static_cast< unsigned int >(nDomX) - 1) sigmaN_E(index, i * nDomY + (j+1)) = Domain(1, 300000 + i * nDomY + j + 1); - if(i == 0) sigmaN_W(index, i * nDomY + (j+1)) = Domain(1, 350000 + i * nDomY + j + 1); - - if(i != static_cast< unsigned int >(nDomX) - 1) pmlN_E(index, i * nDomY + (j+1)) = Domain(1, 250000 + i * nDomY + j + 1); - if(i != 0) pmlN_W(index, i * nDomY + (j+1)) = Domain(1, 400000 + i * nDomY + j + 1); - - topology[index].push_back(i * nDomY + (j+1)); - } - } - } - - // Create resolution - Resolution< std::complex< double > > resolution("DDM"); - - // Create DDM formulation - FormulationDDM< std::complex< double > > formulation("Helmholtz", resolution, topology); - - // Create fields - SubdomainField< std::complex< double >, Form::Form0 > u(resolution, "u", omega | gammaDir | pmlS | pmlE | pmlN | pmlW | pmlSE | pmlNE | pmlNW | pmlSW, FunctionSpaceType::Lagrange); - SubdomainField< std::complex< double >, Form::Form0 > lambda(resolution, "lambda", gammaDir, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > gS(resolution, "gS", sigmaS | sigmaS_W | sigmaS_E, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > gE(resolution, "gE", sigmaE | sigmaE_S | sigmaE_N, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > gN(resolution, "gN", sigmaN | sigmaN_E | sigmaN_W, FunctionSpaceType::Lagrange); - InterfaceField< std::complex< double >, Form::Form0 > gW(resolution, "gW", sigmaW | sigmaW_N | sigmaW_S, FunctionSpaceType::Lagrange); - - std::complex< double > im(0., 1.); - AnalyticalFunction< helmholtz2D::SoftScatteringByACylinder< std::complex< double > > > solution(k, circleSize, xSize / 2., ySize / 2., 2 * k); - - // Tell to the formulation that g is field that have to be exchanged between subdomains - formulation.addInterfaceField(gS); - formulation.addInterfaceField(gE); - formulation.addInterfaceField(gN); - formulation.addInterfaceField(gW); - - // Add terms to the formulation - for(unsigned int i = 0; i < nDom; ++i) { - // Compute PML parameters - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaS = abs(y< std::complex< double > >() - (y< std::complex< double > >(omega(i)) - ySize / 2.)); - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaE = abs(x< std::complex< double > >() - (x< std::complex< double > >(omega(i)) + xSize / 2.)); - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaN = abs(y< std::complex< double > >() - (y< std::complex< double > >(omega(i)) + ySize / 2.)); - gmshfem::function::ScalarFunction< std::complex< double > > distSigmaW = abs(x< std::complex< double > >() - (x< std::complex< double > >(omega(i)) - xSize / 2.)); - - gmshfem::function::ScalarFunction< std::complex< double > > sigS = 1. / (pmlSize - distSigmaS) - 1./ pmlSize; - gmshfem::function::ScalarFunction< std::complex< double > > sigE = 1. / (pmlSize - distSigmaE) - 1./ pmlSize; - gmshfem::function::ScalarFunction< std::complex< double > > sigN = 1. / (pmlSize - distSigmaN) - 1./ pmlSize; - gmshfem::function::ScalarFunction< std::complex< double > > sigW = 1. / (pmlSize - distSigmaW) - 1./ pmlSize; - - gmshfem::function::ScalarFunction< std::complex< double > > kyS = 1. + im * sigS / k; - gmshfem::function::ScalarFunction< std::complex< double > > kxE = 1. + im * sigE / k; - gmshfem::function::ScalarFunction< std::complex< double > > kyN = 1. + im * sigN / k; - gmshfem::function::ScalarFunction< std::complex< double > > kxW = 1. + im * sigW / k; - - gmshfem::function::TensorFunction< std::complex< double > > DS = tensorDiag< std::complex< double > >(kyS, 1. / kyS, kyS); - gmshfem::function::ScalarFunction< std::complex< double > > ES = kyS; - - gmshfem::function::TensorFunction< std::complex< double > > DE = tensorDiag< std::complex< double > >(1. / kxE, kxE, kxE); - gmshfem::function::ScalarFunction< std::complex< double > > EE = kxE; - - gmshfem::function::TensorFunction< std::complex< double > > DN = tensorDiag< std::complex< double > >(kyN, 1. / kyN, kyN); - gmshfem::function::ScalarFunction< std::complex< double > > EN = kyN; - - gmshfem::function::TensorFunction< std::complex< double > > DW = tensorDiag< std::complex< double > >(1. / kxW, kxW, kxW); - gmshfem::function::ScalarFunction< std::complex< double > > EW = kxW; - - // VOLUME TERMS - - formulation(i).integral(grad(dof(u(i))), grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(- k * k * dof(u(i)), tf(u(i)), omega(i), gauss); - - // Physical source - formulation(i).integral(dof(lambda(i)), tf(u(i)), gammaDir(i), gauss); - formulation(i).integral(dof(u(i)), tf(lambda(i)), gammaDir(i), gauss); - formulation(i).integral(formulation.physicalSource(-solution), tf(lambda(i)), gammaDir(i), gauss); - - // S - formulation(i).integral(DS * grad(dof(u(i))), grad(tf(u(i))), pmlS(i), gauss); - formulation(i).integral(- ES * k * k * dof(u(i)), tf(u(i)), pmlS(i), gauss); - - // E - formulation(i).integral(DE * grad(dof(u(i))), grad(tf(u(i))), pmlE(i), gauss); - formulation(i).integral(- EE * k * k * dof(u(i)), tf(u(i)), pmlE(i), gauss); - - // N - formulation(i).integral(DN * grad(dof(u(i))), grad(tf(u(i))), pmlN(i), gauss); - formulation(i).integral(- EN * k * k * dof(u(i)), tf(u(i)), pmlN(i), gauss); - - // W - formulation(i).integral(DW * grad(dof(u(i))), grad(tf(u(i))), pmlW(i), gauss); - formulation(i).integral(- EW * k * k * dof(u(i)), tf(u(i)), pmlW(i), gauss); - - // SE - formulation(i).integral(DS * DE * grad(dof(u(i))), grad(tf(u(i))), pmlSE(i), gauss); - formulation(i).integral(- ES * EE * k * k * dof(u(i)), tf(u(i)), pmlSE(i), gauss); - - // NE - formulation(i).integral(DN * DE * grad(dof(u(i))), grad(tf(u(i))), pmlNE(i), gauss); - formulation(i).integral(- EN * EE * k * k * dof(u(i)), tf(u(i)), pmlNE(i), gauss); - - // NW - formulation(i).integral(DN * DW * grad(dof(u(i))), grad(tf(u(i))), pmlNW(i), gauss); - formulation(i).integral(- EN * EW * k * k * dof(u(i)), tf(u(i)), pmlNW(i), gauss); - - // SW - formulation(i).integral(DS * DW * grad(dof(u(i))), grad(tf(u(i))), pmlSW(i), gauss); - formulation(i).integral(- ES * EW * k * k * dof(u(i)), tf(u(i)), pmlSW(i), gauss); - - // Artificial sources - for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { - const unsigned int j = topology[i][jj]; - if(!sigmaS(i,j).isEmpty()) formulation(i).integral(formulation.artificialSource( -gN(j,i) ), tf(u(i)), sigmaS(i,j) | sigmaS_W(i,j) | sigmaS_E(i,j), gauss); - if(!sigmaE(i,j).isEmpty()) formulation(i).integral(formulation.artificialSource( -gW(j,i) ), tf(u(i)), sigmaE(i,j) | sigmaE_S(i,j) | sigmaE_N(i,j), gauss); - if(!sigmaN(i,j).isEmpty()) formulation(i).integral(formulation.artificialSource( -gS(j,i) ), tf(u(i)), sigmaN(i,j) | sigmaN_E(i,j) | sigmaN_W(i,j), gauss); - if(!sigmaW(i,j).isEmpty()) formulation(i).integral(formulation.artificialSource( -gE(j,i) ), tf(u(i)), sigmaW(i,j) | sigmaW_N(i,j) | sigmaW_S(i,j), gauss); - } - - // INTERFACE TERMS - for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { - const unsigned int j = topology[i][jj]; - // S - if(!sigmaS(i,j).isEmpty()) { - formulation(i,j).integral(dof(gS(i,j)), tf(gS(i,j)), sigmaS(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gN(j,i) ), tf(gS(i,j)), sigmaS(i,j), gauss); - - formulation(i,j).integral(dof(gS(i,j)), tf(gS(i,j)), sigmaS_W(i,j) | sigmaS_E(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gN(j,i) ), tf(gS(i,j)), sigmaS_W(i,j) | sigmaS_E(i,j), gauss); - - if(!pmlS_W(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gE(i - nDomY,i) ), tf(gS(i,j)), pmlS_W(i,j), gauss); - if(!pmlS_E(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gW(i + nDomY,i) ), tf(gS(i,j)), pmlS_E(i,j), gauss); - - formulation(i,j).integral(- 2. * DS * grad(u(i)), grad(tf(gS(i,j))), pmlS(i), gauss); - formulation(i,j).integral(2. * ES * k * k * u(i), tf(gS(i,j)), pmlS(i), gauss); - - formulation(i,j).integral(- 2. * DS * DW * grad(u(i)), grad(tf(gS(i,j))), pmlSW(i), gauss); - formulation(i,j).integral(2. * ES * EW * k * k * u(i), tf(gS(i,j)), pmlSW(i), gauss); - - formulation(i,j).integral(- 2. * DS * DE * grad(u(i)), grad(tf(gS(i,j))), pmlSE(i), gauss); - formulation(i,j).integral(2. * ES * EE * k * k * u(i), tf(gS(i,j)), pmlSE(i), gauss); - } - - // E - if(!sigmaE(i,j).isEmpty()) { - formulation(i,j).integral(dof(gE(i,j)), tf(gE(i,j)), sigmaE(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gW(j,i) ), tf(gE(i,j)), sigmaE(i,j), gauss); - - formulation(i,j).integral(dof(gE(i,j)), tf(gE(i,j)), sigmaE_S(i,j) | sigmaE_N(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gW(j,i) ), tf(gE(i,j)), sigmaE_S(i,j) | sigmaE_N(i,j), gauss); - - if(!pmlE_S(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gN(i - 1,i) ), tf(gE(i,j)), pmlE_S(i,j), gauss); - if(!pmlE_N(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gS(i + 1,i) ), tf(gE(i,j)), pmlE_N(i,j), gauss); - - formulation(i,j).integral(- 2. * DE * grad(u(i)), grad(tf(gE(i,j))), pmlE(i), gauss); - formulation(i,j).integral(2. * EE * k * k * u(i), tf(gE(i,j)), pmlE(i), gauss); - - formulation(i,j).integral(- 2. * DS * DE * grad(u(i)), grad(tf(gE(i,j))), pmlSE(i), gauss); - formulation(i,j).integral(2. * ES * EE * k * k * u(i), tf(gE(i,j)), pmlSE(i), gauss); - - formulation(i,j).integral(- 2. * DN * DE * grad(u(i)), grad(tf(gE(i,j))), pmlNE(i), gauss); - formulation(i,j).integral(2. * EN * EE * k * k * u(i), tf(gE(i,j)), pmlNE(i), gauss); - } - - // N - if(!sigmaN(i,j).isEmpty()) { - formulation(i,j).integral(dof(gN(i,j)), tf(gN(i,j)), sigmaN(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gS(j,i) ), tf(gN(i,j)), sigmaN(i,j), gauss); - - formulation(i,j).integral(dof(gN(i,j)), tf(gN(i,j)), sigmaN_E(i,j) | sigmaN_W(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gS(j,i) ), tf(gN(i,j)), sigmaN_E(i,j) | sigmaN_W(i,j), gauss); - - if(!pmlN_E(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gW(i + nDomY,i) ), tf(gN(i,j)), pmlN_E(i,j), gauss); - if(!pmlN_W(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gE(i - nDomY,i) ), tf(gN(i,j)), pmlN_W(i,j), gauss); - - formulation(i,j).integral(- 2. * DN * grad(u(i)), grad(tf(gN(i,j))), pmlN(i), gauss); - formulation(i,j).integral(2. * EN * k * k * u(i), tf(gN(i,j)), pmlN(i), gauss); - - formulation(i,j).integral(- 2. * DN * DE * grad(u(i)), grad(tf(gN(i,j))), pmlNE(i), gauss); - formulation(i,j).integral(2. * EN * EE * k * k * u(i), tf(gN(i,j)), pmlNE(i), gauss); - - formulation(i,j).integral(- 2. * DN * DW * grad(u(i)), grad(tf(gN(i,j))), pmlNW(i), gauss); - formulation(i,j).integral(2. * EN * EW * k * k * u(i), tf(gN(i,j)), pmlNW(i), gauss); - } - - // W - if(!sigmaW(i,j).isEmpty()) { - formulation(i,j).integral(dof(gW(i,j)), tf(gW(i,j)), sigmaW(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gE(j,i) ), tf(gW(i,j)), sigmaW(i,j), gauss); - - formulation(i,j).integral(dof(gW(i,j)), tf(gW(i,j)), sigmaW_N(i,j) | sigmaW_S(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gE(j,i) ), tf(gW(i,j)), sigmaW_N(i,j) | sigmaW_S(i,j), gauss); - - if(!pmlW_N(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gS(i + 1,i) ), tf(gW(i,j)), pmlW_N(i,j), gauss); - if(!pmlW_S(i,j).isEmpty()) formulation(i,j).integral(formulation.artificialSource( 2. * gN(i - 1,i) ), tf(gW(i,j)), pmlW_S(i,j), gauss); - - formulation(i,j).integral(- 2. * DW * grad(u(i)), grad(tf(gW(i,j))), pmlW(i), gauss); - formulation(i,j).integral(2. * EW * k * k * u(i), tf(gW(i,j)), pmlW(i), gauss); - - formulation(i,j).integral(- 2. * DN * DW * grad(u(i)), grad(tf(gW(i,j))), pmlNW(i), gauss); - formulation(i,j).integral(2. * EN * EW * k * k * u(i), tf(gW(i,j)), pmlNW(i), gauss); - - formulation(i,j).integral(- 2. * DS * DW * grad(u(i)), grad(tf(gW(i,j))), pmlSW(i), gauss); - formulation(i,j).integral(2. * ES * EW * k * k * u(i), tf(gW(i,j)), pmlSW(i), gauss); - } - } - } - - // Solve the DDM formulation - formulation.pre(); - formulation.solve("gmres"); - - if(errorMono) { - gmshfem::domain::Domain omegaMono, pmlSMono, pmlEMono, pmlNMono, pmlWMono, pmlSEMono, pmlNEMono, pmlNWMono, pmlSWMono; - for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { - omegaMono |= omega(i); - } - - for(unsigned int i = 0; i < static_cast< unsigned int >(nDomX); ++i) { - pmlSMono |= pmlS(i * nDomY + 0); - pmlNMono |= pmlN(i * nDomY + nDomY - 1); - } - for(unsigned int j = 0; j < static_cast< unsigned int >(nDomY); ++j) { - pmlEMono |= pmlE((nDomX - 1) * nDomY + j); - pmlWMono |= pmlW(0 * nDomY + j); - } - pmlSEMono = pmlSE((nDomX - 1) * nDomY + 0); - pmlNEMono = pmlNE((nDomX - 1) * nDomY + nDomY - 1); - pmlNWMono = pmlNW(0 * nDomY + nDomY - 1); - pmlSWMono = pmlSW(0); - - gmshfem::function::TensorFunction< std::complex< double > > DSmono = getPmlDParameter(k, pmlSize, 0., false); - gmshfem::function::TensorFunction< std::complex< double > > DEmono = getPmlDParameter(k, pmlSize, nDomX * xSize, true); - gmshfem::function::TensorFunction< std::complex< double > > DNmono = getPmlDParameter(k, pmlSize, nDomY * ySize, false); - gmshfem::function::TensorFunction< std::complex< double > > DWmono = getPmlDParameter(k, pmlSize, 0., true); - - gmshfem::function::ScalarFunction< std::complex< double > > ESmono = getPmlEParameter(k, pmlSize, 0., false); - gmshfem::function::ScalarFunction< std::complex< double > > EEmono = getPmlEParameter(k, pmlSize, nDomX * xSize, true); - gmshfem::function::ScalarFunction< std::complex< double > > ENmono = getPmlEParameter(k, pmlSize, nDomY * ySize, false); - gmshfem::function::ScalarFunction< std::complex< double > > EWmono = getPmlEParameter(k, pmlSize, 0., true); - - gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > uMono(resolution, "uMono", gammaDir(circlePosX * nDomY + circlePosY) | omegaMono | pmlSMono | pmlEMono | pmlNMono | pmlWMono | pmlSEMono | pmlNEMono | pmlNWMono | pmlSWMono, FunctionSpaceType::Lagrange); - gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambdaMono(resolution, "lambdaMono", gammaDir(circlePosX * nDomY + circlePosY), FunctionSpaceType::Lagrange); - - Formulation< std::complex< double > > monodomain("HelmholtzMono", resolution); - - monodomain.integral(grad(dof(uMono)), grad(tf(uMono)), omegaMono, gauss); - monodomain.integral(- k * k * dof(uMono), tf(uMono), omegaMono, gauss); - - monodomain.integral(dof(lambdaMono), tf(uMono), gammaDir(circlePosX * nDomY + circlePosY), gauss); - monodomain.integral(dof(uMono), tf(lambdaMono), gammaDir(circlePosX * nDomY + circlePosY), gauss); - monodomain.integral(- solution, tf(lambdaMono), gammaDir(circlePosX * nDomY + circlePosY), gauss); - - monodomain.integral(DSmono * grad(dof(uMono)), grad(tf(uMono)), pmlSMono, gauss); - monodomain.integral(- k * k * ESmono * dof(uMono), tf(uMono), pmlSMono, gauss); - - monodomain.integral(DEmono * grad(dof(uMono)), grad(tf(uMono)), pmlEMono, gauss); - monodomain.integral(- k * k * EEmono * dof(uMono), tf(uMono), pmlEMono, gauss); - - monodomain.integral(DNmono * grad(dof(uMono)), grad(tf(uMono)), pmlNMono, gauss); - monodomain.integral(- k * k * ENmono * dof(uMono), tf(uMono), pmlNMono, gauss); - - monodomain.integral(DWmono * grad(dof(uMono)), grad(tf(uMono)), pmlWMono, gauss); - monodomain.integral(- k * k * EWmono * dof(uMono), tf(uMono), pmlWMono, gauss); - - monodomain.integral(DSmono * DEmono * grad(dof(uMono)), grad(tf(uMono)), pmlSEMono, gauss); - monodomain.integral(- k * k * ESmono * EEmono * dof(uMono), tf(uMono), pmlSEMono, gauss); - - monodomain.integral(DNmono * DEmono * grad(dof(uMono)), grad(tf(uMono)), pmlNEMono, gauss); - monodomain.integral(- k * k * ENmono * EEmono * dof(uMono), tf(uMono), pmlNEMono, gauss); - - monodomain.integral(DNmono * DWmono * grad(dof(uMono)), grad(tf(uMono)), pmlNWMono, gauss); - monodomain.integral(- k * k * ENmono * EWmono * dof(uMono), tf(uMono), pmlNWMono, gauss); - - monodomain.integral(DSmono * DWmono * grad(dof(uMono)), grad(tf(uMono)), pmlSWMono, gauss); - monodomain.integral(- k * k * ESmono * EWmono * dof(uMono), tf(uMono), pmlSWMono, gauss); - - monodomain.pre(); - monodomain.assemble(); - monodomain.solve(); - - save(uMono); - - for(unsigned int i = 0; i < nDom; ++i) { - save(uMono - u(i), omega(i), "eMono_" + std::to_string(i)); - } - - // L2 error - double num = 0., den = 0.; - for(unsigned int i = 0; i < nDom; ++i) { - std::complex< double > denLocal = integrate(pow(abs(uMono), 2), omega(i), gauss); - std::complex< double > numLocal = integrate(pow(abs(uMono - u(i)), 2), omega(i), gauss); - num += numLocal.real(); - den += denLocal.real(); - } - msg::info << "L2 mono domain error = " << std::sqrt(num / den) << msg::endl; - } - - for(unsigned int i = 0; i < nDom; ++i) { - save(+u(i), omega(i), "u_" + std::to_string(i)); - save(solution - u(i), omega(i), "e_" + std::to_string(i)); - for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { - const unsigned int j = topology[i][jj]; - if(!sigmaS(i,j).isEmpty()) save(gS(i,j)); - if(!sigmaE(i,j).isEmpty()) save(gE(i,j)); - if(!sigmaN(i,j).isEmpty()) save(gN(i,j)); - if(!sigmaW(i,j).isEmpty()) save(gW(i,j)); - } - } - - return 0; -} - -gmshfem::function::TensorFunction< std::complex< double > > getPmlDParameter(const double k, const double pmlSize, const double pos, const bool onX) -{ - gmshfem::function::ScalarFunction< std::complex< double > > kx = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > ky = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > kz = 1.; - - std::complex< double > I(0., 1.); - if(onX) { - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(x< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaX = 1. / (pmlSize - distSigma) - 1./ pmlSize; - kx = 1. + I * sigmaX / k; - } - else { // onY - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(y< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaY = 1. / (pmlSize - distSigma) - 1./ pmlSize; - ky = 1. + I * sigmaY / k; - } - - return tensorDiag< std::complex< double > >(ky * kz / kx, kx * kz / ky, kx * ky / kz); -} - -gmshfem::function::ScalarFunction< std::complex< double > > getPmlEParameter(const double k, const double pmlSize, const double pos, const bool onX) -{ - gmshfem::function::ScalarFunction< std::complex< double > > kx = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > ky = 1.; - gmshfem::function::ScalarFunction< std::complex< double > > kz = 1.; - - std::complex< double > I(0., 1.); - if(onX) { - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(x< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaX = 1. / (pmlSize - distSigma) - 1./ pmlSize; - kx = 1. + I * sigmaX / k; - } - else { // onY - gmshfem::function::ScalarFunction< std::complex< double > > distSigma = abs(y< std::complex< double > >() - pos); - gmshfem::function::ScalarFunction< std::complex< double > > sigmaY = 1. / (pmlSize - distSigma) - 1./ pmlSize; - ky = 1. + I * sigmaY / k; - } - - return kx * ky * kz; -} diff --git a/demos/helmholtzflow/freefield/runTests.sh b/demos/helmholtzflow/freefield/runTests.sh deleted file mode 100644 index 8b4741f0..00000000 --- a/demos/helmholtzflow/freefield/runTests.sh +++ /dev/null @@ -1,19 +0,0 @@ -cd build -cmake .. && make - -echo "****************************" -echo " zeroth order TC " -echo "****************************" -./demo -transmission T0 -alpha 0 -M 0.8 -echo "****************************" -echo " zeroth order TC with rotation " -echo "****************************" -./demo -transmission T0 -alpha -1 -M 0.8 -echo "****************************" -echo " second order TC with rotation " -echo "****************************" -./demo -transmission T2 -alpha -1 -M 0.8 -echo "****************************" -echo " Pade TC with rotation " -echo "****************************" -./demo -transmission Pade -padeOrder 4 -alpha -1 -M 0.8 diff --git a/demos/navier/scattering/CMakeLists.txt b/demos/navier/scattering/CMakeLists.txt deleted file mode 100755 index 4d2e4b0c..00000000 --- a/demos/navier/scattering/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -cmake_minimum_required(VERSION 3.0 FATAL_ERROR) - -project(demo CXX) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../demos.cmake) - -add_executable(demo main.cpp ${EXTRA_INCS}) -target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/examples/.clang-format b/examples/.clang-format new file mode 100644 index 00000000..d902ab97 --- /dev/null +++ b/examples/.clang-format @@ -0,0 +1,112 @@ +--- +Language: Cpp +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^"(?!gmsh\.h"|petsc\.h"|Eigen")' + Priority: 2 + - Regex: '"gmsh.h"|"petsc.h"|"Eigen"' + Priority: 3 + - Regex: '^<' + Priority: 4 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: false +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: true +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..a3b6e79a --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,14 @@ +set(EXAMPLES + helmholtz/checkerboard_bcgs + helmholtz/scattering/planeWaveDisk + helmholtzflow/freefield + helmholtzflow/waveguide + maxwell + navier/scattering +) + +foreach(EXAMPLE ${EXAMPLES}) + add_test(NAME "example:${EXAMPLE}:mkdir" COMMAND "${CMAKE_COMMAND}" -E make_directory build WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${EXAMPLE}) + add_test(NAME "example:${EXAMPLE}:cmake" COMMAND "${CMAKE_COMMAND}" -DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX} .. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${EXAMPLE}/build) + add_test(NAME "example:${EXAMPLE}:build" COMMAND "${CMAKE_MAKE_PROGRAM}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${EXAMPLE}/build) +endforeach() diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..82741b66 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,4 @@ +# Examples +> This directory contains the GmsmDDM research codes. + +This directory contains research codes based on GmshDDM. diff --git a/examples/README_template.md b/examples/README_template.md new file mode 100644 index 00000000..a4bf0e06 --- /dev/null +++ b/examples/README_template.md @@ -0,0 +1,23 @@ +# Project name +> author 1, author 2, ... + +Dependency(ies): +* GmshDDM : [commit hash] +* GmshFEM : [commit hash] +* ... + +## Project description + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + +## Installation + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + +## Usage + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + +## References + +Papers, proceedings, ... diff --git a/demos/demos.cmake b/examples/example.cmake similarity index 97% rename from demos/demos.cmake rename to examples/example.cmake index 38ebee16..3e2c7ef6 100644 --- a/demos/demos.cmake +++ b/examples/example.cmake @@ -50,7 +50,8 @@ if(NOT GMSHFEM_INC) message(FATAL_ERROR "Could not find GmshFEM header 'gmshfem/GmshFem.h'") endif(NOT GMSHFEM_INC) list(APPEND EXTRA_LIBS ${GMSHFEM_LIB}) -list(APPEND EXTRA_INCS ${GMSHFEM_INC}/gmshfem/) +list(APPEND EXTRA_INCS ${GMSHFEM_INC}) +list(APPEND EXTRA_INCS ${GMSHFEM_INC}/gmshfem/contrib) # Find GmshDDM find_library(GMSHDDM_LIB gmshddm) diff --git a/demos/helmholtz/waveguide/CMakeLists.txt b/examples/helmholtz/checkerboard_bcgs/CMakeLists.txt similarity index 73% rename from demos/helmholtz/waveguide/CMakeLists.txt rename to examples/helmholtz/checkerboard_bcgs/CMakeLists.txt index 4d2e4b0c..c368ce59 100644 --- a/demos/helmholtz/waveguide/CMakeLists.txt +++ b/examples/helmholtz/checkerboard_bcgs/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(demo CXX) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../demos.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake) add_executable(demo main.cpp ${EXTRA_INCS}) target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/demos/helmholtz/checkerboard_bcgs/conv_test.txt b/examples/helmholtz/checkerboard_bcgs/conv_test.txt similarity index 100% rename from demos/helmholtz/checkerboard_bcgs/conv_test.txt rename to examples/helmholtz/checkerboard_bcgs/conv_test.txt diff --git a/demos/helmholtz/checkerboard_bcgs/main.cpp b/examples/helmholtz/checkerboard_bcgs/main.cpp similarity index 82% rename from demos/helmholtz/checkerboard_bcgs/main.cpp rename to examples/helmholtz/checkerboard_bcgs/main.cpp index 69213f7a..df7859e4 100644 --- a/demos/helmholtz/checkerboard_bcgs/main.cpp +++ b/examples/helmholtz/checkerboard_bcgs/main.cpp @@ -1,10 +1,8 @@ -#include <gmshddm/GmshDdm.h> +#include <gmsh.h> #include <gmshddm/Formulation.h> - +#include <gmshddm/GmshDdm.h> #include <gmshfem/Message.h> -#include <gmsh.h> - using gmshfem::equation::dof; using gmshfem::equation::tf; using gmshfem::function::operator-; @@ -51,10 +49,10 @@ void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const doub // * * // (p0)*******(p1) int p[4]; - p[0] = gmsh::model::geo::addPoint(i * xSize, j * ySize, 0., lc); - p[1] = gmsh::model::geo::addPoint((i + 1) * xSize, j * ySize, 0., lc); + p[0] = gmsh::model::geo::addPoint(i * xSize, j * ySize, 0., lc); + p[1] = gmsh::model::geo::addPoint((i + 1) * xSize, j * ySize, 0., lc); p[2] = gmsh::model::geo::addPoint((i + 1) * xSize, (j + 1) * ySize, 0., lc); - p[3] = gmsh::model::geo::addPoint(i * xSize, (j + 1) * ySize, 0., lc); + p[3] = gmsh::model::geo::addPoint(i * xSize, (j + 1) * ySize, 0., lc); int l[4]; borders[i][j][0] = l[0] = gmsh::model::geo::addLine(p[1], p[2]); @@ -93,7 +91,6 @@ void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const doub gmsh::model::addPhysicalGroup(0, {pS}, 1); gmsh::model::setPhysicalName(0, 1, "source"); } - } } gmsh::model::geo::removeAllDuplicates(); @@ -109,16 +106,16 @@ void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const doub gmsh::model::addPhysicalGroup(2, {omega[i][j]}, i * nDomY + j + 1); gmsh::model::setPhysicalName(2, i * nDomY + j + 1, "omega_" + std::to_string(i) + "_" + std::to_string(j)); - gmsh::model::addPhysicalGroup(1, {borders[i][j][0]}, 10000 + i * nDomY + j + 1); + gmsh::model::addPhysicalGroup(1, {borders[i][j][0]}, 10000 + i * nDomY + j + 1); gmsh::model::setPhysicalName(1, 10000 + i * nDomY + j + 1, "sigmaE_" + std::to_string(i) + "_" + std::to_string(j)); - gmsh::model::addPhysicalGroup(1, {borders[i][j][1]}, 20000 + i * nDomY + j + 1); + gmsh::model::addPhysicalGroup(1, {borders[i][j][1]}, 20000 + i * nDomY + j + 1); gmsh::model::setPhysicalName(1, 20000 + i * nDomY + j + 1, "sigmaN_" + std::to_string(i) + "_" + std::to_string(j)); - gmsh::model::addPhysicalGroup(1, {borders[i][j][2]}, 30000 + i * nDomY + j + 1); + gmsh::model::addPhysicalGroup(1, {borders[i][j][2]}, 30000 + i * nDomY + j + 1); gmsh::model::setPhysicalName(1, 30000 + i * nDomY + j + 1, "sigmaW_" + std::to_string(i) + "_" + std::to_string(j)); - gmsh::model::addPhysicalGroup(1, {borders[i][j][3]}, 40000 + i * nDomY + j + 1); + gmsh::model::addPhysicalGroup(1, {borders[i][j][3]}, 40000 + i * nDomY + j + 1); gmsh::model::setPhysicalName(1, 40000 + i * nDomY + j + 1, "sigmaS_" + std::to_string(i) + "_" + std::to_string(j)); } } @@ -175,27 +172,27 @@ int main(int argc, char **argv) omega(index) = gmshfem::domain::Domain(2, index + 1); for(unsigned int f = 0; f < 4; ++f) { - sigma[f](index) = gmshfem::domain::Domain(1, (f+1) * 10000 + i * nDomY + j + 1); + sigma[f](index) = gmshfem::domain::Domain(1, (f + 1) * 10000 + i * nDomY + j + 1); } if(i != static_cast< unsigned int >(nDomX) - 1) { // E - sigmaInterface[0](index, (i+1) * nDomY + j) = sigma[0](index); - topology[index].push_back((i+1) * nDomY + j); + sigmaInterface[0](index, (i + 1) * nDomY + j) = sigma[0](index); + topology[index].push_back((i + 1) * nDomY + j); } if(j != static_cast< unsigned int >(nDomY) - 1) { // N - sigmaInterface[1](index, i * nDomY + (j+1)) = sigma[1](index); - topology[index].push_back(i * nDomY + (j+1)); + sigmaInterface[1](index, i * nDomY + (j + 1)) = sigma[1](index); + topology[index].push_back(i * nDomY + (j + 1)); } if(i != 0) { // W - sigmaInterface[2](index, (i-1) * nDomY + j) = sigma[2](index); - topology[index].push_back((i-1) * nDomY + j); + sigmaInterface[2](index, (i - 1) * nDomY + j) = sigma[2](index); + topology[index].push_back((i - 1) * nDomY + j); } if(j != 0) { // S - sigmaInterface[3](index, i * nDomY + (j-1)) = sigma[3](index); - topology[index].push_back(i * nDomY + (j-1)); + sigmaInterface[3](index, i * nDomY + (j - 1)) = sigma[3](index); + topology[index].push_back(i * nDomY + (j - 1)); } } } @@ -208,7 +205,7 @@ int main(int argc, char **argv) gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambda("lambda", gamma, gmshfem::field::FunctionSpaceTypeForm0::Lagrange); - const std::vector< std::string > orientation {"E", "N", "W", "S"}; + const std::vector< std::string > orientation{"E", "N", "W", "S"}; std::vector< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > > g; g.reserve(4); for(unsigned int f = 0; f < 4; ++f) { @@ -229,7 +226,7 @@ int main(int argc, char **argv) if(i == sourcePosX * nDomY + sourcePosY) { formulation(i).integral(dof(lambda), tf(u(i)), gamma, gauss); formulation(i).integral(dof(u(i)), tf(lambda), gamma, gauss); - formulation(i).integral(formulation.physicalSource(- 1.), tf(lambda), gamma, gauss); + formulation(i).integral(formulation.physicalSource(-1.), tf(lambda), gamma, gauss); } // boundary @@ -245,8 +242,8 @@ int main(int argc, char **argv) for(unsigned int f = 0; f < 4; ++f) { for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - if(!sigmaInterface[f](i,j).isEmpty()) { - formulation(i).integral(formulation.artificialSource( - g[(f+2)%4](j,i) ), tf(u(i)), sigmaInterface[f](i,j), gauss); + if(!sigmaInterface[f](i, j).isEmpty()) { + formulation(i).integral(formulation.artificialSource(-g[(f + 2) % 4](j, i)), tf(u(i)), sigmaInterface[f](i, j), gauss); } } } @@ -255,11 +252,10 @@ int main(int argc, char **argv) for(unsigned int f = 0; f < 4; ++f) { for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - if(!sigmaInterface[f](i,j).isEmpty()) { - formulation(i,j).integral(dof(g[f](i,j)), tf(g[f](i,j)), sigmaInterface[f](i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( g[(f+2)%4](j,i) ), tf(g[f](i,j)), sigmaInterface[f](i,j), gauss); - formulation(i,j).integral(2. * v[f](i), tf(g[f](i,j)), sigmaInterface[f](i,j), gauss); - + if(!sigmaInterface[f](i, j).isEmpty()) { + formulation(i, j).integral(dof(g[f](i, j)), tf(g[f](i, j)), sigmaInterface[f](i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(g[(f + 2) % 4](j, i)), tf(g[f](i, j)), sigmaInterface[f](i, j), gauss); + formulation(i, j).integral(2. * v[f](i), tf(g[f](i, j)), sigmaInterface[f](i, j), gauss); } } } diff --git a/demos/helmholtz/scattering/planeWaveDisk/CMakeLists.txt b/examples/helmholtz/scattering/planeWaveDisk/CMakeLists.txt similarity index 72% rename from demos/helmholtz/scattering/planeWaveDisk/CMakeLists.txt rename to examples/helmholtz/scattering/planeWaveDisk/CMakeLists.txt index f01d5714..78dcc127 100644 --- a/demos/helmholtz/scattering/planeWaveDisk/CMakeLists.txt +++ b/examples/helmholtz/scattering/planeWaveDisk/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(demo CXX) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../demos.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../example.cmake) add_executable(demo main.cpp ${EXTRA_INCS}) target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/demos/helmholtz/scattering/planeWaveDisk/main.cpp b/examples/helmholtz/scattering/planeWaveDisk/main.cpp similarity index 70% rename from demos/helmholtz/scattering/planeWaveDisk/main.cpp rename to examples/helmholtz/scattering/planeWaveDisk/main.cpp index c58ab829..22f639c6 100644 --- a/demos/helmholtz/scattering/planeWaveDisk/main.cpp +++ b/examples/helmholtz/scattering/planeWaveDisk/main.cpp @@ -1,8 +1,10 @@ -#include <gmshddm/GmshDdm.h> +#include "gmsh.h" + #include <gmshddm/Formulation.h> -#include <gmshfem/Message.h> +#include <gmshddm/GmshDdm.h> +#include <gmshddm/MPIInterface.h> #include <gmshfem/AnalyticalFunction.h> -#include "gmsh.h" +#include <gmshfem/Message.h> using namespace gmshddm; using namespace gmshddm::common; @@ -27,20 +29,20 @@ void circlesConcentric(const unsigned int nDom, const double r0, const double rI } gmsh::model::add("circlesConcentric"); - std::vector< int > tagsCircle(nDom+2); + std::vector< int > tagsCircle(nDom + 2); for(unsigned int i = 0; i <= nDom; ++i) { tagsCircle[i] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt(double(i * (rInf * rInf - r0 * r0)) / nDom + r0 * r0)); } - tagsCircle[nDom+1] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt(double( nDom * (rPml * rPml - r0 * r0)) / nDom + r0 * r0)); + tagsCircle[nDom + 1] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt(double(nDom * (rPml * rPml - r0 * r0)) / nDom + r0 * r0)); std::vector< int > tagsCurve(nDom + 2); - for(unsigned int i = 0; i <= (nDom+1); ++i) { + for(unsigned int i = 0; i <= (nDom + 1); ++i) { tagsCurve[i] = gmsh::model::occ::addCurveLoop({tagsCircle[i]}); } - - std::vector< int > tagsSurface(nDom+1); + + std::vector< int > tagsSurface(nDom + 1); for(unsigned int i = 0; i <= nDom; ++i) { - tagsSurface[i] = gmsh::model::occ::addPlaneSurface({tagsCurve[i], tagsCurve[i+1]}); + tagsSurface[i] = gmsh::model::occ::addPlaneSurface({tagsCurve[i], tagsCurve[i + 1]}); } gmsh::model::occ::synchronize(); @@ -50,24 +52,24 @@ void circlesConcentric(const unsigned int nDom, const double r0, const double rI gmsh::model::addPhysicalGroup(1, {tagsCircle[nDom]}, 92); gmsh::model::setPhysicalName(1, 92, "gammaInf"); - - gmsh::model::addPhysicalGroup(1, {tagsCircle[nDom+1]}, 93); + + gmsh::model::addPhysicalGroup(1, {tagsCircle[nDom + 1]}, 93); gmsh::model::setPhysicalName(1, 93, "gammaPml"); - + for(unsigned int i = 0; i < nDom; ++i) { - gmsh::model::addPhysicalGroup(2, {tagsCircle[i]}, i+1); - gmsh::model::setPhysicalName(2, i+1, "omega_" + std::to_string(i)); + gmsh::model::addPhysicalGroup(2, {tagsCircle[i]}, i + 1); + gmsh::model::setPhysicalName(2, i + 1, "omega_" + std::to_string(i)); if(i != nDom - 1) { - gmsh::model::addPhysicalGroup(1, {tagsCircle[i+1]}, 200 + i); + gmsh::model::addPhysicalGroup(1, {tagsCircle[i + 1]}, 200 + i); gmsh::model::setPhysicalName(1, 200 + i, "sigma_" + std::to_string(i)); } } gmsh::model::addPhysicalGroup(2, {tagsCircle[nDom]}, 1 + nDom); gmsh::model::setPhysicalName(2, 1 + nDom, "omega_pml"); - + std::vector< std::pair< int, int > > out; gmsh::model::getEntities(out, 0); gmsh::model::mesh::setSize(out, lc); @@ -81,21 +83,19 @@ int main(int argc, char **argv) unsigned int nDom = 3; //gmshDdm.userDefinedParameter(nDom, "nDom"); - unsigned int MPI_Size = getSize_MPI(); - unsigned int MPI_Rank = getRank_MPI(); - + double rInf = 5.; double r0 = 1; double lc = 0.1; int Npml = 4; - double rPml = rInf+Npml*lc; - + double rPml = rInf + Npml * lc; + gmshDdm.userDefinedParameter(rInf, "rInf"); gmshDdm.userDefinedParameter(r0, "r0"); gmshDdm.userDefinedParameter(lc, "lc"); - - int FEMorder = 3; + + int FEMorder = 3; std::string gauss = "Gauss10"; gmshDdm.userDefinedParameter(gauss, "gauss"); @@ -103,7 +103,7 @@ int main(int argc, char **argv) // transmission conditions std::string Transmission = "Taylor2"; gmshDdm.userDefinedParameter(Transmission, "transmission"); - double alpha = pi/4.; + double alpha = pi / 4.; gmshDdm.userDefinedParameter(alpha, "alpha"); msg::info << " Transmission condition " << Transmission << " with rotation alpha = " << alpha << msg::endl; // Build geometry and mesh using gmsh API @@ -112,16 +112,16 @@ int main(int argc, char **argv) // Define domain Subdomain omega(nDom); Subdomain gammaPml(nDom); - Subdomain gammaInf(nDom); + Subdomain gammaInf(nDom); Subdomain gammaScat(nDom); Interface sigma(nDom); for(unsigned int i = 0; i < nDom; ++i) { // ddm entities - - if(i == (nDom - 1) ) { + + if(i == (nDom - 1)) { gammaPml(i) = Domain(1, 93); gammaInf(i) = Domain(1, 92); - omega(i) = ( Domain(2, i+1) | Domain (2, i+2) ); + omega(i) = (Domain(2, i + 1) | Domain(2, i + 2)); } else { omega(i) = Domain(2, i + 1); @@ -154,15 +154,15 @@ int main(int argc, char **argv) gmshddm::problem::Formulation< std::complex< double > > formulation("helmholtz", topology); double w = 2 * pi; - double theta = pi/3.; + double theta = pi / 3.; // Create fields SubdomainField< std::complex< double >, Form::Form0 > u("u", omega | gammaScat | gammaPml | sigma, FunctionSpaceTypeForm0::HierarchicalH1, FEMorder); InterfaceField< std::complex< double >, Form::Form0 > g("g", sigma, FunctionSpaceTypeForm0::HierarchicalH1, FEMorder); Function< std::complex< double >, Degree::Degree0 > *solution = nullptr; - - solution = new AnalyticalFunction< helmholtz2D::ScatteringByASoftCylinder< std::complex< double > > >(w, r0, 0., 0., 2*w, theta); + + solution = new AnalyticalFunction< helmholtz2D::ScatteringByASoftCylinder< std::complex< double > > >(w, r0, 0., 0., 2 * w, theta); for(unsigned int i = 0; i < nDom; ++i) { // physical source constraint u(i).addConstraint(gammaScat(i), *solution); @@ -170,15 +170,15 @@ int main(int argc, char **argv) solution->activateMemorization(); ScalarFunction< std::complex< double > > S, dS; - if ( Transmission == "Taylor0" ) { - S = -im*w*exp(im*alpha/2.); + if(Transmission == "Taylor0") { + S = -im * w * exp(im * alpha / 2.); dS = 0.; } - else if ( Transmission == "Taylor2" ) { - S = -im*w*cos(alpha/2.); - dS = -im*exp(-im*alpha/2.0)/(2.0*w); + else if(Transmission == "Taylor2") { + S = -im * w * cos(alpha / 2.); + dS = -im * exp(-im * alpha / 2.0) / (2.0 * w); } - + // add interface field formulation.addInterfaceField(g); @@ -186,25 +186,25 @@ int main(int argc, char **argv) const double WPml = rPml - rInf; ScalarFunction< std::complex< double > > cosT = x< std::complex< double > >() / r2d< std::complex< double > >(); ScalarFunction< std::complex< double > > sinT = y< std::complex< double > >() / r2d< std::complex< double > >(); - ScalarFunction< std::complex< double > > dampingProfileR = heaviside( abs(r2d< std::complex< double > >()) - rInf ) / (WPml - (r2d< std::complex< double > >() - rInf)); - ScalarFunction< std::complex< double > > dampingProfileInt = - heaviside( abs(r2d< std::complex< double > >()) - rInf ) * ln((WPml - (r2d< std::complex< double > >() - rInf)) / WPml); + ScalarFunction< std::complex< double > > dampingProfileR = heaviside(abs(r2d< std::complex< double > >()) - rInf) / (WPml - (r2d< std::complex< double > >() - rInf)); + ScalarFunction< std::complex< double > > dampingProfileInt = -heaviside(abs(r2d< std::complex< double > >()) - rInf) * ln((WPml - (r2d< std::complex< double > >() - rInf)) / WPml); ScalarFunction< std::complex< double > > cR = 1. + im * dampingProfileR / w; ScalarFunction< std::complex< double > > cStretch = 1. + im * (1. / r2d< std::complex< double > >()) * dampingProfileInt / w; ScalarFunction< std::complex< double > > S_PML = cR * cStretch; - TensorFunction< std::complex< double > > D = tensor< std::complex <double > >(cStretch / cR * cosT * cosT + cR / cStretch * sinT * sinT, - cStretch / cR * cosT * sinT - cR / cStretch * cosT * sinT, - 0., - cStretch / cR * cosT * sinT - cR / cStretch * cosT * sinT, - cStretch / cR * sinT * sinT + cR / cStretch * cosT * cosT, - 0., - 0., 0., 0.); + TensorFunction< std::complex< double > > D = tensor< std::complex< double > >(cStretch / cR * cosT * cosT + cR / cStretch * sinT * sinT, + cStretch / cR * cosT * sinT - cR / cStretch * cosT * sinT, + 0., + cStretch / cR * cosT * sinT - cR / cStretch * cosT * sinT, + cStretch / cR * sinT * sinT + cR / cStretch * cosT * cosT, + 0., + 0., 0., 0.); // Add terms to the formulation for(unsigned int i = 0; i < nDom; ++i) { // VOLUME TERMS - if ( i == (nDom -1) ) { // pre-processing is slower with the PML formulation + if(i == (nDom - 1)) { // pre-processing is slower with the PML formulation formulation(i).integral(D * grad(dof(u(i))), grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(- w * w * S_PML * dof(u(i)), tf(u(i)), omega(i), gauss); + formulation(i).integral(-w * w * S_PML * dof(u(i)), tf(u(i)), omega(i), gauss); } else { formulation(i).integral(grad(dof(u(i))), grad(tf(u(i))), omega(i), gauss); @@ -213,18 +213,18 @@ int main(int argc, char **argv) // Artificial source for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(S * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(- dS * grad( dof(u(i)) ), grad( tf(u(i)) ) , sigma(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -g(j,i) ), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(S * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(-dS * grad(dof(u(i))), grad(tf(u(i))), sigma(i, j), gauss); + formulation(i).integral(formulation.artificialSource(-g(j, i)), tf(u(i)), sigma(i, j), gauss); } // INTERFACE TERMS for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i,j).integral(dof(g(i,j)), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( g(j,i) ), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(-2.0 * S * u(i), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(2.0 * dS * grad( u(i) ), grad ( tf(g(i,j)) ), sigma(i,j), gauss); + formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(g(j, i)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-2.0 * S * u(i), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2.0 * dS * grad(u(i)), grad(tf(g(i, j))), sigma(i, j), gauss); } } @@ -235,14 +235,14 @@ int main(int argc, char **argv) gmshDdm.userDefinedParameter(maxIter, "maxIter"); formulation.pre(); formulation.solve("gmres", tolerence, maxIter); - + // L2 error double num = 0., den = 0.; Subdomain omega_err(nDom); for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { - if ( i % MPI_Size == MPI_Rank ) { - omega_err(i) = Domain (2, i + 1); - save(+u(i), omega(i),"u_"+std::to_string(i)); + if(gmshddm::mpi::isItMySubdomain(i)) { + omega_err(i) = Domain(2, i + 1); + save(+u(i), omega(i), "u_" + std::to_string(i)); save(*solution, omega_err(i), "uex_" + std::to_string(i)); save(*solution - u(i), omega_err(i), "err_" + std::to_string(i)); diff --git a/demos/helmholtz/checkerboard_bcgs/CMakeLists.txt b/examples/helmholtzflow/freefield/CMakeLists.txt similarity index 73% rename from demos/helmholtz/checkerboard_bcgs/CMakeLists.txt rename to examples/helmholtzflow/freefield/CMakeLists.txt index 4d2e4b0c..c368ce59 100644 --- a/demos/helmholtz/checkerboard_bcgs/CMakeLists.txt +++ b/examples/helmholtzflow/freefield/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(demo CXX) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../demos.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake) add_executable(demo main.cpp ${EXTRA_INCS}) target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/demos/helmholtzflow/freefield/main.cpp b/examples/helmholtzflow/freefield/main.cpp similarity index 63% rename from demos/helmholtzflow/freefield/main.cpp rename to examples/helmholtzflow/freefield/main.cpp index 373429a6..36a41a07 100644 --- a/demos/helmholtzflow/freefield/main.cpp +++ b/examples/helmholtzflow/freefield/main.cpp @@ -1,8 +1,9 @@ -#include <gmshddm/GmshDdm.h> -#include <gmshddm/Formulation.h> -#include <gmshfem/Message.h> #include "gmsh.h" + +#include <gmshddm/Formulation.h> +#include <gmshddm/GmshDdm.h> #include <gmshfem/AnalyticalFunction.h> +#include <gmshfem/Message.h> using namespace gmshddm; using namespace gmshddm::common; @@ -37,9 +38,9 @@ void circlesConcentric(const unsigned int nDom, const double rInf, const double std::vector< int > tagsCircle(nDom + 1); for(unsigned int i = 0; i < nDom; ++i) { - tagsCircle[i] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt(double( (i+1) * (rInf * rInf)) / nDom )); + tagsCircle[i] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt(double((i + 1) * (rInf * rInf)) / nDom)); } - tagsCircle[nDom] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt( double(rPml * rPml) ) ); + tagsCircle[nDom] = gmsh::model::occ::addCircle(0., 0., 0., std::sqrt(double(rPml * rPml))); std::vector< int > tagsCurve(nDom + 1); for(unsigned int i = 0; i < (nDom + 1); ++i) { @@ -48,12 +49,12 @@ void circlesConcentric(const unsigned int nDom, const double rInf, const double std::vector< int > tagsSurface(nDom + 1); tagsSurface[0] = gmsh::model::occ::addPlaneSurface({tagsCurve[0]}); - for(unsigned int i = 1; i < (nDom+1); ++i) { - tagsSurface[i] = gmsh::model::occ::addPlaneSurface({tagsCurve[i-1], tagsCurve[i]}); + for(unsigned int i = 1; i < (nDom + 1); ++i) { + tagsSurface[i] = gmsh::model::occ::addPlaneSurface({tagsCurve[i - 1], tagsCurve[i]}); } gmsh::model::occ::synchronize(); - gmsh::model::mesh::embed(0,{tagPoint},2,1); + gmsh::model::mesh::embed(0, {tagPoint}, 2, 1); for(unsigned int i = 0; i < nDom; ++i) { gmsh::model::addPhysicalGroup(2, {tagsCircle[i]}, 100 + i); @@ -65,7 +66,7 @@ void circlesConcentric(const unsigned int nDom, const double rInf, const double } } - gmsh::model::addPhysicalGroup(1, {tagsCircle[nDom-1]}, 92); + gmsh::model::addPhysicalGroup(1, {tagsCircle[nDom - 1]}, 92); gmsh::model::setPhysicalName(1, 92, "gammaInf"); gmsh::model::addPhysicalGroup(1, {tagsCircle[nDom]}, 93); @@ -95,18 +96,18 @@ int main(int argc, char **argv) unsigned int nDom = 5; // gmshDdm.userDefinedParameter(nDom, "nDom"); const double pi = 3.14159265358979323846264338327950288; - + // geometry parameters double r0 = 2.; double lc = 0.07; - double rPML = r0+4.*lc; + double rPML = r0 + 4. * lc; gmshDdm.userDefinedParameter(rPML, "rPML"); gmshDdm.userDefinedParameter(r0, "r0"); gmshDdm.userDefinedParameter(lc, "lc"); // souce point location double xs = -0.1; double ys = 0.2; - + // numerical parameters int FEMorder = 4; gmshDdm.userDefinedParameter(FEMorder, "FEMorder"); @@ -133,13 +134,13 @@ int main(int argc, char **argv) if(i == (nDom - 1)) { gammaPml(i) = Domain(1, 93); gammaInf(i) = Domain(1, 92); - omega(i) = ( Domain(2, i + 100) | Domain (2, 100 + i + 1) ); + omega(i) = (Domain(2, i + 100) | Domain(2, 100 + i + 1)); } else { omega(i) = Domain(2, i + 100); } - if ( i == 0 ) { + if(i == 0) { source(i) = Domain(0, 999); } @@ -167,30 +168,30 @@ int main(int argc, char **argv) const std::complex< double > im(0., 1.); double M = 0.5; // Mach number gmshDdm.userDefinedParameter(M, "M"); - double theta = pi/3.; // mean flow orientation + double theta = pi / 3.; // mean flow orientation msg::info << "Mach number " << M << " theta " << theta << msg::endl; - double Mx = M*std::cos(theta); - double My = M*std::sin(theta); + double Mx = M * std::cos(theta); + double My = M * std::sin(theta); // Parameters for Inverse Lorentz transformation - double beta = sqrt(1-M*M); // Jacobian - double Alphax = 1 + Mx*Mx/(beta*(1+beta)); - double Alphay = 1 + My*My/(beta*(1+beta)); - double K = Mx*My/(beta*(1+beta)); + double beta = sqrt(1 - M * M); // Jacobian + double Alphax = 1 + Mx * Mx / (beta * (1 + beta)); + double Alphay = 1 + My * My / (beta * (1 + beta)); + double K = Mx * My / (beta * (1 + beta)); // Inverse Lorentz transformation - TensorFunction< std::complex< double > > Linv = tensor< std::complex <double > > (beta*Alphay, -beta*K, 0., -beta*K, beta*Alphax,0.,0.,0.,0.); + TensorFunction< std::complex< double > > Linv = tensor< std::complex< double > >(beta * Alphay, -beta * K, 0., -beta * K, beta * Alphax, 0., 0., 0., 0.); // Mach-velocity vector - VectorFunction< std::complex< double > > MM = vector< std::complex< double > > (Mx,My,0.); - ScalarFunction< std::complex< double > > Mn = MM*normal< std::complex< double > >(); - ScalarFunction< std::complex< double > > Mt = MM*tangent< std::complex< double > >(); - ScalarFunction< std::complex< double > > beta_n = sqrt(1-Mn*Mn); // Jacobian + VectorFunction< std::complex< double > > MM = vector< std::complex< double > >(Mx, My, 0.); + ScalarFunction< std::complex< double > > Mn = MM * normal< std::complex< double > >(); + ScalarFunction< std::complex< double > > Mt = MM * tangent< std::complex< double > >(); + ScalarFunction< std::complex< double > > beta_n = sqrt(1 - Mn * Mn); // Jacobian // Transmission condition ScalarFunction< std::complex< double > > Si, Sj, Sti, Stj, dS; - float pointsByWl = ( 2*pi*FEMorder*( 1 - abs(M) ) ) / (lc*k); + float pointsByWl = (2 * pi * FEMorder * (1 - abs(M))) / (lc * k); msg::info << " - FEM basis order = " << FEMorder << "" << msg::endl; msg::info << " - Minimum number of dofs by wavelength = " << pointsByWl << msg::endl; @@ -207,7 +208,7 @@ int main(int argc, char **argv) Function< std::complex< double >, Degree::Degree0 > *solution = nullptr; solution = new AnalyticalFunction< helmholtz2D::MonopoleFreeField< std::complex< double > > >(k, M, theta, 1., xs, ys, 0., 0.); solution->activateMemorization(); - + // PML parameters double Sigma0 = beta; ScalarFunction< std::complex< double > > det_J; @@ -216,104 +217,104 @@ int main(int argc, char **argv) ScalarFunction< std::complex< double > > cosT = x< std::complex< double > >() / r2d< std::complex< double > >(); ScalarFunction< std::complex< double > > sinT = y< std::complex< double > >() / r2d< std::complex< double > >(); - ScalarFunction< std::complex< double > > dampingProfileR = Sigma0*heaviside( abs(r2d< std::complex< double > >()) - r0 ) / (Wpml - (r2d< std::complex< double > >() - r0)); - ScalarFunction< std::complex< double > > dampingProfileInt = -Sigma0*heaviside( abs(r2d< std::complex< double > >()) - r0 ) * ln((Wpml - (r2d< std::complex< double > >() - r0)) / Wpml); + ScalarFunction< std::complex< double > > dampingProfileR = Sigma0 * heaviside(abs(r2d< std::complex< double > >()) - r0) / (Wpml - (r2d< std::complex< double > >() - r0)); + ScalarFunction< std::complex< double > > dampingProfileInt = -Sigma0 * heaviside(abs(r2d< std::complex< double > >()) - r0) * ln((Wpml - (r2d< std::complex< double > >() - r0)) / Wpml); ScalarFunction< std::complex< double > > gamma = 1. - im * dampingProfileR / k; ScalarFunction< std::complex< double > > gamma_hat = 1. - im * (1. / r2d< std::complex< double > >()) * dampingProfileInt / k; det_J = gamma * gamma_hat; - J_PML_inv_T = tensor< std::complex <double > >(cosT/gamma,sinT/gamma,0.,-sinT/gamma_hat,cosT/gamma_hat,0.,0.,0.,0.); + J_PML_inv_T = tensor< std::complex< double > >(cosT / gamma, sinT / gamma, 0., -sinT / gamma_hat, cosT / gamma_hat, 0., 0., 0., 0.); // build vector and matrix for the weak form VectorFunction< std::complex< double > > J_PML_inv_T_M = J_PML_inv_T * MM; - TensorFunction< std::complex< double > > J_PML_Linv = J_PML_inv_T * Linv; + TensorFunction< std::complex< double > > J_PML_Linv = J_PML_inv_T * Linv; msg::info << "Use a PML as radiation condition - circular stable formulation" << msg::endl; for(unsigned int i = 0; i < nDom; ++i) { // VOLUME TERMS - if ( i != (nDom - 1) ) { + if(i != (nDom - 1)) { // convected Helmholz weak form - formulation(i).integral(vector< std::complex< double > >(1-Mx*Mx, -Mx*My, 0.) * grad(dof(u(i))), vector< std::complex< double > >(1., 0., 0.) * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(vector< std::complex< double > >(-Mx*My, 1-My*My, 0.) * grad(dof(u(i))), vector< std::complex< double > >(0., 1., 0.) * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(dof(u(i)), vector< std::complex< double > >(-im*k*Mx,-im*k*My, 0.) * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(vector< std::complex< double > >(im*k*Mx, im*k*My, 0.) * grad(dof(u(i))), tf(u(i)), omega(i), gauss); - formulation(i).integral(- k * k * dof(u(i)), tf(u(i)), omega(i), gauss); + formulation(i).integral(vector< std::complex< double > >(1 - Mx * Mx, -Mx * My, 0.) * grad(dof(u(i))), vector< std::complex< double > >(1., 0., 0.) * grad(tf(u(i))), omega(i), gauss); + formulation(i).integral(vector< std::complex< double > >(-Mx * My, 1 - My * My, 0.) * grad(dof(u(i))), vector< std::complex< double > >(0., 1., 0.) * grad(tf(u(i))), omega(i), gauss); + formulation(i).integral(dof(u(i)), vector< std::complex< double > >(-im * k * Mx, -im * k * My, 0.) * grad(tf(u(i))), omega(i), gauss); + formulation(i).integral(vector< std::complex< double > >(im * k * Mx, im * k * My, 0.) * grad(dof(u(i))), tf(u(i)), omega(i), gauss); + formulation(i).integral(-k * k * dof(u(i)), tf(u(i)), omega(i), gauss); } else { // convected Helmholz weak form with PML - formulation(i).integral( det_J * J_PML_Linv*grad(dof(u(i))) , J_PML_Linv*grad(tf(u(i))) , omega(i), gauss); + formulation(i).integral(det_J * J_PML_Linv * grad(dof(u(i))), J_PML_Linv * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(+ k*k/(beta*beta) * det_J * J_PML_inv_T_M * dof(u(i)) , J_PML_inv_T_M * tf(u(i)), omega(i), gauss); - formulation(i).integral(+ im*k/beta* det_J * J_PML_Linv * grad(dof(u(i))), J_PML_inv_T_M * tf(u(i)), omega(i), gauss); + formulation(i).integral(+k * k / (beta * beta) * det_J * J_PML_inv_T_M * dof(u(i)), J_PML_inv_T_M * tf(u(i)), omega(i), gauss); + formulation(i).integral(+im * k / beta * det_J * J_PML_Linv * grad(dof(u(i))), J_PML_inv_T_M * tf(u(i)), omega(i), gauss); - formulation(i).integral(- im*k/beta* det_J * J_PML_inv_T_M * dof(u(i)), J_PML_Linv * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(- k*k/(beta*beta) * det_J * dof(u(i)), tf(u(i)), omega(i), gauss); + formulation(i).integral(-im * k / beta * det_J * J_PML_inv_T_M * dof(u(i)), J_PML_Linv * grad(tf(u(i))), omega(i), gauss); + formulation(i).integral(-k * k / (beta * beta) * det_J * dof(u(i)), tf(u(i)), omega(i), gauss); } // point source formulation(i).integral(formulation.physicalSource(-1.), tf(u(i)), source(i), gauss); - + // Artificial source - Zeroth order transmission condition for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(formulation.artificialSource( -g(j,i) ), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(formulation.artificialSource(-g(j, i)), tf(u(i)), sigma(i, j), gauss); // Contribution from the boundary terms - formulation(i).integral( (im*k*Mn) * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(Mn * Mt * tangent< std::complex< double > >() * grad( dof(u(i)) ), dof(u(i)), sigma(i,j), gauss); + formulation(i).integral((im * k * Mn) * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(Mn * Mt * tangent< std::complex< double > >() * grad(dof(u(i))), dof(u(i)), sigma(i, j), gauss); } // Interface weak form for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i,j).integral(dof(g(i,j)), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( g(j,i) ), tf(g(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(g(j, i)), tf(g(i, j)), sigma(i, j), gauss); } - if ( transmission == "T0" ) { - Si = im*k*(exp(im*alpha/2.)-Mn); // alpha=0, beta*beta*Si = i*k*(1-Mn) - Sti = - Mn * Mt; - Sj = im*k*(exp(im*alpha/2.)+Mn); + if(transmission == "T0") { + Si = im * k * (exp(im * alpha / 2.) - Mn); // alpha=0, beta*beta*Si = i*k*(1-Mn) + Sti = -Mn * Mt; + Sj = im * k * (exp(im * alpha / 2.) + Mn); for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral( Si * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral( Sti * tangent< std::complex< double > >() * grad( dof(u(i)) ), dof(u(i)), sigma(i,j), gauss); - formulation(i,j).integral(- (Si+Sj) * u(i) , tf(g(i,j)), sigma(i,j), gauss); - } + formulation(i).integral(Si * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(Sti * tangent< std::complex< double > >() * grad(dof(u(i))), dof(u(i)), sigma(i, j), gauss); + formulation(i, j).integral(-(Si + Sj) * u(i), tf(g(i, j)), sigma(i, j), gauss); + } } - else if ( transmission == "T2" ) { - Si = im*k*(cos(alpha/2.)-Mn) ; - Sj = im*k*(cos(alpha/2.)+Mn) ; - Sti = ( exp(-im*alpha/2.) - Mn ) * Mt ; - Stj = ( exp(-im*alpha/2.) + Mn ) * Mt ; - dS = im*(beta*beta)*exp(-im*alpha/2.) / (2.0*k); - + else if(transmission == "T2") { + Si = im * k * (cos(alpha / 2.) - Mn); + Sj = im * k * (cos(alpha / 2.) + Mn); + Sti = (exp(-im * alpha / 2.) - Mn) * Mt; + Stj = (exp(-im * alpha / 2.) + Mn) * Mt; + dS = im * (beta * beta) * exp(-im * alpha / 2.) / (2.0 * k); + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral( Si * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral( Sti * tangent< std::complex< double > >() * grad( dof(u(i)) ), dof(u(i)), sigma(i,j), gauss); - formulation(i).integral(- dS * grad( dof(u(i)) ), grad( tf(u(i)) ), sigma(i,j), gauss); - - formulation(i,j).integral(- (Si+Sj) * u(i) , tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(- (Sti+Stj) * tangent< std::complex< double > >() * grad( u(i) ) , tf(g(i,j)), sigma(i,j), gauss); - - formulation(i,j).integral( 2. * dS * grad( u(i) ), grad( tf(g(i,j)) ), sigma(i,j), gauss); + formulation(i).integral(Si * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(Sti * tangent< std::complex< double > >() * grad(dof(u(i))), dof(u(i)), sigma(i, j), gauss); + formulation(i).integral(-dS * grad(dof(u(i))), grad(tf(u(i))), sigma(i, j), gauss); + + formulation(i, j).integral(-(Si + Sj) * u(i), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-(Sti + Stj) * tangent< std::complex< double > >() * grad(u(i)), tf(g(i, j)), sigma(i, j), gauss); + + formulation(i, j).integral(2. * dS * grad(u(i)), grad(tf(g(i, j))), sigma(i, j), gauss); } } - else if ( transmission == "Pade" ) { + else if(transmission == "Pade") { int padeOrder = 2; gmshDdm.userDefinedParameter(padeOrder, "padeOrder"); const double Np = 2. * padeOrder + 1.; - const std::complex< double > exp1 = std::complex<double>(std::cos(alpha),std::sin(alpha)); - const std::complex< double > exp2 = std::complex<double>(std::cos(alpha/2.),std::sin(alpha/2.)); - const std::complex< double > coef = 2./Np; - + const std::complex< double > exp1 = std::complex< double >(std::cos(alpha), std::sin(alpha)); + const std::complex< double > exp2 = std::complex< double >(std::cos(alpha / 2.), std::sin(alpha / 2.)); + const std::complex< double > coef = 2. / Np; + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral( im * k * exp2 * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(- (im*Mn*k) * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(- Mn*Mt * tangent< std::complex< double > >() * grad( dof(u(i)) ), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(im * k * exp2 * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(-(im * Mn * k) * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(-Mn * Mt * tangent< std::complex< double > >() * grad(dof(u(i))), tf(u(i)), sigma(i, j), gauss); // interface unknowns - formulation(i,j).integral(-2.*(im * k * exp2) * u(i), tf(g(i,j)), sigma(i,j), gauss); - + formulation(i, j).integral(-2. * (im * k * exp2) * u(i), tf(g(i, j)), sigma(i, j), gauss); + // define Pade coefficients std::vector< std::complex< double > > c(padeOrder, 0.); for(int l = 0; l < padeOrder; ++l) { @@ -322,27 +323,27 @@ int main(int argc, char **argv) } // define the auxiliary fields - std::vector< Field< std::complex< double >, Form::Form0 >* > phi; + std::vector< Field< std::complex< double >, Form::Form0 > * > phi; for(int l = 0; l < padeOrder; ++l) { - phi.push_back(new Field< std::complex< double >, Form::Form0 >("phi_" + std::to_string(l), sigma(i,j), FunctionSpaceTypeForm0::HierarchicalH1, FEMorder)); + phi.push_back(new Field< std::complex< double >, Form::Form0 >("phi_" + std::to_string(l), sigma(i, j), FunctionSpaceTypeForm0::HierarchicalH1, FEMorder)); fieldBucket.push_back(phi.back()); } - + // write the augmented weak form for(int l = 0; l < padeOrder; ++l) { // boundary integral terms relating the auxiliary fields - formulation(i).integral(im * k * exp2 * coef * c[l] * dof(*phi[l]), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(im * k * exp2 * coef * c[l] * dof(u(i)), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(im * k * exp2 * coef * c[l] * dof(*phi[l]), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(im * k * exp2 * coef * c[l] * dof(u(i)), tf(u(i)), sigma(i, j), gauss); // coupling of the auxiliary equations - formulation(i).integral(- (beta*beta) * grad(dof(*phi[l])), grad(tf(*phi[l])), sigma(i,j), gauss); - formulation(i).integral(- 2. * im * k * Mt * tangent< std::complex< double > >() * grad(dof(*phi[l])), tf(*phi[l]), sigma(i,j), gauss); - formulation(i).integral( (k*k) * (exp1 * c[l] + 1.) * dof(*phi[l]), tf(*phi[l]), sigma(i,j), gauss); - formulation(i).integral( (k*k) * exp1 * (c[l] + 1.) * dof(u(i)), tf(*phi[l]), sigma(i,j), gauss); + formulation(i).integral(-(beta * beta) * grad(dof(*phi[l])), grad(tf(*phi[l])), sigma(i, j), gauss); + formulation(i).integral(-2. * im * k * Mt * tangent< std::complex< double > >() * grad(dof(*phi[l])), tf(*phi[l]), sigma(i, j), gauss); + formulation(i).integral((k * k) * (exp1 * c[l] + 1.) * dof(*phi[l]), tf(*phi[l]), sigma(i, j), gauss); + formulation(i).integral((k * k) * exp1 * (c[l] + 1.) * dof(u(i)), tf(*phi[l]), sigma(i, j), gauss); } // interfaces unknowns for(int l = 0; l < padeOrder; ++l) { - formulation(i,j).integral(- 2. * (im * k * exp2) * coef * c[l] * (*phi[l]), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(- 2. * (im * k * exp2) * coef * c[l] * u(i), tf(g(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(-2. * (im * k * exp2) * coef * c[l] * (*phi[l]), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-2. * (im * k * exp2) * coef * c[l] * u(i), tf(g(i, j)), sigma(i, j), gauss); } } } @@ -355,8 +356,8 @@ int main(int argc, char **argv) double num = 0., den = 0.; // L2 error Subdomain omega_err(nDom); for(unsigned int i = 0; i < nDom; ++i) { - omega_err(i) = Domain(2, i+100); - save(+u(i), omega(i),"u_"+std::to_string(i)); + omega_err(i) = Domain(2, i + 100); + save(+u(i), omega(i), "u_" + std::to_string(i)); save(*solution, omega_err(i), "uex_" + std::to_string(i)); save(*solution - u(i), omega_err(i), "err_" + std::to_string(i)); diff --git a/examples/helmholtzflow/freefield/runTests.sh b/examples/helmholtzflow/freefield/runTests.sh new file mode 100644 index 00000000..5486cd76 --- /dev/null +++ b/examples/helmholtzflow/freefield/runTests.sh @@ -0,0 +1,7 @@ +cd build + cmake..&&make + + echo "****************************" echo " zeroth order TC " echo "****************************" + ./ + demo - + transmission T0 - alpha 0 - M 0.8 echo "****************************" echo " zeroth order TC with rotation " echo "****************************"./ demo - transmission T0 - alpha - 1 - M 0.8 echo "****************************" echo " second order TC with rotation " echo "****************************"./ demo - transmission T2 - alpha - 1 - M 0.8 echo "****************************" echo " Pade TC with rotation " echo "****************************"./ demo - transmission Pade - padeOrder 4 - alpha - 1 - M 0.8 diff --git a/demos/helmholtzflow/freefield/CMakeLists.txt b/examples/helmholtzflow/waveguide/CMakeLists.txt similarity index 73% rename from demos/helmholtzflow/freefield/CMakeLists.txt rename to examples/helmholtzflow/waveguide/CMakeLists.txt index 4d2e4b0c..c368ce59 100644 --- a/demos/helmholtzflow/freefield/CMakeLists.txt +++ b/examples/helmholtzflow/waveguide/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(demo CXX) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../demos.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake) add_executable(demo main.cpp ${EXTRA_INCS}) target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/demos/helmholtzflow/waveguide/main.cpp b/examples/helmholtzflow/waveguide/main.cpp similarity index 64% rename from demos/helmholtzflow/waveguide/main.cpp rename to examples/helmholtzflow/waveguide/main.cpp index 34e495ea..454510b8 100644 --- a/demos/helmholtzflow/waveguide/main.cpp +++ b/examples/helmholtzflow/waveguide/main.cpp @@ -1,10 +1,11 @@ -#include <gmshddm/GmshDdm.h> #include <gmshddm/Formulation.h> +#include <gmshddm/GmshDdm.h> +#include <gmshddm/MPIInterface.h> #include <gmshfem/Message.h> // #include "mpi.h" // #include "petscsys.h" -#include "gmsh.h" -#include "AnalyticalFunction.h" +#include <gmsh.h> +#include <gmshfem/AnalyticalFunction.h> using namespace gmshddm; using namespace gmshddm::common; @@ -81,21 +82,16 @@ int main(int argc, char **argv) { GmshDdm gmshDdm(argc, argv); - // rank and size - unsigned int MPI_Rank = getRank_MPI(); - unsigned int MPI_Size = getSize_MPI(); - printf("I am processor of rank %d out of %d processes \n", MPI_Rank, MPI_Size); - double pi = 3.14159265359; int nDom = 4; gmshDdm.userDefinedParameter(nDom, "nDom"); - + // duct geometry parameters double L = 0.5; double H = 0.25; - double lc = sqrt(L*H)/(40.0); + double lc = sqrt(L * H) / (40.0); gmshDdm.userDefinedParameter(lc, "lc"); - + // upper wall boundary condition std::string wallType = "hard"; gmshDdm.userDefinedParameter(wallType, "wallType"); @@ -104,33 +100,31 @@ int main(int argc, char **argv) double k = 70; gmshDdm.userDefinedParameter(k, "k"); int mode = 3; - double ky = mode*pi/H; - + double ky = mode * pi / H; + // relative Mach number double M = 0.8; gmshDdm.userDefinedParameter(M, "M"); - double beta = sqrt(1-M*M); - double beta2 = beta*beta; - + double beta = sqrt(1 - M * M); + double beta2 = beta * beta; + // transmission conditions std::string Transmission = "DtN"; gmshDdm.userDefinedParameter(Transmission, "transmission"); // init transmission operators ScalarFunction< std::complex< double > > Si, Sj, dS; - double alpha=0.; // rotation branch-cut, in [0, -pi] + double alpha = 0.; // rotation branch-cut, in [0, -pi] gmshDdm.userDefinedParameter(alpha, "alpha"); - if ( MPI_Rank == 0 ) { - if (Transmission != "DtN") { - msg::info << " use " << Transmission << " as transmission condition with alpha = " << alpha << msg::endl; - } - else { - msg::info << " use analytical DtN as transmission condition " << msg::endl; - } - if ( wallType == "soft" && Transmission == "Pade" ) { - msg::error << "Pade condition not available yet for Dirichlet wall " << msg::endl; - } + if(Transmission != "DtN") { + msg::info << " use " << Transmission << " as transmission condition with alpha = " << alpha << msg::endl; + } + else { + msg::info << " use analytical DtN as transmission condition " << msg::endl; + } + if(wallType == "soft" && Transmission == "Pade") { + msg::error << "Pade condition not available yet for Dirichlet wall " << msg::endl; } - + // numerical parameters int FEMorder = 4; gmshDdm.userDefinedParameter(FEMorder, "FEMorder"); @@ -139,7 +133,7 @@ int main(int argc, char **argv) // Build geometry and mesh using gmsh API // for the moment all the procs do the meshing - waveguide(nDom, H, L, lc); + waveguide(nDom, H, L, lc); // Define domain Subdomain omega(nDom); @@ -150,7 +144,7 @@ int main(int argc, char **argv) for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { omega(i) = Domain(2, i + 1); - if(i == (static_cast< unsigned int >(nDom-1)) ) { + if(i == (static_cast< unsigned int >(nDom - 1))) { gammaInf(i) = Domain(1, 2); // outgoing boundary } @@ -162,7 +156,7 @@ int main(int argc, char **argv) if(i != 0) { sigma(i, i - 1) = Domain(1, 200 + i - 1); } - if(i != (static_cast< unsigned int >(nDom-1)) ) { + if(i != (static_cast< unsigned int >(nDom - 1))) { sigma(i, i + 1) = Domain(1, 200 + i); } } @@ -174,9 +168,9 @@ int main(int argc, char **argv) if(i != 0) { topology[i].push_back(i - 1); } - if(i != (static_cast< unsigned int >(nDom-1)) ) { + if(i != (static_cast< unsigned int >(nDom - 1))) { topology[i].push_back(i + 1); - } + } } // Create DDM formulation @@ -186,15 +180,15 @@ int main(int argc, char **argv) // Create fields SubdomainField< std::complex< double >, Form::Form0 > u("u", omega | gammaDir | gammaInf | border | sigma, FunctionSpaceTypeForm0::HierarchicalH1, FEMorder); InterfaceField< std::complex< double >, Form::Form0 > g("g", sigma, FunctionSpaceTypeForm0::HierarchicalH1, FEMorder); - + // define analytical solution Function< std::complex< double >, Degree::Degree0 > *solution = nullptr; - if ( wallType == "hard" ) { + if(wallType == "hard") { solution = new AnalyticalFunction< helmholtz2D::DuctModeSolution< std::complex< double > > >(k, M, H, 0., 0., mode, 0); } - else if ( wallType == "soft" ) { + else if(wallType == "soft") { solution = new AnalyticalFunction< helmholtz2D::DuctModeSolution< std::complex< double > > >(k, M, H, 0., 0., mode, 1); - for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { + for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { u(i).addConstraint(border(i), 0.); } } @@ -202,124 +196,118 @@ int main(int argc, char **argv) std::complex< double > im(0., 1.); std::complex< double > kx; // propagative wavenumber - double Argsqrt = k*k-beta2*ky*ky; - if (Argsqrt >= 0) { - kx = (1/(beta2))*(-M*k + sqrt(Argsqrt)); - if ( MPI_Rank == 0 ) { - msg::info << " propagative mode " << msg::endl; - } + double Argsqrt = k * k - beta2 * ky * ky; + if(Argsqrt >= 0) { + kx = (1 / (beta2)) * (-M * k + sqrt(Argsqrt)); + msg::info << " propagative mode " << msg::endl; } else { - kx = (1/(beta2))*(-M*k - im*sqrt(abs(Argsqrt))); - if ( MPI_Rank == 0 ) { - msg::info << " evanescent mode " << msg::endl; - } + kx = (1 / (beta2)) * (-M * k - im * sqrt(abs(Argsqrt))); + msg::info << " evanescent mode " << msg::endl; } - if ( k>(beta*ky) && k<ky ) { + if(k > (beta * ky) && k < ky) { msg::info << " - inverse upstream mode ! " << msg::endl; } - float pointsByWl = (2*pi*FEMorder*(1+M)/k) / lc; - if ( MPI_Rank == 0 ) { - msg::info << " - Approximate dofs by wavelength = " << pointsByWl << "" << msg::endl; - msg::info << " - Mach number = " << M << "" << msg::endl; - } - + float pointsByWl = (2 * pi * FEMorder * (1 + M) / k) / lc; + msg::info << " - Approximate dofs by wavelength = " << pointsByWl << "" << msg::endl; + msg::info << " - Mach number = " << M << "" << msg::endl; + // define output absorbing boundary condition - std::complex< double > ABC = im*kx; - + std::complex< double > ABC = im * kx; + // Tell to the formulation that g is field that have to be exchanged between subdomains formulation.addInterfaceField(g); - for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { + for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { // VOLUME TERMS formulation(i).integral(vector< std::complex< double > >(beta2, 0., 0.) * grad(dof(u(i))), vector< std::complex< double > >(1., 0., 0.) * grad(tf(u(i))), omega(i), gauss); formulation(i).integral(vector< std::complex< double > >(0., 1., 0.) * grad(dof(u(i))), vector< std::complex< double > >(0., 1., 0.) * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(vector< std::complex< double > >(im*k*M, 0., 0.) * grad(dof(u(i))), tf(u(i)), omega(i), gauss); - formulation(i).integral(dof(u(i)), vector< std::complex< double > >(-im*k*M, 0., 0.) * grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(- k * k * dof(u(i)), tf(u(i)), omega(i), gauss); + formulation(i).integral(vector< std::complex< double > >(im * k * M, 0., 0.) * grad(dof(u(i))), tf(u(i)), omega(i), gauss); + formulation(i).integral(dof(u(i)), vector< std::complex< double > >(-im * k * M, 0., 0.) * grad(tf(u(i))), omega(i), gauss); + formulation(i).integral(-k * k * dof(u(i)), tf(u(i)), omega(i), gauss); // SURFACE TERMS // artificial boundary condition, use analytical DtN formulation(i).integral(beta2 * ABC * dof(u(i)), tf(u(i)), gammaInf(i), gauss); // Contribution from the mass boundary matrix - formulation(i).integral( (im*k*M) * dof(u(i)), tf(u(i)), gammaInf(i), gauss); + formulation(i).integral((im * k * M) * dof(u(i)), tf(u(i)), gammaInf(i), gauss); // Physical source - if ( wallType == "soft" ) { - formulation(i).integral(formulation.physicalSource( -im*kx*beta2*sin< std::complex< double > >(ky * y< std::complex< double > >() ) ), tf(u(i)), gammaDir(i), gauss); + if(wallType == "soft") { + formulation(i).integral(formulation.physicalSource(-im * kx * beta2 * sin< std::complex< double > >(ky * y< std::complex< double > >())), tf(u(i)), gammaDir(i), gauss); } - else if ( wallType == "hard" ) { - formulation(i).integral(formulation.physicalSource( -im*kx*beta2*cos< std::complex< double > >(ky * y< std::complex< double > >() ) ), tf(u(i)), gammaDir(i), gauss); + else if(wallType == "hard") { + formulation(i).integral(formulation.physicalSource(-im * kx * beta2 * cos< std::complex< double > >(ky * y< std::complex< double > >())), tf(u(i)), gammaDir(i), gauss); } // Contribution from the mass boundary matrix - formulation(i).integral( (-im*k*M) * dof(u(i)), tf(u(i)), gammaDir(i), gauss); + formulation(i).integral((-im * k * M) * dof(u(i)), tf(u(i)), gammaDir(i), gauss); // Artificial source for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(formulation.artificialSource( -g(j,i) ), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(formulation.artificialSource(-g(j, i)), tf(u(i)), sigma(i, j), gauss); // Contribution from the mass boundary matrix - formulation(i).integral( (im*k*M) * dof(u(i)), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral((im * k * M) * dof(u(i)), tf(u(i)), sigma(i, j), gauss); } // INTERFACE TERMS for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i,j).integral(dof(g(i,j)), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( g(j,i) ), tf(g(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(g(j, i)), tf(g(i, j)), sigma(i, j), gauss); } // Transmission condition - if ( Transmission == "Taylor0" ) { - Si = im*k*(exp(im*alpha/2.)-M)/beta2; - Sj = im*k*(exp(im*alpha/2.)+M)/beta2; + if(Transmission == "Taylor0") { + Si = im * k * (exp(im * alpha / 2.) - M) / beta2; + Sj = im * k * (exp(im * alpha / 2.) + M) / beta2; for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(beta2 * Si * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i,j).integral(- beta2 * (Si+Sj) * u(i), tf(g(i,j)), sigma(i,j), gauss); + formulation(i).integral(beta2 * Si * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i, j).integral(-beta2 * (Si + Sj) * u(i), tf(g(i, j)), sigma(i, j), gauss); } } - else if ( Transmission == "Taylor2" ) { - Si = im*k*(cos(alpha/2.)-M)/beta2; - Sj = im*k*(cos(alpha/2.)+M)/beta2; - dS = im*exp(-im*alpha/2.0)/(2.0*k); + else if(Transmission == "Taylor2") { + Si = im * k * (cos(alpha / 2.) - M) / beta2; + Sj = im * k * (cos(alpha / 2.) + M) / beta2; + dS = im * exp(-im * alpha / 2.0) / (2.0 * k); for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(beta2 * Si * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(- beta2 * dS * grad( dof(u(i)) ), grad( tf(u(i)) ), sigma(i,j), gauss); - formulation(i,j).integral(- beta2 * (Si+Sj) * u(i), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(+ beta2 * (2.*dS) * grad( u(i) ), grad( tf(g(i,j)) ), sigma(i,j), gauss); + formulation(i).integral(beta2 * Si * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(-beta2 * dS * grad(dof(u(i))), grad(tf(u(i))), sigma(i, j), gauss); + formulation(i, j).integral(-beta2 * (Si + Sj) * u(i), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(+beta2 * (2. * dS) * grad(u(i)), grad(tf(g(i, j))), sigma(i, j), gauss); } } - else if ( Transmission == "DtN" ) { // analytic DtN relative the normal of the artificial boundary, for a given mode - Si = im*kx; - Sj = im*( kx + 2*M*k/(beta2) ); // or Sj = im*( (M*k + sqrt(Argsqrt)) / beta2 ); + else if(Transmission == "DtN") { // analytic DtN relative the normal of the artificial boundary, for a given mode + Si = im * kx; + Sj = im * (kx + 2 * M * k / (beta2)); // or Sj = im*( (M*k + sqrt(Argsqrt)) / beta2 ); for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(beta2 * Si * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i,j).integral(- beta2 * (Si+Sj) * u(i), tf(g(i,j)), sigma(i,j), gauss); + formulation(i).integral(beta2 * Si * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i, j).integral(-beta2 * (Si + Sj) * u(i), tf(g(i, j)), sigma(i, j), gauss); } } - else if ( Transmission == "Pade" ) { + else if(Transmission == "Pade") { int padeOrder = 4; gmshDdm.userDefinedParameter(padeOrder, "padeOrder"); - if ( i == 0 && MPI_Rank == 0 ) { + if(i == 0) { msg::info << "Use Pade transmission condition of order " << padeOrder << msg::endl; } const double Np = 2. * padeOrder + 1.; - const std::complex< double > exp1 = std::complex<double>(std::cos(alpha),std::sin(alpha)); - const std::complex< double > exp2 = std::complex<double>(std::cos(alpha/2.),std::sin(alpha/2.)); - const std::complex< double > coef = 2./Np; - + const std::complex< double > exp1 = std::complex< double >(std::cos(alpha), std::sin(alpha)); + const std::complex< double > exp2 = std::complex< double >(std::cos(alpha / 2.), std::sin(alpha / 2.)); + const std::complex< double > coef = 2. / Np; + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral( im * k * exp2 * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(- (im*M*k) * dof(u(i)), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(im * k * exp2 * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(-(im * M * k) * dof(u(i)), tf(u(i)), sigma(i, j), gauss); // interface unknowns - formulation(i,j).integral(- 2. * (im * k * exp2) * u(i), tf(g(i,j)), sigma(i,j), gauss); - + formulation(i, j).integral(-2. * (im * k * exp2) * u(i), tf(g(i, j)), sigma(i, j), gauss); + // define Pade coefficients std::vector< std::complex< double > > c(padeOrder, 0.); for(int l = 0; l < padeOrder; ++l) { @@ -328,47 +316,46 @@ int main(int argc, char **argv) } // define the auxiliary fields - std::vector< Field< std::complex< double >, Form::Form0 >* > phi; + std::vector< Field< std::complex< double >, Form::Form0 > * > phi; for(int l = 0; l < padeOrder; ++l) { - phi.push_back(new Field< std::complex< double >, Form::Form0 >("phi_" + std::to_string(l), sigma(i,j), FunctionSpaceTypeForm0::HierarchicalH1, FEMorder)); + phi.push_back(new Field< std::complex< double >, Form::Form0 >("phi_" + std::to_string(l), sigma(i, j), FunctionSpaceTypeForm0::HierarchicalH1, FEMorder)); fieldBucket.push_back(phi.back()); } - + // write the augmented weak form for(int l = 0; l < padeOrder; ++l) { // boundary integral terms relating the auxiliary fields - formulation(i).integral(im * k * exp2 * coef * c[l] * dof(*phi[l]), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(im * k * exp2 * coef * c[l] * dof(u(i)), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(im * k * exp2 * coef * c[l] * dof(*phi[l]), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(im * k * exp2 * coef * c[l] * dof(u(i)), tf(u(i)), sigma(i, j), gauss); // coupling of the auxiliary equations - formulation(i).integral(grad(dof(*phi[l])), grad(tf(*phi[l])), sigma(i,j), gauss); - formulation(i).integral(- (k*k)/ beta2 * (exp1 * c[l] + 1.) * dof(*phi[l]), tf(*phi[l]), sigma(i,j), gauss); - formulation(i).integral(- (k*k)/ beta2 * exp1 * (c[l] + 1.) * dof(u(i)), tf(*phi[l]), sigma(i,j), gauss); + formulation(i).integral(grad(dof(*phi[l])), grad(tf(*phi[l])), sigma(i, j), gauss); + formulation(i).integral(-(k * k) / beta2 * (exp1 * c[l] + 1.) * dof(*phi[l]), tf(*phi[l]), sigma(i, j), gauss); + formulation(i).integral(-(k * k) / beta2 * exp1 * (c[l] + 1.) * dof(u(i)), tf(*phi[l]), sigma(i, j), gauss); } - + // interfaces unknowns for(int l = 0; l < padeOrder; ++l) { - formulation(i,j).integral(- 2. * (im * k * exp2) * coef * c[l] * (*phi[l]), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(- 2. * (im * k * exp2) * coef * c[l] * u(i), tf(g(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(-2. * (im * k * exp2) * coef * c[l] * (*phi[l]), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-2. * (im * k * exp2) * coef * c[l] * u(i), tf(g(i, j)), sigma(i, j), gauss); } } } - else { + else { msg::error << "Transmission condition not available !" << msg::endl; exit(0); } - } // Solve the DDM formulation formulation.pre(); - formulation.solve("jacobi",1e-6); + formulation.solve("jacobi", 1e-6); //formulation.solve("gmres"); double num = 0., den = 0.; double local_err; // L2 local error for(unsigned int i = 0; i < static_cast< unsigned int >(nDom); ++i) { - if ( i % MPI_Size == MPI_Rank ) { - save(+u(i),omega(i),"u_"+std::to_string(i)); + if(gmshddm::mpi::isItMySubdomain(i)) { + save(+u(i), omega(i), "u_" + std::to_string(i)); save(*solution, omega(i), "uex_" + std::to_string(i)); save(*solution - u(i), omega(i), "err_" + std::to_string(i)); @@ -390,7 +377,7 @@ int main(int argc, char **argv) } */ - msg::info << "Local L2 error = " << local_err << " on rank " << MPI_Rank <<msg::endl; + msg::info << "Local L2 error = " << local_err << " on rank " << gmshddm::mpi::getMPIRank() << msg::endl; for(unsigned int i = 0; i < fieldBucket.size(); ++i) { delete fieldBucket[i]; diff --git a/demos/maxwell/CMakeLists.txt b/examples/maxwell/CMakeLists.txt similarity index 74% rename from demos/maxwell/CMakeLists.txt rename to examples/maxwell/CMakeLists.txt index c7811951..14a0aa41 100644 --- a/demos/maxwell/CMakeLists.txt +++ b/examples/maxwell/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(demo CXX) -include(${CMAKE_CURRENT_SOURCE_DIR}/../demos.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../example.cmake) add_executable(demo main.cpp ${EXTRA_INCS}) target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/demos/maxwell/main.cpp b/examples/maxwell/main.cpp similarity index 70% rename from demos/maxwell/main.cpp rename to examples/maxwell/main.cpp index 7bfc3661..9b3e8c39 100644 --- a/demos/maxwell/main.cpp +++ b/examples/maxwell/main.cpp @@ -1,10 +1,9 @@ +#include "gmsh.h" + #include <gmshddm/Formulation.h> #include <gmshddm/GmshDdm.h> - #include <gmshfem/Message.h> -#include "gmsh.h" - using namespace gmshddm; using namespace gmshddm::common; using namespace gmshddm::domain; @@ -20,8 +19,9 @@ using namespace gmshfem::function; using namespace gmshfem::post; void waveguide(const unsigned int nDom, const double a, const double b, - const double L, const double lc) { - if (nDom < 2) { + const double L, const double lc) +{ + if(nDom < 2) { gmshfem::msg::error << "nDom should be at least equal to 2." << gmshfem::msg::endl; exit(0); @@ -30,9 +30,9 @@ void waveguide(const unsigned int nDom, const double a, const double b, const double domainSize = L / nDom; - std::vector<std::vector<int>> borders(nDom); - std::vector<int> omegas(nDom); - std::vector<int> sigmas(nDom - 1); + std::vector< std::vector< int > > borders(nDom); + std::vector< int > omegas(nDom); + std::vector< int > sigmas(nDom - 1); int p[4]; @@ -48,7 +48,7 @@ void waveguide(const unsigned int nDom, const double a, const double b, line[3] = gmsh::model::geo::addLine(p[3], p[0]); int curveLoop = - gmsh::model::geo::addCurveLoop({line[3], line[0], -line[1], line[2]}); + gmsh::model::geo::addCurveLoop({line[3], line[0], -line[1], line[2]}); int tagSurface = gmsh::model::geo::addPlaneSurface({curveLoop}); gmsh::model::geo::mesh::setTransfiniteSurface(tagSurface); @@ -56,11 +56,11 @@ void waveguide(const unsigned int nDom, const double a, const double b, gmsh::model::addPhysicalGroup(2, {tagSurface}, 1); gmsh::model::setPhysicalName(2, 1, "gammaDir"); - for (unsigned int i = 0; i < nDom; ++i) { - std::vector<std::pair<int, int>> extrudeEntities; + for(unsigned int i = 0; i < nDom; ++i) { + std::vector< std::pair< int, int > > extrudeEntities; gmsh::model::geo::extrude( - {std::make_pair(2, tagSurface)}, domainSize, 0., 0., extrudeEntities, - {static_cast<int>((domainSize) / lc)}, std::vector<double>(), true); + {std::make_pair(2, tagSurface)}, domainSize, 0., 0., extrudeEntities, + {static_cast< int >((domainSize) / lc)}, std::vector< double >(), true); tagSurface = extrudeEntities[0].second; omegas[i] = extrudeEntities[1].second; borders[i].push_back(extrudeEntities[2].second); @@ -73,26 +73,27 @@ void waveguide(const unsigned int nDom, const double a, const double b, gmsh::model::addPhysicalGroup(2, {tagSurface}, 2); gmsh::model::setPhysicalName(2, 2, "gammaInf"); - for (unsigned int i = 0; i < borders.size(); ++i) { + for(unsigned int i = 0; i < borders.size(); ++i) { gmsh::model::addPhysicalGroup(2, borders[i], 100 + i); gmsh::model::setPhysicalName(2, 100 + i, "border_" + std::to_string(i)); } - for (unsigned int i = 0; i < omegas.size(); ++i) { + for(unsigned int i = 0; i < omegas.size(); ++i) { gmsh::model::addPhysicalGroup(3, {omegas[i]}, i + 1); gmsh::model::setPhysicalName(3, i + 1, "omega_" + std::to_string(i)); } - for (unsigned int i = 0; i < sigmas.size(); ++i) { + for(unsigned int i = 0; i < sigmas.size(); ++i) { gmsh::model::addPhysicalGroup(2, {sigmas[i]}, 200 + i); gmsh::model::setPhysicalName( - 2, 200 + i, "sigma_" + std::to_string(i) + "_" + std::to_string(i + 1)); + 2, 200 + i, "sigma_" + std::to_string(i) + "_" + std::to_string(i + 1)); } gmsh::model::geo::synchronize(); gmsh::model::mesh::generate(); } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ GmshDdm gmshDdm(argc, argv); /**** * input Data @@ -121,34 +122,35 @@ int main(int argc, char **argv) { double ky = mode_m * pi / a; double kz = mode_n * pi / b; double kc = sqrt(ky * ky + kz * kz); - std::complex<double> im(0., 1.); - std::complex<double> beta; - if (-kc * kc + k * k >= 0) { + std::complex< double > im(0., 1.); + std::complex< double > beta; + if(-kc * kc + k * k >= 0) { beta = sqrt(-kc * kc + k * k); - } else { + } + else { beta = -im * sqrt(kc * kc - k * k); } // TM - VectorFunction<std::complex<double>> Einc = vector<std::complex<double>>( - sin<std::complex<double>>(ky * y<std::complex<double>>()) * - sin<std::complex<double>>(kz * z<std::complex<double>>()), - im * beta * ky / (kc * kc) * - cos<std::complex<double>>(ky * y<std::complex<double>>()) * - sin<std::complex<double>>(kz * z<std::complex<double>>()), - im * beta * kz / (kc * kc) * - cos<std::complex<double>>(kz * z<std::complex<double>>()) * - sin<std::complex<double>>(ky * y<std::complex<double>>())); - /**** + VectorFunction< std::complex< double > > Einc = vector< std::complex< double > >( + sin< std::complex< double > >(ky * y< std::complex< double > >()) * + sin< std::complex< double > >(kz * z< std::complex< double > >()), + im * beta * ky / (kc * kc) * + cos< std::complex< double > >(ky * y< std::complex< double > >()) * + sin< std::complex< double > >(kz * z< std::complex< double > >()), + im * beta * kz / (kc * kc) * + cos< std::complex< double > >(kz * z< std::complex< double > >()) * + sin< std::complex< double > >(ky * y< std::complex< double > >())); + /**** * FEM ****/ - if (!ddm) { - /**** + if(!ddm) { + /**** * Gmsh part ****/ gmsh::model::add("waveguide"); const double domainSize = L; - std::vector<std::vector<int>> borders(1); - std::vector<int> omegas(1); + std::vector< std::vector< int > > borders(1); + std::vector< int > omegas(1); int p[4]; p[0] = gmsh::model::geo::addPoint(0., 0, 0., lc); p[1] = gmsh::model::geo::addPoint(0, a, 0., lc); @@ -162,17 +164,17 @@ int main(int argc, char **argv) { line[3] = gmsh::model::geo::addLine(p[3], p[0]); int curveLoop = - gmsh::model::geo::addCurveLoop({line[3], line[0], -line[1], line[2]}); + gmsh::model::geo::addCurveLoop({line[3], line[0], -line[1], line[2]}); int tagSurface = gmsh::model::geo::addPlaneSurface({curveLoop}); gmsh::model::geo::mesh::setTransfiniteSurface(tagSurface); gmsh::model::geo::mesh::setRecombine(2, tagSurface); gmsh::model::addPhysicalGroup(2, {tagSurface}, 1); gmsh::model::setPhysicalName(2, 1, "gammaDir"); - std::vector<std::pair<int, int>> extrudeEntities; + std::vector< std::pair< int, int > > extrudeEntities; gmsh::model::geo::extrude( - {std::make_pair(2, tagSurface)}, domainSize, 0., 0., extrudeEntities, - {static_cast<int>((domainSize) / lc)}, std::vector<double>(), true); + {std::make_pair(2, tagSurface)}, domainSize, 0., 0., extrudeEntities, + {static_cast< int >((domainSize) / lc)}, std::vector< double >(), true); tagSurface = extrudeEntities[0].second; omegas[0] = extrudeEntities[1].second; borders[0].push_back(extrudeEntities[2].second); @@ -193,22 +195,22 @@ int main(int argc, char **argv) { Domain gammaInf(2, 2); Domain gammaDir(2, 1); Domain border(2, 100); - gmshfem::problem::Formulation<std::complex<double>> formulation("maxwell"); + gmshfem::problem::Formulation< std::complex< double > > formulation("maxwell"); /**** * Create fields ****/ - Field<std::complex<double>, Form::Form1> E( - "E", omega | gammaDir | gammaInf | border, - FunctionSpaceTypeForm1::HierarchicalHCurl, FEorder); - Field<std::complex<double>, Form::Form1> lambda( - "lambda", gammaDir , FunctionSpaceTypeForm1::HierarchicalHCurl, - FEorder); + Field< std::complex< double >, Form::Form1 > E( + "E", omega | gammaDir | gammaInf | border, + FunctionSpaceTypeForm1::HierarchicalHCurl, FEorder); + Field< std::complex< double >, Form::Form1 > lambda( + "lambda", gammaDir, FunctionSpaceTypeForm1::HierarchicalHCurl, + FEorder); // VectorFunction<std::complex<double>> n = normal<std::complex<double>>(); // VOLUME TERMS - E.addConstraint(border, vector<std::complex<double>>(0.,0.,0.)); - lambda.addConstraint(border, vector<std::complex<double>>(0.,0.,0.)); + E.addConstraint(border, vector< std::complex< double > >(0., 0., 0.)); + lambda.addConstraint(border, vector< std::complex< double > >(0., 0., 0.)); formulation.integral(curl(dof(E)), curl(tf(E)), omega, gauss); formulation.integral(-k * k * dof(E), tf(E), omega, gauss); @@ -217,7 +219,7 @@ int main(int argc, char **argv) { // gauss); formulation.integral(-im * k * dof(E), tf(E), gammaInf, gauss); // Physical source using Lagrange mutiplier - formulation.integral(dof(lambda), tf(E), gammaDir , gauss); + formulation.integral(dof(lambda), tf(E), gammaDir, gauss); formulation.integral(dof(E), tf(lambda), gammaDir, gauss); formulation.integral(Einc, tf(lambda), gammaDir, gauss); formulation.pre(); @@ -242,69 +244,69 @@ int main(int argc, char **argv) { Subdomain gammaDir(nDom); Subdomain border(nDom); Interface sigma(nDom); - for (unsigned int i = 0; i < unsigned(nDom); ++i) { + for(unsigned int i = 0; i < unsigned(nDom); ++i) { omega(i) = Domain(3, i + 1); - if (i == unsigned(nDom) - 1) { + if(i == unsigned(nDom) - 1) { gammaInf(i) = Domain(2, 2); } - if (i == 0) { + if(i == 0) { gammaDir(i) = Domain(2, 1); } border(i) = Domain(2, 100 + i); - if (i != 0) { + if(i != 0) { sigma(i, i - 1) = Domain(2, 200 + i - 1); } - if (i != unsigned(nDom) - 1) { + if(i != unsigned(nDom) - 1) { sigma(i, i + 1) = Domain(2, 200 + i); } } /**** * Define topology ****/ - std::vector<std::vector<unsigned int>> topology(nDom); - for (unsigned int i = 0; i < unsigned(nDom); ++i) { - if (i != 0) { + std::vector< std::vector< unsigned int > > topology(nDom); + for(unsigned int i = 0; i < unsigned(nDom); ++i) { + if(i != 0) { topology[i].push_back(i - 1); } - if (i != unsigned(nDom) - 1) { + if(i != unsigned(nDom) - 1) { topology[i].push_back(i + 1); } } // Create DDM formulation - gmshddm::problem::Formulation<std::complex<double>> formulation("Maxwell", - topology); + gmshddm::problem::Formulation< std::complex< double > > formulation("Maxwell", + topology); // Create fields - SubdomainField<std::complex<double>, Form::Form1> E( - "E", omega | gammaDir | gammaInf | sigma, - FunctionSpaceTypeForm1::HierarchicalHCurl, FEorder); - SubdomainField<std::complex<double>, Form::Form1> lambda( - "lambda", gammaDir, FunctionSpaceTypeForm1::HierarchicalHCurl, - FEorder); - InterfaceField<std::complex<double>, Form::Form1> g( - "g", sigma, FunctionSpaceTypeForm1::HierarchicalHCurl, 0); + SubdomainField< std::complex< double >, Form::Form1 > E( + "E", omega | gammaDir | gammaInf | sigma, + FunctionSpaceTypeForm1::HierarchicalHCurl, FEorder); + SubdomainField< std::complex< double >, Form::Form1 > lambda( + "lambda", gammaDir, FunctionSpaceTypeForm1::HierarchicalHCurl, + FEorder); + InterfaceField< std::complex< double >, Form::Form1 > g( + "g", sigma, FunctionSpaceTypeForm1::HierarchicalHCurl, 0); // Tell to the formulation that g is field that have to be exchanged between // subdomains formulation.addInterfaceField(g); - VectorFunction<std::complex<double>> n = normal<std::complex<double>>(); - VectorFunction<std::complex<double>> functionZero = - vector<std::complex<double>>(0., 0., 0.); - for (unsigned int i = 0; i < unsigned(nDom); ++i){ + VectorFunction< std::complex< double > > n = normal< std::complex< double > >(); + VectorFunction< std::complex< double > > functionZero = + vector< std::complex< double > >(0., 0., 0.); + for(unsigned int i = 0; i < unsigned(nDom); ++i) { E(i).addConstraint(border(i), functionZero); lambda(i).addConstraint(border(i), functionZero); - for (unsigned int jj = 0; jj < topology[i].size(); ++jj) { + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; g(i, j).addConstraint(border(i), functionZero); } } // Add terms to the formulation - for (unsigned int i = 0; i < unsigned(nDom); ++i) { + for(unsigned int i = 0; i < unsigned(nDom); ++i) { // VOLUME TERMS formulation(i).integral(curl(dof(E(i))), curl(tf(E(i))), omega(i), gauss); formulation(i).integral(-k * k * dof(E(i)), tf(E(i)), omega(i), gauss); @@ -316,13 +318,13 @@ int main(int argc, char **argv) { // Physical source using Lagrange mutiplier formulation(i).integral(dof(lambda(i)), tf(E(i)), gammaDir(i), gauss); - formulation(i).integral(dof(E(i)), tf(lambda(i)), gammaDir(i) , + formulation(i).integral(dof(E(i)), tf(lambda(i)), gammaDir(i), gauss); formulation(i).integral(formulation.physicalSource(Einc), tf(lambda(i)), gammaDir(i), gauss); // Artificial source on transmission boundaries - for (unsigned int jj = 0; jj < topology[i].size(); ++jj) { + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; /* formulation(i).integral(-im * k * n % (dof(E(i)) % n), tf(E(i)), sigma(i, j), gauss);*/ @@ -332,7 +334,7 @@ int main(int argc, char **argv) { sigma(i, j), gauss); } // INTERFACE TERMS - for (unsigned int jj = 0; jj < topology[i].size(); ++jj) { + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), gauss); @@ -348,7 +350,7 @@ int main(int argc, char **argv) { // Solve the DDM formulation formulation.solve("gmres"); //save field E - for (int i = 0; i < nDom; ++i) { + for(int i = 0; i < nDom; ++i) { save(E(i), omega(i), "E" + std::to_string(i)); } } diff --git a/demos/helmholtzflow/waveguide/CMakeLists.txt b/examples/navier/scattering/CMakeLists.txt old mode 100644 new mode 100755 similarity index 73% rename from demos/helmholtzflow/waveguide/CMakeLists.txt rename to examples/navier/scattering/CMakeLists.txt index 4d2e4b0c..c368ce59 --- a/demos/helmholtzflow/waveguide/CMakeLists.txt +++ b/examples/navier/scattering/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(demo CXX) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../demos.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake) add_executable(demo main.cpp ${EXTRA_INCS}) target_link_libraries(demo ${EXTRA_LIBS}) diff --git a/demos/navier/scattering/main.cpp b/examples/navier/scattering/main.cpp similarity index 68% rename from demos/navier/scattering/main.cpp rename to examples/navier/scattering/main.cpp index d94b532a..b717993b 100644 --- a/demos/navier/scattering/main.cpp +++ b/examples/navier/scattering/main.cpp @@ -1,10 +1,9 @@ -#include <gmshddm/GmshDdm.h> -#include <gmshddm/Formulation.h> +#include "gmsh.h" +#include <gmshddm/Formulation.h> +#include <gmshddm/GmshDdm.h> #include <gmshfem/Message.h> -#include "gmsh.h" - using namespace gmshddm; using namespace gmshddm::common; using namespace gmshddm::domain; @@ -39,7 +38,7 @@ void circlesConcentric(const unsigned int nDom, const double r0, const double rI std::vector< int > tagsSurface(nDom); for(unsigned int i = 0; i < nDom; ++i) { - tagsSurface[i] = gmsh::model::occ::addPlaneSurface({tagsCurve[i], tagsCurve[i+1]}); + tagsSurface[i] = gmsh::model::occ::addPlaneSurface({tagsCurve[i], tagsCurve[i + 1]}); } gmsh::model::occ::synchronize(); @@ -55,7 +54,7 @@ void circlesConcentric(const unsigned int nDom, const double r0, const double rI gmsh::model::setPhysicalName(2, 1 + i, "omega_" + std::to_string(i)); if(i != nDom - 1) { - gmsh::model::addPhysicalGroup(1, {tagsCircle[i+1]}, 200 + i); + gmsh::model::addPhysicalGroup(1, {tagsCircle[i + 1]}, 200 + i); gmsh::model::setPhysicalName(1, 200 + i, "sigma_" + std::to_string(i)); } } @@ -127,20 +126,20 @@ int main(int argc, char **argv) gmshddm::problem::Formulation< std::complex< double > > formulation("Navier", topology); const double pi = 3.14159265358979323846264338327950288; - const double rho = 1.; //.............[kg/m3] masse volumique - double f = 1.; //.............[Hz] fréquence - double w = 2 * pi * f; //.............[rad/s] pulsation - const double lambda = 1.; //.............[Pa] premier coefficient de Lamé - const double mu = 1.; //.............[Pa] deuxième coefficient de Lamé - const double cP = sqrt((lambda+2.0*mu)/rho); //.............[m/s] celerite de l'onde P - const double cS = sqrt(mu/rho); //.............[m/s] celerite de l'onde S - double kP = w/cP; //.............[1/m] nombre d'onde p - double kS = w/cS; //.............[1/m] nombre d'onde s - - TensorFunction< std::complex< double > > C_xx = tensor< std::complex< double > >((lambda+2.*mu), 0., 0., 0., mu, 0., 0., 0., 0.); + const double rho = 1.; //.............[kg/m3] masse volumique + double f = 1.; //.............[Hz] fréquence + double w = 2 * pi * f; //.............[rad/s] pulsation + const double lambda = 1.; //.............[Pa] premier coefficient de Lamé + const double mu = 1.; //.............[Pa] deuxième coefficient de Lamé + const double cP = sqrt((lambda + 2.0 * mu) / rho); //.............[m/s] celerite de l'onde P + const double cS = sqrt(mu / rho); //.............[m/s] celerite de l'onde S + double kP = w / cP; //.............[1/m] nombre d'onde p + double kS = w / cS; //.............[1/m] nombre d'onde s + + TensorFunction< std::complex< double > > C_xx = tensor< std::complex< double > >((lambda + 2. * mu), 0., 0., 0., mu, 0., 0., 0., 0.); TensorFunction< std::complex< double > > C_xy = tensor< std::complex< double > >(0., lambda, 0., mu, 0., 0., 0., 0., 0.); TensorFunction< std::complex< double > > C_yx = tensor< std::complex< double > >(0., mu, 0., lambda, 0., 0., 0., 0., 0.); - TensorFunction< std::complex< double > > C_yy = tensor< std::complex< double > >(mu, 0., 0., 0., (lambda+2.*mu), 0., 0., 0., 0.); + TensorFunction< std::complex< double > > C_yy = tensor< std::complex< double > >(mu, 0., 0., 0., (lambda + 2. * mu), 0., 0., 0., 0.); // Create fields SubdomainField< std::complex< double >, Form::Form0 > ux("ux", omega | gammaScat | gammaInf | sigma, FunctionSpaceTypeForm0::Lagrange); @@ -172,7 +171,7 @@ int main(int argc, char **argv) // Physical source formulation(i).integral(dof(lambdax(i)), tf(ux(i)), gammaScat(i), gauss); formulation(i).integral(dof(ux(i)), tf(lambdax(i)), gammaScat(i), gauss); - formulation(i).integral(formulation.physicalSource(- (cos(kP * x< std::complex< double > >()) + im * sin(kP * x< std::complex< double > >()))), tf(lambdax(i)), gammaScat(i), gauss); + formulation(i).integral(formulation.physicalSource(-(cos(kP * x< std::complex< double > >()) + im * sin(kP * x< std::complex< double > >()))), tf(lambdax(i)), gammaScat(i), gauss); formulation(i).integral(dof(lambday(i)), tf(uy(i)), gammaScat(i), gauss); formulation(i).integral(dof(uy(i)), tf(lambday(i)), gammaScat(i), gauss); @@ -185,45 +184,45 @@ int main(int argc, char **argv) formulation(i).integral(-im * w * cP * rho * nY * nY * dof(uy(i)), tf(uy(i)), gammaInf(i), gauss); formulation(i).integral(-im * w * cS * rho * nY * nY * dof(ux(i)), tf(ux(i)), gammaInf(i), gauss); - formulation(i).integral( im * w * cS * rho * nX * nY * dof(uy(i)), tf(ux(i)), gammaInf(i), gauss); + formulation(i).integral(im * w * cS * rho * nX * nY * dof(uy(i)), tf(ux(i)), gammaInf(i), gauss); formulation(i).integral(-im * w * cS * rho * nX * nX * dof(uy(i)), tf(uy(i)), gammaInf(i), gauss); - formulation(i).integral( im * w * cS * rho * nX * nY * dof(ux(i)), tf(uy(i)), gammaInf(i), gauss); + formulation(i).integral(im * w * cS * rho * nX * nY * dof(ux(i)), tf(uy(i)), gammaInf(i), gauss); // Artificial source for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(-im * w * cP * rho * nX * nX * dof(ux(i)), tf(ux(i)), sigma(i,j), gauss); - formulation(i).integral(-im * w * cP * rho * nX * nY * dof(uy(i)), tf(ux(i)), sigma(i,j), gauss); - formulation(i).integral(-im * w * cP * rho * nX * nY * dof(ux(i)), tf(uy(i)), sigma(i,j), gauss); - formulation(i).integral(-im * w * cP * rho * nY * nY * dof(uy(i)), tf(uy(i)), sigma(i,j), gauss); - - formulation(i).integral(-im * w * cS * rho * nY * nY * dof(ux(i)), tf(ux(i)), sigma(i,j), gauss); - formulation(i).integral( im * w * cS * rho * nX * nY * dof(uy(i)), tf(ux(i)), sigma(i,j), gauss); - formulation(i).integral(-im * w * cS * rho * nX * nX * dof(uy(i)), tf(uy(i)), sigma(i,j), gauss); - formulation(i).integral( im * w * cS * rho * nX * nY * dof(ux(i)), tf(uy(i)), sigma(i,j), gauss); - - formulation(i).integral(formulation.artificialSource( -gx(j,i) ), tf(ux(i)), sigma(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -gy(j,i) ), tf(uy(i)), sigma(i,j), gauss); + formulation(i).integral(-im * w * cP * rho * nX * nX * dof(ux(i)), tf(ux(i)), sigma(i, j), gauss); + formulation(i).integral(-im * w * cP * rho * nX * nY * dof(uy(i)), tf(ux(i)), sigma(i, j), gauss); + formulation(i).integral(-im * w * cP * rho * nX * nY * dof(ux(i)), tf(uy(i)), sigma(i, j), gauss); + formulation(i).integral(-im * w * cP * rho * nY * nY * dof(uy(i)), tf(uy(i)), sigma(i, j), gauss); + + formulation(i).integral(-im * w * cS * rho * nY * nY * dof(ux(i)), tf(ux(i)), sigma(i, j), gauss); + formulation(i).integral(im * w * cS * rho * nX * nY * dof(uy(i)), tf(ux(i)), sigma(i, j), gauss); + formulation(i).integral(-im * w * cS * rho * nX * nX * dof(uy(i)), tf(uy(i)), sigma(i, j), gauss); + formulation(i).integral(im * w * cS * rho * nX * nY * dof(ux(i)), tf(uy(i)), sigma(i, j), gauss); + + formulation(i).integral(formulation.artificialSource(-gx(j, i)), tf(ux(i)), sigma(i, j), gauss); + formulation(i).integral(formulation.artificialSource(-gy(j, i)), tf(uy(i)), sigma(i, j), gauss); } // INTERFACE TERMS for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i,j).integral(dof(gx(i,j)), tf(gx(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gx(j,i) ), tf(gx(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(dof(gx(i, j)), tf(gx(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(gx(j, i)), tf(gx(i, j)), sigma(i, j), gauss); - formulation(i,j).integral(dof(gy(i,j)), tf(gy(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( gy(j,i) ), tf(gy(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(dof(gy(i, j)), tf(gy(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(gy(j, i)), tf(gy(i, j)), sigma(i, j), gauss); - formulation(i,j).integral(2. * im * w * cP * rho * nX * nX * ux(i), tf(gx(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(2. * im * w * cP * rho * nX * nY * uy(i), tf(gx(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(2. * im * w * cP * rho * nX * nY * ux(i), tf(gy(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(2. * im * w * cP * rho * nY * nY * uy(i), tf(gy(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(2. * im * w * cP * rho * nX * nX * ux(i), tf(gx(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2. * im * w * cP * rho * nX * nY * uy(i), tf(gx(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2. * im * w * cP * rho * nX * nY * ux(i), tf(gy(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2. * im * w * cP * rho * nY * nY * uy(i), tf(gy(i, j)), sigma(i, j), gauss); - formulation(i,j).integral(2. * im * w * cS * rho * nY * nY * ux(i), tf(gx(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(-2. * im * w * cS * rho * nX * nY * uy(i), tf(gx(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(2. * im * w * cS * rho * nX * nX * uy(i), tf(gy(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(-2. * im * w * cS * rho * nX * nY * ux(i), tf(gy(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(2. * im * w * cS * rho * nY * nY * ux(i), tf(gx(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-2. * im * w * cS * rho * nX * nY * uy(i), tf(gx(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2. * im * w * cS * rho * nX * nX * uy(i), tf(gy(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-2. * im * w * cS * rho * nX * nY * ux(i), tf(gy(i, j)), sigma(i, j), gauss); } } diff --git a/tutorials/.clang-format b/tutorials/.clang-format new file mode 100644 index 00000000..d902ab97 --- /dev/null +++ b/tutorials/.clang-format @@ -0,0 +1,112 @@ +--- +Language: Cpp +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^"(?!gmsh\.h"|petsc\.h"|Eigen")' + Priority: 2 + - Regex: '"gmsh.h"|"petsc.h"|"Eigen"' + Priority: 3 + - Regex: '^<' + Priority: 4 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: false +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: true +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt new file mode 100644 index 00000000..210187a9 --- /dev/null +++ b/tutorials/CMakeLists.txt @@ -0,0 +1,11 @@ +set(TUTOS + helmholtz/waveguide + maxwell/waveguide +) + +foreach(TUTO ${TUTOS}) + add_test(NAME "tuto:${TUTO}:mkdir" COMMAND "${CMAKE_COMMAND}" -E make_directory build WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${TUTO}) + add_test(NAME "tuto:${TUTO}:cmake" COMMAND "${CMAKE_COMMAND}" -DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX} .. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${TUTO}/build) + add_test(NAME "tuto:${TUTO}:build" COMMAND "${CMAKE_MAKE_PROGRAM}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${TUTO}/build) + add_test(NAME "tuto:${TUTO}:run" COMMAND ./tuto WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${TUTO}/build) +endforeach() diff --git a/tutorials/README.md b/tutorials/README.md new file mode 100644 index 00000000..fc6fff34 --- /dev/null +++ b/tutorials/README.md @@ -0,0 +1,3 @@ +# GmshDDM tutorials + +Todo: Create tutorials based on problems of increasing difficulties that shows first the basic features of GmshDDM ('basic tutorial'), then that presents some more advanced uses ('advanced tutorial') @CGeuzaine ? diff --git a/tutorials/helmholtz/waveguide/CMakeLists.txt b/tutorials/helmholtz/waveguide/CMakeLists.txt new file mode 100644 index 00000000..7481f3ad --- /dev/null +++ b/tutorials/helmholtz/waveguide/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(tuto CXX) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../tutorial.cmake) + +add_executable(tuto main.cpp ${EXTRA_INCS}) +target_link_libraries(tuto ${EXTRA_LIBS}) diff --git a/demos/helmholtz/waveguide/main.cpp b/tutorials/helmholtz/waveguide/main.cpp similarity index 78% rename from demos/helmholtz/waveguide/main.cpp rename to tutorials/helmholtz/waveguide/main.cpp index a1917660..0a9b5b02 100644 --- a/demos/helmholtz/waveguide/main.cpp +++ b/tutorials/helmholtz/waveguide/main.cpp @@ -1,11 +1,10 @@ -#include <gmshddm/GmshDdm.h> +#include "gmsh.h" + #include <gmshddm/Formulation.h> +#include <gmshddm/GmshDdm.h> #include <gmshddm/MPIInterface.h> - #include <gmshfem/Message.h> -#include "gmsh.h" - using namespace gmshddm; using namespace gmshddm::common; using namespace gmshddm::domain; @@ -44,6 +43,7 @@ void waveguide(const unsigned int nDom, const double l, const double L, const do gmsh::model::addPhysicalGroup(1, {line}, 1); gmsh::model::setPhysicalName(1, 1, "gammaDir"); + std::vector< int > cornerTags; for(unsigned int i = 0; i < nDom; ++i) { std::vector< std::pair< int, int > > extrudeEntities; gmsh::model::geo::extrude({std::make_pair(1, line)}, domainSize, 0., 0., extrudeEntities, {static_cast< int >((domainSize) / lc)}, std::vector< double >(), true); @@ -52,6 +52,10 @@ void waveguide(const unsigned int nDom, const double l, const double L, const do borders[i].push_back(extrudeEntities[2].second); borders[i].push_back(extrudeEntities[3].second); sigmas[i] = line; + if(i != nDom - 1) { + cornerTags.push_back(3 + cornerTags.size()); + cornerTags.push_back(3 + cornerTags.size()); + } } gmsh::model::addPhysicalGroup(1, {line}, 2); @@ -72,6 +76,9 @@ void waveguide(const unsigned int nDom, const double l, const double L, const do gmsh::model::setPhysicalName(1, 200 + i, "sigma_" + std::to_string(i) + "_" + std::to_string(i + 1)); } + gmsh::model::addPhysicalGroup(0, cornerTags, 1000); + gmsh::model::setPhysicalName(0, 1000, "corner"); + gmsh::model::geo::synchronize(); gmsh::model::mesh::generate(); } @@ -79,10 +86,7 @@ void waveguide(const unsigned int nDom, const double l, const double L, const do int main(int argc, char **argv) { GmshDdm gmshDdm(argc, argv); - - const unsigned int MPI_Size = getMPISize(); - const unsigned int MPI_Rank = getMPIRank(); - + double pi = 3.14159265359; int nDom = 3; @@ -111,6 +115,7 @@ int main(int argc, char **argv) Subdomain gammaDir(nDom); Subdomain border(nDom); Interface sigma(nDom); + Domain corner = Domain("corner"); for(unsigned int i = 0; i < nDom; ++i) { omega(i) = Domain(2, i + 1); @@ -150,8 +155,17 @@ int main(int argc, char **argv) // Create fields SubdomainField< std::complex< double >, Form::Form0 > u("u", omega | gammaDir | gammaInf | border | sigma, FunctionSpaceTypeForm0::HierarchicalH1, order); - SubdomainField< std::complex< double >, Form::Form0 > lambda("lambda", gammaDir | border, FunctionSpaceTypeForm0::HierarchicalH1, order); + for(unsigned int i = 0; i < nDom; ++i) { + u(i).addConstraint(border(i), 0.); + } + u(0).addConstraint(gammaDir(0), sin< std::complex< double > >(pi * y< std::complex< double > >() / l)); InterfaceField< std::complex< double >, Form::Form0 > g("g", sigma, FunctionSpaceTypeForm0::HierarchicalH1, order); + for(unsigned int i = 0; i < nDom; ++i) { + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + g(i, j).addConstraint(corner, 0.); + } + } std::complex< double > im(0., 1.); @@ -161,29 +175,23 @@ int main(int argc, char **argv) // Add terms to the formulation for(unsigned int i = 0; i < nDom; ++i) { // VOLUME TERMS - formulation(i).integral(grad(dof(u(i))), grad(tf(u(i))), omega(i), gauss); - formulation(i).integral(- k * k * dof(u(i)), tf(u(i)), omega(i), gauss); - formulation(i).integral(- im * k * dof(u(i)), tf(u(i)), gammaInf(i), gauss); - - // Physical source - formulation(i).integral(dof(lambda(i)), tf(u(i)), gammaDir(i) | border(i), gauss); - formulation(i).integral(dof(u(i)), tf(lambda(i)), gammaDir(i) | border(i), gauss); - formulation(i).integral(formulation.physicalSource( -sin< std::complex< double > >((kIn * pi / l) * y< std::complex< double > >() ) ), tf(lambda(i)), gammaDir(i), gauss); + formulation(i).integral(-k * k * dof(u(i)), tf(u(i)), omega(i), gauss); + formulation(i).integral(-im * k * dof(u(i)), tf(u(i)), gammaInf(i), gauss); // Artificial source for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i).integral(- im * k * dof(u(i)), tf(u(i)), sigma(i,j), gauss); - formulation(i).integral(formulation.artificialSource( -g(j,i) ), tf(u(i)), sigma(i,j), gauss); + formulation(i).integral(-im * k * dof(u(i)), tf(u(i)), sigma(i, j), gauss); + formulation(i).integral(formulation.artificialSource(-g(j, i)), tf(u(i)), sigma(i, j), gauss); } // INTERFACE TERMS for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { const unsigned int j = topology[i][jj]; - formulation(i,j).integral(dof(g(i,j)), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(formulation.artificialSource( g(j,i) ), tf(g(i,j)), sigma(i,j), gauss); - formulation(i,j).integral(2. * im * k * u(i), tf(g(i,j)), sigma(i,j), gauss); + formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(g(j, i)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2. * im * k * u(i), tf(g(i, j)), sigma(i, j), gauss); } } @@ -194,8 +202,8 @@ int main(int argc, char **argv) formulation.solve("gmres", 1e-6, iterMax); for(unsigned int i = 0; i < nDom; ++i) { - if(i % MPI_Size == MPI_Rank) { - save(u(i), omega(i), "u_" + std::to_string(i)); + if(isItMySubdomain(i)) { + save(u(i), omega(i), "u_" + std::to_string(i)); } } diff --git a/tutorials/maxwell/main.cpp b/tutorials/maxwell/main.cpp new file mode 100644 index 00000000..9b3e8c39 --- /dev/null +++ b/tutorials/maxwell/main.cpp @@ -0,0 +1,359 @@ +#include "gmsh.h" + +#include <gmshddm/Formulation.h> +#include <gmshddm/GmshDdm.h> +#include <gmshfem/Message.h> + +using namespace gmshddm; +using namespace gmshddm::common; +using namespace gmshddm::domain; +using namespace gmshddm::problem; +using namespace gmshddm::field; + +using namespace gmshfem; +using namespace gmshfem::domain; +using namespace gmshfem::equation; +using namespace gmshfem::problem; +using namespace gmshfem::field; +using namespace gmshfem::function; +using namespace gmshfem::post; + +void waveguide(const unsigned int nDom, const double a, const double b, + const double L, const double lc) +{ + if(nDom < 2) { + gmshfem::msg::error << "nDom should be at least equal to 2." + << gmshfem::msg::endl; + exit(0); + } + gmsh::model::add("waveguide"); + + const double domainSize = L / nDom; + + std::vector< std::vector< int > > borders(nDom); + std::vector< int > omegas(nDom); + std::vector< int > sigmas(nDom - 1); + + int p[4]; + + p[0] = gmsh::model::geo::addPoint(0., 0, 0., lc); + p[1] = gmsh::model::geo::addPoint(0, a, 0., lc); + p[2] = gmsh::model::geo::addPoint(0, a, b, lc); + p[3] = gmsh::model::geo::addPoint(0, 0., b, lc); + int line[4]; + + line[0] = gmsh::model::geo::addLine(p[0], p[1]); + line[1] = gmsh::model::geo::addLine(p[2], p[1]); + line[2] = gmsh::model::geo::addLine(p[2], p[3]); + line[3] = gmsh::model::geo::addLine(p[3], p[0]); + + int curveLoop = + gmsh::model::geo::addCurveLoop({line[3], line[0], -line[1], line[2]}); + + int tagSurface = gmsh::model::geo::addPlaneSurface({curveLoop}); + gmsh::model::geo::mesh::setTransfiniteSurface(tagSurface); + gmsh::model::geo::mesh::setRecombine(2, tagSurface); + gmsh::model::addPhysicalGroup(2, {tagSurface}, 1); + gmsh::model::setPhysicalName(2, 1, "gammaDir"); + + for(unsigned int i = 0; i < nDom; ++i) { + std::vector< std::pair< int, int > > extrudeEntities; + gmsh::model::geo::extrude( + {std::make_pair(2, tagSurface)}, domainSize, 0., 0., extrudeEntities, + {static_cast< int >((domainSize) / lc)}, std::vector< double >(), true); + tagSurface = extrudeEntities[0].second; + omegas[i] = extrudeEntities[1].second; + borders[i].push_back(extrudeEntities[2].second); + borders[i].push_back(extrudeEntities[3].second); + borders[i].push_back(extrudeEntities[4].second); + borders[i].push_back(extrudeEntities[5].second); + sigmas[i] = tagSurface; + } + + gmsh::model::addPhysicalGroup(2, {tagSurface}, 2); + gmsh::model::setPhysicalName(2, 2, "gammaInf"); + + for(unsigned int i = 0; i < borders.size(); ++i) { + gmsh::model::addPhysicalGroup(2, borders[i], 100 + i); + gmsh::model::setPhysicalName(2, 100 + i, "border_" + std::to_string(i)); + } + + for(unsigned int i = 0; i < omegas.size(); ++i) { + gmsh::model::addPhysicalGroup(3, {omegas[i]}, i + 1); + gmsh::model::setPhysicalName(3, i + 1, "omega_" + std::to_string(i)); + } + + for(unsigned int i = 0; i < sigmas.size(); ++i) { + gmsh::model::addPhysicalGroup(2, {sigmas[i]}, 200 + i); + gmsh::model::setPhysicalName( + 2, 200 + i, "sigma_" + std::to_string(i) + "_" + std::to_string(i + 1)); + } + gmsh::model::geo::synchronize(); + gmsh::model::mesh::generate(); +} + +int main(int argc, char **argv) +{ + GmshDdm gmshDdm(argc, argv); + /**** + * input Data + ****/ + double pi = 3.14159265359; + int nDom = 2; + double L = 2; + double a = 1; + double b = 1; + double k = 10; + double mode_m = 2.; + double mode_n = 1.; + int FEorder = 0; + double lc = 0.5; + bool ddm = true; + std::string gauss = "Gauss4"; + gmshDdm.userDefinedParameter(ddm, "ddm"); + gmshDdm.userDefinedParameter(nDom, "nDom"); + gmshDdm.userDefinedParameter(L, "L"); + gmshDdm.userDefinedParameter(a, "a"); + gmshDdm.userDefinedParameter(b, "b"); + gmshDdm.userDefinedParameter(lc, "lc"); + gmshDdm.userDefinedParameter(k, "k"); + gmshDdm.userDefinedParameter(FEorder, "FEorder"); + gmshDdm.userDefinedParameter(gauss, "gauss"); + double ky = mode_m * pi / a; + double kz = mode_n * pi / b; + double kc = sqrt(ky * ky + kz * kz); + std::complex< double > im(0., 1.); + std::complex< double > beta; + if(-kc * kc + k * k >= 0) { + beta = sqrt(-kc * kc + k * k); + } + else { + beta = -im * sqrt(kc * kc - k * k); + } + // TM + VectorFunction< std::complex< double > > Einc = vector< std::complex< double > >( + sin< std::complex< double > >(ky * y< std::complex< double > >()) * + sin< std::complex< double > >(kz * z< std::complex< double > >()), + im * beta * ky / (kc * kc) * + cos< std::complex< double > >(ky * y< std::complex< double > >()) * + sin< std::complex< double > >(kz * z< std::complex< double > >()), + im * beta * kz / (kc * kc) * + cos< std::complex< double > >(kz * z< std::complex< double > >()) * + sin< std::complex< double > >(ky * y< std::complex< double > >())); + /**** + * FEM + ****/ + if(!ddm) { + /**** + * Gmsh part + ****/ + gmsh::model::add("waveguide"); + const double domainSize = L; + std::vector< std::vector< int > > borders(1); + std::vector< int > omegas(1); + int p[4]; + p[0] = gmsh::model::geo::addPoint(0., 0, 0., lc); + p[1] = gmsh::model::geo::addPoint(0, a, 0., lc); + p[2] = gmsh::model::geo::addPoint(0, a, b, lc); + p[3] = gmsh::model::geo::addPoint(0, 0., b, lc); + int line[4]; + + line[0] = gmsh::model::geo::addLine(p[0], p[1]); + line[1] = gmsh::model::geo::addLine(p[2], p[1]); + line[2] = gmsh::model::geo::addLine(p[2], p[3]); + line[3] = gmsh::model::geo::addLine(p[3], p[0]); + + int curveLoop = + gmsh::model::geo::addCurveLoop({line[3], line[0], -line[1], line[2]}); + + int tagSurface = gmsh::model::geo::addPlaneSurface({curveLoop}); + gmsh::model::geo::mesh::setTransfiniteSurface(tagSurface); + gmsh::model::geo::mesh::setRecombine(2, tagSurface); + gmsh::model::addPhysicalGroup(2, {tagSurface}, 1); + gmsh::model::setPhysicalName(2, 1, "gammaDir"); + std::vector< std::pair< int, int > > extrudeEntities; + gmsh::model::geo::extrude( + {std::make_pair(2, tagSurface)}, domainSize, 0., 0., extrudeEntities, + {static_cast< int >((domainSize) / lc)}, std::vector< double >(), true); + tagSurface = extrudeEntities[0].second; + omegas[0] = extrudeEntities[1].second; + borders[0].push_back(extrudeEntities[2].second); + borders[0].push_back(extrudeEntities[3].second); + borders[0].push_back(extrudeEntities[4].second); + borders[0].push_back(extrudeEntities[5].second); + + gmsh::model::addPhysicalGroup(2, {tagSurface}, 2); + gmsh::model::setPhysicalName(2, 2, "gammaInf"); + gmsh::model::addPhysicalGroup(2, borders[0], 100); + gmsh::model::setPhysicalName(2, 100, "border_" + std::to_string(0)); + gmsh::model::addPhysicalGroup(3, {omegas[0]}, 1); + gmsh::model::setPhysicalName(3, 1, "omega_" + std::to_string(0)); + + gmsh::model::geo::synchronize(); + gmsh::model::mesh::generate(); + Domain omega(3, 1); + Domain gammaInf(2, 2); + Domain gammaDir(2, 1); + Domain border(2, 100); + gmshfem::problem::Formulation< std::complex< double > > formulation("maxwell"); + + /**** + * Create fields + ****/ + Field< std::complex< double >, Form::Form1 > E( + "E", omega | gammaDir | gammaInf | border, + FunctionSpaceTypeForm1::HierarchicalHCurl, FEorder); + Field< std::complex< double >, Form::Form1 > lambda( + "lambda", gammaDir, FunctionSpaceTypeForm1::HierarchicalHCurl, + FEorder); + // VectorFunction<std::complex<double>> n = normal<std::complex<double>>(); + // VOLUME TERMS + + E.addConstraint(border, vector< std::complex< double > >(0., 0., 0.)); + lambda.addConstraint(border, vector< std::complex< double > >(0., 0., 0.)); + + formulation.integral(curl(dof(E)), curl(tf(E)), omega, gauss); + formulation.integral(-k * k * dof(E), tf(E), omega, gauss); + // Silver Muller + // formulation.integral(- im * k * n % (dof(E) % n), tf(E), gammaInf, + // gauss); + formulation.integral(-im * k * dof(E), tf(E), gammaInf, gauss); + // Physical source using Lagrange mutiplier + formulation.integral(dof(lambda), tf(E), gammaDir, gauss); + formulation.integral(dof(E), tf(lambda), gammaDir, gauss); + formulation.integral(Einc, tf(lambda), gammaDir, gauss); + formulation.pre(); + formulation.assemble(); + formulation.solve(); + save(E, omega, "E"); + } + /**** + * DDM + ****/ + else { + /**** + * Build geometry and mesh using gmsh API + ****/ + waveguide(nDom, a, b, L, lc); + + /**** + * Define domains + ****/ + Subdomain omega(nDom); + Subdomain gammaInf(nDom); + Subdomain gammaDir(nDom); + Subdomain border(nDom); + Interface sigma(nDom); + for(unsigned int i = 0; i < unsigned(nDom); ++i) { + omega(i) = Domain(3, i + 1); + + if(i == unsigned(nDom) - 1) { + gammaInf(i) = Domain(2, 2); + } + + if(i == 0) { + gammaDir(i) = Domain(2, 1); + } + + border(i) = Domain(2, 100 + i); + + if(i != 0) { + sigma(i, i - 1) = Domain(2, 200 + i - 1); + } + if(i != unsigned(nDom) - 1) { + sigma(i, i + 1) = Domain(2, 200 + i); + } + } + /**** + * Define topology + ****/ + std::vector< std::vector< unsigned int > > topology(nDom); + for(unsigned int i = 0; i < unsigned(nDom); ++i) { + if(i != 0) { + topology[i].push_back(i - 1); + } + if(i != unsigned(nDom) - 1) { + topology[i].push_back(i + 1); + } + } + // Create DDM formulation + gmshddm::problem::Formulation< std::complex< double > > formulation("Maxwell", + topology); + // Create fields + SubdomainField< std::complex< double >, Form::Form1 > E( + "E", omega | gammaDir | gammaInf | sigma, + FunctionSpaceTypeForm1::HierarchicalHCurl, FEorder); + SubdomainField< std::complex< double >, Form::Form1 > lambda( + "lambda", gammaDir, FunctionSpaceTypeForm1::HierarchicalHCurl, + FEorder); + InterfaceField< std::complex< double >, Form::Form1 > g( + "g", sigma, FunctionSpaceTypeForm1::HierarchicalHCurl, 0); + + + // Tell to the formulation that g is field that have to be exchanged between + // subdomains + formulation.addInterfaceField(g); + VectorFunction< std::complex< double > > n = normal< std::complex< double > >(); + VectorFunction< std::complex< double > > functionZero = + vector< std::complex< double > >(0., 0., 0.); + for(unsigned int i = 0; i < unsigned(nDom); ++i) { + E(i).addConstraint(border(i), functionZero); + lambda(i).addConstraint(border(i), functionZero); + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + g(i, j).addConstraint(border(i), functionZero); + } + } + + // Add terms to the formulation + for(unsigned int i = 0; i < unsigned(nDom); ++i) { + // VOLUME TERMS + formulation(i).integral(curl(dof(E(i))), curl(tf(E(i))), omega(i), gauss); + formulation(i).integral(-k * k * dof(E(i)), tf(E(i)), omega(i), gauss); + // Silver Muller + /* formulation(i).integral(-im * k * n % (dof(E(i)) % n), tf(E(i)), + gammaInf(i), gauss);*/ + formulation(i).integral(-im * k * dof(E(i)), tf(E(i)), gammaInf(i), + gauss); + // Physical source using Lagrange mutiplier + formulation(i).integral(dof(lambda(i)), tf(E(i)), gammaDir(i), + gauss); + formulation(i).integral(dof(E(i)), tf(lambda(i)), gammaDir(i), + gauss); + formulation(i).integral(formulation.physicalSource(Einc), tf(lambda(i)), + gammaDir(i), gauss); + + // Artificial source on transmission boundaries + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + /* formulation(i).integral(-im * k * n % (dof(E(i)) % n), tf(E(i)), + sigma(i, j), gauss);*/ + formulation(i).integral(-im * k * dof(E(i)), tf(E(i)), sigma(i, j), + gauss); + formulation(i).integral(formulation.artificialSource(g(j, i)), tf(E(i)), + sigma(i, j), gauss); + } + // INTERFACE TERMS + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), + gauss); + formulation(i, j).integral(formulation.artificialSource(g(j, i)), + tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(-2. * im * k * E(i), tf(g(i, j)), + sigma(i, j), gauss); + /*formulation(i, j).integral(-2. * im * k * n % (E(i) % n), tf(g(i, j)), + sigma(i, j), gauss);*/ + } + } + formulation.pre(); + // Solve the DDM formulation + formulation.solve("gmres"); + //save field E + for(int i = 0; i < nDom; ++i) { + save(E(i), omega(i), "E" + std::to_string(i)); + } + } + + return 0; +} diff --git a/tutorials/maxwell/waveguide/CMakeLists.txt b/tutorials/maxwell/waveguide/CMakeLists.txt new file mode 100644 index 00000000..7481f3ad --- /dev/null +++ b/tutorials/maxwell/waveguide/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(tuto CXX) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../tutorial.cmake) + +add_executable(tuto main.cpp ${EXTRA_INCS}) +target_link_libraries(tuto ${EXTRA_LIBS}) diff --git a/tutorials/maxwell/waveguide/main.cpp b/tutorials/maxwell/waveguide/main.cpp new file mode 100644 index 00000000..3d9c6310 --- /dev/null +++ b/tutorials/maxwell/waveguide/main.cpp @@ -0,0 +1,213 @@ +#include "gmsh.h" + +#include <gmshddm/Formulation.h> +#include <gmshddm/GmshDdm.h> +#include <gmshddm/MPIInterface.h> +#include <gmshfem/Message.h> + +using namespace gmshddm; +using namespace gmshddm::common; +using namespace gmshddm::domain; +using namespace gmshddm::problem; +using namespace gmshddm::field; +using namespace gmshddm::mpi; + +using namespace gmshfem; +using namespace gmshfem::domain; +using namespace gmshfem::equation; +using namespace gmshfem::problem; +using namespace gmshfem::field; +using namespace gmshfem::function; +using namespace gmshfem::post; + +void waveguide(const unsigned int nDom, const double l, const double L, const double lc) +{ + if(nDom < 2) { + gmshfem::msg::error << "nDom should be at least equal to 2." << gmshfem::msg::endl; + exit(0); + } + gmsh::model::add("waveguide"); + + const double domainSize = L / nDom; + + std::vector< std::vector< int > > borders(nDom); + std::vector< int > omegas(nDom); + std::vector< int > sigmas(nDom - 1); + + int p[2]; + + p[0] = gmsh::model::geo::addPoint(0., l, 0., lc); + p[1] = gmsh::model::geo::addPoint(0., 0., 0., lc); + + int line = gmsh::model::geo::addLine(p[0], p[1]); + gmsh::model::addPhysicalGroup(1, {line}, 1); + gmsh::model::setPhysicalName(1, 1, "gammaDir"); + + std::vector< int > cornerTags; + for(unsigned int i = 0; i < nDom; ++i) { + std::vector< std::pair< int, int > > extrudeEntities; + gmsh::model::geo::extrude({std::make_pair(1, line)}, domainSize, 0., 0., extrudeEntities, {static_cast< int >((domainSize) / lc)}, std::vector< double >(), true); + line = extrudeEntities[0].second; + omegas[i] = extrudeEntities[1].second; + borders[i].push_back(extrudeEntities[2].second); + borders[i].push_back(extrudeEntities[3].second); + sigmas[i] = line; + if(i != nDom - 1) { + cornerTags.push_back(3 + cornerTags.size()); + cornerTags.push_back(3 + cornerTags.size()); + } + } + + gmsh::model::addPhysicalGroup(1, {line}, 2); + gmsh::model::setPhysicalName(1, 2, "gammaInf"); + + for(unsigned int i = 0; i < borders.size(); ++i) { + gmsh::model::addPhysicalGroup(1, borders[i], 100 + i); + gmsh::model::setPhysicalName(1, 100 + i, "border_" + std::to_string(i)); + } + + for(unsigned int i = 0; i < omegas.size(); ++i) { + gmsh::model::addPhysicalGroup(2, {omegas[i]}, i + 1); + gmsh::model::setPhysicalName(2, i + 1, "omega_" + std::to_string(i)); + } + + for(unsigned int i = 0; i < sigmas.size(); ++i) { + gmsh::model::addPhysicalGroup(1, {sigmas[i]}, 200 + i); + gmsh::model::setPhysicalName(1, 200 + i, "sigma_" + std::to_string(i) + "_" + std::to_string(i + 1)); + } + + gmsh::model::addPhysicalGroup(0, cornerTags, 1000); + gmsh::model::setPhysicalName(0, 1000, "corner"); + + gmsh::model::geo::synchronize(); + gmsh::model::mesh::generate(); +} + +int main(int argc, char **argv) +{ + GmshDdm gmshDdm(argc, argv); + + double pi = 3.14159265359; + + int nDom = 3; + gmshDdm.userDefinedParameter(nDom, "nDom"); + double L = 5; + double l = 1; + double lc = 0.02; + double k = 2 * pi; + double kIn = 1.; + int order = 1; + gmshDdm.userDefinedParameter(L, "L"); + gmshDdm.userDefinedParameter(l, "l"); + gmshDdm.userDefinedParameter(lc, "lc"); + gmshDdm.userDefinedParameter(k, "k"); + gmshDdm.userDefinedParameter(kIn, "kIn"); + gmshDdm.userDefinedParameter(order, "order"); + std::string gauss = "Gauss10"; + gmshDdm.userDefinedParameter(gauss, "gauss"); + + // Build geometry and mesh using gmsh API + waveguide(nDom, l, L, lc); + + // Define domain + Subdomain omega(nDom); + Subdomain gammaInf(nDom); + Subdomain gammaDir(nDom); + Subdomain border(nDom); + Interface sigma(nDom); + Domain corner = Domain("corner"); + + for(unsigned int i = 0; i < nDom; ++i) { + omega(i) = Domain(2, i + 1); + + if(i == nDom - 1) { + gammaInf(i) = Domain(1, 2); + } + + if(i == 0) { + gammaDir(i) = Domain(1, 1); + } + + border(i) = Domain(1, 100 + i); + + if(i != 0) { + sigma(i, i - 1) = Domain(1, 200 + i - 1); + } + if(i != nDom - 1) { + sigma(i, i + 1) = Domain(1, 200 + i); + } + } + + // Define topology + std::vector< std::vector< unsigned int > > topology(nDom); + for(unsigned int i = 0; i < nDom; ++i) { + if(i != 0) { + topology[i].push_back(i - 1); + } + if(i != nDom - 1) { + topology[i].push_back(i + 1); + } + } + + + // Create DDM formulation + gmshddm::problem::Formulation< std::complex< double > > formulation("Maxwell", topology); + + // Create fields + SubdomainField< std::complex< double >, Form::Form1 > e("e", omega | gammaDir | gammaInf | border | sigma, FunctionSpaceTypeForm1::HierarchicalHCurl, order); + for(unsigned int i = 0; i < nDom; ++i) { + e(i).addConstraint(border(i), vector< std::complex< double > >(0., 0., 0.)); + } + e(0).addConstraint(gammaDir(0), sin< std::complex< double > >(2. * pi * y< std::complex< double > >() / l) * vector< std::complex< double > >(0., 1., 0.)); + InterfaceField< std::complex< double >, Form::Form1 > g("g", sigma, FunctionSpaceTypeForm1::HierarchicalHCurl, order); + for(unsigned int i = 0; i < nDom; ++i) { + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + g(i, j).addConstraint(border(i), vector< std::complex< double > >(0., 0., 0.)); + } + } + + std::complex< double > im(0., 1.); + + // Tell to the formulation that g is field that have to be exchanged between subdomains + formulation.addInterfaceField(g); + + VectorFunction< std::complex< double > > n = normal< std::complex< double > >(); + + // Add terms to the formulation + for(unsigned int i = 0; i < nDom; ++i) { + // VOLUME TERMS + formulation(i).integral(curl(dof(e(i))), curl(tf(e(i))), omega(i), gauss); + formulation(i).integral(-k * k * dof(e(i)), tf(e(i)), omega(i), gauss); + formulation(i).integral(-im * k * n % (dof(e(i)) % n), tf(e(i)), gammaInf(i), gauss); + + // Artificial source + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + formulation(i).integral(-im * k * n % (dof(e(i)) % n), tf(e(i)), sigma(i, j), gauss); + formulation(i).integral(formulation.artificialSource(-g(j, i)), tf(e(i)), sigma(i, j), gauss); + } + + // INTERFACE TERMS + for(unsigned int jj = 0; jj < topology[i].size(); ++jj) { + const unsigned int j = topology[i][jj]; + formulation(i, j).integral(dof(g(i, j)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(formulation.artificialSource(g(j, i)), tf(g(i, j)), sigma(i, j), gauss); + formulation(i, j).integral(2. * im * k * n % (e(i) % n), tf(g(i, j)), sigma(i, j), gauss); + } + } + + // Solve the DDM formulation + formulation.pre(); + int iterMax = 1000; + gmshDdm.userDefinedParameter(iterMax, "iter"); + formulation.solve("gmres", 1e-6, iterMax); + + for(unsigned int i = 0; i < nDom; ++i) { + if(isItMySubdomain(i)) { + save(e(i), omega(i), "e_" + std::to_string(i)); + } + } + + return 0; +} diff --git a/tutorials/tutorial.cmake b/tutorials/tutorial.cmake new file mode 100644 index 00000000..3e2c7ef6 --- /dev/null +++ b/tutorials/tutorial.cmake @@ -0,0 +1,98 @@ +# The following commands are useful for the demos, and can be included in each +# demos's CMakeLists.txt; they fill the EXTRA_INCS and EXTRA_LIBS variables. + +# Detect if we use the MinGW compilers on Cygwin - if we do, handle the build as +# a pure Windows build +if(CYGWIN OR MSYS) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR + CMAKE_CXX_COMPILER_ID MATCHES "Clang") + execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine + OUTPUT_VARIABLE CXX_COMPILER_MACHINE + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(CXX_COMPILER_MACHINE MATCHES "mingw") + set(WIN32 1) + add_definitions(-DWIN32) + set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so" ".lib" ".LIB" ".dll" ".DLL") + endif() + endif() +endif() + +# Make sure we have C++11 support +set(CMAKE_CXX_STANDARD 11) + +# Enable all warnings +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag("-Wall" HAVE_WALL) +if(HAVE_WALL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +endif() + +# Find Gmsh +find_library(GMSH_LIB gmsh) +if(NOT GMSH_LIB) + message(FATAL_ERROR "Could not find Gmsh library") +endif(NOT GMSH_LIB) +find_path(GMSH_INC gmsh.h) +if(NOT GMSH_INC) + message(FATAL_ERROR "Could not find Gmsh header 'gmsh.h'") +endif(NOT GMSH_INC) +list(APPEND EXTRA_INCS ${GMSH_INC}) +list(APPEND EXTRA_LIBS ${GMSH_LIB}) + +# Find GmshFEM +find_library(GMSHFEM_LIB gmshfem) +if(NOT GMSHFEM_LIB) + message(FATAL_ERROR "Could not find GmshFEM library") +endif(NOT GMSHFEM_LIB) +find_path(GMSHFEM_INC gmshfem/GmshFem.h) +if(NOT GMSHFEM_INC) + message(FATAL_ERROR "Could not find GmshFEM header 'gmshfem/GmshFem.h'") +endif(NOT GMSHFEM_INC) +list(APPEND EXTRA_LIBS ${GMSHFEM_LIB}) +list(APPEND EXTRA_INCS ${GMSHFEM_INC}) +list(APPEND EXTRA_INCS ${GMSHFEM_INC}/gmshfem/contrib) + +# Find GmshDDM +find_library(GMSHDDM_LIB gmshddm) +if(NOT GMSHDDM_LIB) + message(FATAL_ERROR "Could not find GmshDDM library") +endif(NOT GMSHDDM_LIB) + +find_path(GMSHDDM_INC gmshddm/GmshDdm.h) +if(NOT GMSHDDM_INC) + message(FATAL_ERROR "Could not find GmshDDM header 'gmshddm/GmshDdm.h'") +endif(NOT GMSHDDM_INC) +list(APPEND EXTRA_LIBS ${GMSHDDM_LIB}) +list(APPEND EXTRA_INCS ${GMSHDDM_INC}) + +# OpenMP +find_package(OpenMP) +if(OPENMP_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +endif() + +if(APPLE AND EXISTS "/usr/local/opt/libomp") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xpreprocessor -fopenmp -I/usr/local/opt/libomp/include") + list(APPEND EXTRA_LIBS "-L/usr/local/opt/libomp/lib -lomp") + message(STATUS "Found OpenMP[Homebrew]") +elseif(APPLE AND EXISTS "/opt/local/lib/libomp") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xpreprocessor -fopenmp -I/opt/local/include/libomp") + list(APPEND EXTRA_LIBS "-L/opt/local/lib/libomp -lomp") + message(STATUS "Found OpenMP[MacPorts]") +endif() + +# MPI +find_package(MPI) +if(MPI_FOUND) + list(APPEND EXTRA_INCS ${MPI_CXX_INCLUDE_PATH}) + list(APPEND EXTRA_LIBS ${MPI_CXX_LIBRARIES}) + set(CMAKE_C_COMPILER ${MPI_C_COMPILER}) + set(CMAKE_CXX_COMPILER ${MPI_CXX_COMPILER}) + set(CMAKE_Fortran_COMPILER ${MPI_Fortran_COMPILER}) +endif() + +# Eigen +list(APPEND EXTRA_INCS ${CMAKE_CURRENT_LIST_DIR}/../contrib/eigen) + +include_directories(${EXTRA_INCS}) -- GitLab