From 6f659a831a69e3fc4c02f83a60d055772bb0e768 Mon Sep 17 00:00:00 2001
From: Anthony Royer <anthony.royer@uliege.be>
Date: Fri, 13 May 2022 14:29:40 +0200
Subject: [PATCH] HABC and corner with different number of auxillary fields

---
 .../helmholtz/crossPoints/Subproblem2D.cpp    | 43 +++++++------
 examples/helmholtz/crossPoints/Subproblem2D.h |  2 +-
 examples/helmholtz/crossPoints/ddm2D.cpp      | 63 ++++++++++++++-----
 examples/helmholtz/crossPoints/monoDomain.cpp |  2 +-
 4 files changed, 74 insertions(+), 36 deletions(-)

diff --git a/examples/helmholtz/crossPoints/Subproblem2D.cpp b/examples/helmholtz/crossPoints/Subproblem2D.cpp
index 0cd84471..3d847794 100755
--- a/examples/helmholtz/crossPoints/Subproblem2D.cpp
+++ b/examples/helmholtz/crossPoints/Subproblem2D.cpp
@@ -95,7 +95,7 @@ namespace D2 {
     }
   }
 
-  Subproblem::Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters &parameters, const std::string &E, const std::string &N, const std::string &W, const std::string &S) : _domains(domains), _parameters(parameters), _formulation(formulation), _fieldName(fieldName), _boundary(4, nullptr), _corner(4, nullptr)
+  Subproblem::Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters &parameters, const std::string &E, const std::string &N, const std::string &W, const std::string &S, const std::vector< unsigned int > activatedCrossPoints) : _domains(domains), _parameters(parameters), _formulation(formulation), _fieldName(fieldName), _boundary(4, nullptr), _corner(4, nullptr)
   {
     std::string type[4] = {E, N, W, S};
     std::string method[4];
@@ -134,6 +134,11 @@ namespace D2 {
     }
     
     for(unsigned int c = 0; c < 4; ++c) {
+      auto it = std::find(activatedCrossPoints.begin(), activatedCrossPoints.end(), c);
+      if(it == activatedCrossPoints.end()) {
+        continue;
+      }
+    
       if(method[c] == "sommerfeld" && method[(c+1)%4] == "sommerfeld") {
       }
       else if(method[c] == "habc" && method[(c+1)%4] == "habc") {
@@ -303,7 +308,6 @@ namespace D2 {
     
     const double pi = 3.141592653589793238462643383279;
     const std::complex< double > expPTheta(std::cos(_theta), std::sin(_theta));
-    const std::complex< double > expMTheta(std::cos(-_theta), std::sin(-_theta));
     const std::complex< double > expPTheta2(std::cos(_theta/2.), std::sin(_theta/2.));
     const double M = 2 * _N + 1;
     double cPade[_N];
@@ -618,11 +622,7 @@ namespace D2 {
     const unsigned int N1 = static_cast< HABC * >(_bnd[1])->getN();
     
     const double theta0 = static_cast< HABC * >(_bnd[0])->getTheta();
-  //  const double theta1 = static_cast< HABC * >(_bnd[1])->getTheta();
-      
-    if(N0 != N1) {
-      throw gmshfem::common::Exception("Corner with HABC having different number of auxilary fields");
-    }
+    const double theta1 = static_cast< HABC * >(_bnd[1])->getTheta();
 
     _uHABC_C.resize(N0);
     for(unsigned int m = 0; m < N0; ++m) {
@@ -642,14 +642,19 @@ namespace D2 {
     }
     
     const double pi = 3.141592653589793238462643383279;
-    const std::complex< double > expPTheta(std::cos(theta0), std::sin(theta0));
-    const std::complex< double > expMTheta(std::cos(-theta0), std::sin(-theta0));
-    const std::complex< double > expPTheta2(std::cos(theta0/2.), std::sin(theta0/2.));
+    
+    const std::complex< double > expPTheta_0(std::cos(theta0), std::sin(theta0));
+    const std::complex< double > expPTheta2_0(std::cos(theta0/2.), std::sin(theta0/2.));
+    
+    const std::complex< double > expPTheta_1(std::cos(theta1), std::sin(theta1));
+    const std::complex< double > expPTheta2_1(std::cos(theta1/2.), std::sin(theta1/2.));
+    
     const double M0 = 2 * N0 + 1;
     double cPade0[N0];
     for(unsigned int m = 0; m < N0; ++m) {
       cPade0[m] = std::tan((m+1) * pi / M0) * std::tan((m+1) * pi / M0);
     }
+    
     const double M1 = 2 * N1 + 1;
     double cPade1[N1];
     for(unsigned int n = 0; n < N1; ++n) {
@@ -667,11 +672,11 @@ namespace D2 {
       formulation.integral(-dof(*_vC[0][m]), tf(*uHABC[0][m]), corner, gauss);
 
       formulation.integral( dof(*_vC[0][m]), tf(*_vC[0][m]), corner, gauss);
-      formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[0][m]), tf(*_vC[0][m]), corner, gauss);
+      formulation.integral(-im * kappa * expPTheta2_1 * dof(*uHABC[0][m]), tf(*_vC[0][m]), corner, gauss);
       
       for(unsigned int n = 0; n < N1; ++n) {
-        formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*uHABC[0][m]), tf(*_vC[0][m]), corner, gauss);
-        formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*_uHABC_C[m][n]), tf(*_vC[0][m]), corner, gauss);
+        formulation.integral(-im * kappa * expPTheta2_1 * 2./M1 * cPade1[n] * dof(*uHABC[0][m]), tf(*_vC[0][m]), corner, gauss);
+        formulation.integral(-im * kappa * expPTheta2_1 * 2./M1 * cPade1[n] * dof(*_uHABC_C[m][n]), tf(*_vC[0][m]), corner, gauss);
       }
     }
     
@@ -680,20 +685,20 @@ namespace D2 {
       formulation.integral(-dof(*_vC[1][n]), tf(*uHABC[1][n]), corner, gauss);
 
       formulation.integral( dof(*_vC[1][n]), tf(*_vC[1][n]), corner, gauss);
-      formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[1][n]), tf(*_vC[1][n]), corner, gauss);
+      formulation.integral(-im * kappa * expPTheta2_0 * dof(*uHABC[1][n]), tf(*_vC[1][n]), corner, gauss);
       
       for(unsigned int m = 0; m < N0; ++m) {
-        formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*uHABC[1][n]), tf(*_vC[1][n]), corner, gauss);
-        formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*_uHABC_C[m][n]), tf(*_vC[1][n]), corner, gauss);
+        formulation.integral(-im * kappa * expPTheta2_0 * 2./M0 * cPade0[m] * dof(*uHABC[1][n]), tf(*_vC[1][n]), corner, gauss);
+        formulation.integral(-im * kappa * expPTheta2_0 * 2./M0 * cPade0[m] * dof(*_uHABC_C[m][n]), tf(*_vC[1][n]), corner, gauss);
       }
     }
     
     // auxiliary
     for(unsigned int m = 0; m < N0; ++m) {
       for(unsigned int n = 0; n < N1; ++n) {
-        formulation.integral( (cPade0[m] + cPade1[n] + expMTheta) * dof(*_uHABC_C[m][n]), tf(*_uHABC_C[m][n]), corner, gauss);
-        formulation.integral( (cPade1[n] + 1.) * dof(*uHABC[0][m]), tf(*_uHABC_C[m][n]), corner, gauss);
-        formulation.integral( (cPade0[m] + 1.) * dof(*uHABC[1][n]), tf(*_uHABC_C[m][n]), corner, gauss);
+        formulation.integral( (expPTheta_0 * cPade0[m] + expPTheta_1 * cPade1[n] + 1.) * dof(*_uHABC_C[m][n]), tf(*_uHABC_C[m][n]), corner, gauss);
+        formulation.integral( expPTheta_1 * (cPade1[n] + 1.) * dof(*uHABC[0][m]), tf(*_uHABC_C[m][n]), corner, gauss);
+        formulation.integral( expPTheta_0 * (cPade0[m] + 1.) * dof(*uHABC[1][n]), tf(*_uHABC_C[m][n]), corner, gauss);
       }
     }
   }
diff --git a/examples/helmholtz/crossPoints/Subproblem2D.h b/examples/helmholtz/crossPoints/Subproblem2D.h
index 57bc7692..b153d52f 100755
--- a/examples/helmholtz/crossPoints/Subproblem2D.h
+++ b/examples/helmholtz/crossPoints/Subproblem2D.h
@@ -51,7 +51,7 @@ namespace D2 {
     void _parseParameters(std::string &method, std::vector< std::string > &parameters, const std::string &str) const;
     
    public:
-    Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters &parameters, const std::string &E, const std::string &N, const std::string &W, const std::string &S);
+    Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters &parameters, const std::string &E, const std::string &N, const std::string &W, const std::string &S, const std::vector< unsigned int > activatedCrossPoints);
     ~Subproblem();
     
     void writeFormulation();
diff --git a/examples/helmholtz/crossPoints/ddm2D.cpp b/examples/helmholtz/crossPoints/ddm2D.cpp
index a14e1364..1e984dea 100755
--- a/examples/helmholtz/crossPoints/ddm2D.cpp
+++ b/examples/helmholtz/crossPoints/ddm2D.cpp
@@ -108,6 +108,8 @@ namespace D2 {
     double thetaPade = 0.;
     gmshDdm->userDefinedParameter(thetaPade, "thetaPade");
     thetaPade *= pi;
+    bool switchOffInteriorCrossPoints = false;
+    gmshDdm->userDefinedParameter(switchOffInteriorCrossPoints, "switchOffInteriorCrossPoints");
 
     // ************************
     // P O S T
@@ -190,7 +192,8 @@ namespace D2 {
     gmshfem::msg::info << "   - gauss: " << gauss << gmshfem::msg::endl;
     gmshfem::msg::info << "   - fieldOrder: " << fieldOrder << gmshfem::msg::endl;
     gmshfem::msg::info << "   - neumannOrder: " << neumannOrder << gmshfem::msg::endl;
-     gmshfem::msg::info << "   - stab: " << stab << " * lc (= " << stab * lc << ")" << gmshfem::msg::endl;
+    gmshfem::msg::info << "   - interior cross-points: " <<  (switchOffInteriorCrossPoints ? "switch off" : "switch on") << gmshfem::msg::endl;
+    gmshfem::msg::info << "   - stab: " << stab << " * lc (= " << stab * lc << ")" << gmshfem::msg::endl;
     
 
     // source
@@ -378,8 +381,8 @@ namespace D2 {
       gCornerPmlDiscontinuous.push_back(std::make_pair(
         new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[f] + dir[(f+1)%4] + "_first", pmlBndInterface[f].first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder),
         new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[f] + dir[(f+1)%4] + "_second", pmlBndInterface[f].second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder)));
-      gCornerHABC.push_back(std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N));
-      for(unsigned int n = 0; n < N; ++n) {
+      gCornerHABC.push_back(std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(std::max(N, NExt)));
+      for(unsigned int n = 0; n < std::max(N, NExt); ++n) {
         gCornerHABC[f][n] = std::make_pair(
           new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[f] + dir[(f+1)%4] + "_" + std::to_string(n) + "_first", cornerInterface[f].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder),
           new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[f] + dir[(f+1)%4] + "_" + std::to_string(n) + "_second", cornerInterface[f].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder));
@@ -399,7 +402,7 @@ namespace D2 {
       formulation.addInterfaceField(*gCornerPmlDiscontinuous[f].second);
       
       // HABC
-      for(unsigned int n = 0; n < N; ++n) {
+      for(unsigned int n = 0; n < std::max(N, NExt); ++n) {
         formulation.addInterfaceField(*gCornerHABC[f][n].first);
         formulation.addInterfaceField(*gCornerHABC[f][n].second);
       }
@@ -474,9 +477,39 @@ namespace D2 {
           }
         }
         gmshfem::msg::info << "Subdomain (" << i << ", " << j << ") has boundaries [" << (i == nDomX-1 ? bndExt : bnd) << ", " << (j == nDomY-1 ? bndExt : bnd) << ", " << (i == 0 ? bndExt : bnd) << ", " << (j == 0 ? bndExt : bnd) << "]" << gmshfem::msg::endl;
-        subproblem[i][j] = new Subproblem(formulation(index), u(index).name(), domains, parameters, (i == nDomX-1 ? bndExt : bnd), (j == nDomY-1 ? bndExt : bnd), (i == 0 ? bndExt : bnd), (j == 0 ? bndExt : bnd));
+        std::vector< unsigned int > activatedCrossPoints = {0, 1, 2, 3};
+        if(switchOffInteriorCrossPoints) {
+          activatedCrossPoints.clear();
+          if(i == nDomX-1 && j == nDomY-1) {
+            activatedCrossPoints.push_back(0);
+          }
+          if(i == 0 && j == nDomY-1) {
+            activatedCrossPoints.push_back(1);
+          }
+          if(i == 0 && j == 0) {
+            activatedCrossPoints.push_back(2);
+          }
+          if(i == nDomX-1 && j == 0) {
+            activatedCrossPoints.push_back(3);
+          }
+        }
+        subproblem[i][j] = new Subproblem(formulation(index), u(index).name(), domains, parameters, (i == nDomX-1 ? bndExt : bnd), (j == nDomY-1 ? bndExt : bnd), (i == 0 ? bndExt : bnd), (j == 0 ? bndExt : bnd), activatedCrossPoints);
         subproblem[i][j]->writeFormulation();
         
+        unsigned int Ns[4] = {N, N, N, N};
+        if(i == nDomX-1) {
+          Ns[0] = NExt;
+        }
+        if(j == nDomY-1) {
+          Ns[1] = NExt;
+        }
+        if(i == 0) {
+          Ns[2] = NExt;
+        }
+        if(j == 0) {
+          Ns[3] = NExt;
+        }
+        
         // coupling
         for(unsigned int b = 0; b < 4; ++b) {
           for(unsigned int jj = 0; jj < topology[index].size(); ++jj) {
@@ -521,12 +554,12 @@ namespace D2 {
             }
             if(auto cr = dynamic_cast< HABC_HABC * >(corner)) {
               if(!cornerInterface[c].first(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[c]; ++n) {
                   formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf(*cr->firstBoundary()->getUHABC(n)), cornerInterface[c].first(index, jndex), gauss);
                 }
               }
               if(!cornerInterface[c].second(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[(c+1)%4]; ++n) {
                   formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf(*cr->secondBoundary()->getUHABC(n)), cornerInterface[c].second(index, jndex), gauss);
                 }
               }
@@ -582,14 +615,14 @@ namespace D2 {
             }
             else if(auto cr = dynamic_cast< HABC_Sommerfeld * >(corner)) {
               if(!cornerInterface[c].first(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[c]; ++n) {
                   formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf(*cr->firstBoundary()->getUHABC(n)), cornerInterface[c].first(index, jndex), gauss);
                 }
               }
             }
             else if(auto cr = dynamic_cast< Sommerfeld_HABC * >(corner)) {
               if(!cornerInterface[c].second(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[(c+1)%4]; ++n) {
                   formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf(*cr->secondBoundary()->getUHABC(n)), cornerInterface[c].second(index, jndex), gauss);
                 }
               }
@@ -651,14 +684,14 @@ namespace D2 {
             }
             if(auto cr = dynamic_cast< HABC_HABC * >(corner)) {
               if(!cornerInterface[c].first(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[c]; ++n) {
                   formulation(index, jndex).integral(dof((*gCornerHABC[c][n].first)(index, jndex)), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss);
                   formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss);
                   formulation(index, jndex).integral(2. * *cr->getV(n, 0), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss);
                 }
               }
               if(!cornerInterface[c].second(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[(c+1)%4]; ++n) {
                   formulation(index, jndex).integral(dof((*gCornerHABC[c][n].second)(index, jndex)), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss);
                   formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss);
                   formulation(index, jndex).integral(2. * *cr->getV(n, 1), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss);
@@ -731,7 +764,7 @@ namespace D2 {
             }
             else if(auto cr = dynamic_cast< HABC_Sommerfeld * >(corner)) {
               if(!cornerInterface[c].first(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[c]; ++n) {
                   formulation(index, jndex).integral(dof((*gCornerHABC[c][n].first)(index, jndex)), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss);
                   formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss);
                   formulation(index, jndex).integral(2. * *cr->getV(n), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss);
@@ -740,7 +773,7 @@ namespace D2 {
             }
             else if(auto cr = dynamic_cast< Sommerfeld_HABC * >(corner)) {
               if(!cornerInterface[c].second(index, jndex).isEmpty()) {
-                for(unsigned int n = 0; n < N; ++n) {
+                for(unsigned int n = 0; n < Ns[(c+1)%4]; ++n) {
                   formulation(index, jndex).integral(dof((*gCornerHABC[c][n].second)(index, jndex)), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss);
                   formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss);
                   formulation(index, jndex).integral(2. * *cr->getV(n), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss);
@@ -851,7 +884,7 @@ namespace D2 {
         }
       }
       gmshfem::msg::info << "Monodomain has boundaries [" << bndExt << ", " << bndExt << ", " << bndExt << ", " << bndExt << "]" << gmshfem::msg::endl;
-      Subproblem subproblem(formulationMono, uMono.name(), domains, parameters, bndExt, bndExt, bndExt, bndExt);
+      Subproblem subproblem(formulationMono, uMono.name(), domains, parameters, bndExt, bndExt, bndExt, bndExt, {0,1,2,3});
       subproblem.writeFormulation();
         
       formulationMono.pre();
@@ -933,7 +966,7 @@ namespace D2 {
       delete gCornerPmlContinuous[f].second;
       delete gCornerPmlDiscontinuous[f].first;
       delete gCornerPmlDiscontinuous[f].second;
-      for(unsigned int n = 0; n < N; ++n) {
+      for(unsigned int n = 0; n < std::max(N, NExt); ++n) {
         delete gCornerHABC[f][n].first;
         delete gCornerHABC[f][n].second;
       }
diff --git a/examples/helmholtz/crossPoints/monoDomain.cpp b/examples/helmholtz/crossPoints/monoDomain.cpp
index d5f15947..dc891331 100755
--- a/examples/helmholtz/crossPoints/monoDomain.cpp
+++ b/examples/helmholtz/crossPoints/monoDomain.cpp
@@ -187,7 +187,7 @@ namespace D2 {
         bnd += "WithoutMultiplier_" + std::to_string(pmlSize) + "_" + pmlType;
       }
     }
-    Subproblem subproblem(formulation, u.name(), domains, parameters, bnd, bnd, bnd, bnd);
+    Subproblem subproblem(formulation, u.name(), domains, parameters, bnd, bnd, bnd, bnd, {0,1,2,3});
     subproblem.writeFormulation();
       
     if(spy) {
-- 
GitLab