Dhairya Malhotra 5 lat temu
rodzic
commit
690f2331d9
1 zmienionych plików z 60 dodań i 194 usunięć
  1. 60 194
      include/sctl/boundary_quadrature.hpp

+ 60 - 194
include/sctl/boundary_quadrature.hpp

@@ -2716,6 +2716,7 @@ template <class Real, Integer ORDER=10> class Stellarator {
           Ax2 = (S.Nsurf() >= 2 ? compute_inner_prod(area_elem, compute_dot_prod(Bp0, normal), x0) : 0);
         }
 
+        // TODO: precompute A21adj, A22adj
         auto compute_A21adj = [&S,&normal,&area_elem] (bool toroidal_flux) {
           const Long Nelem = S.NElem();
           const Long Nnodes = ElemBasis::Size();
@@ -2776,7 +2777,6 @@ template <class Real, Integer ORDER=10> class Stellarator {
         };
         if (S.Nsurf() >= 1) Ax0 += compute_A21adj( true) * x1;
         if (S.Nsurf() >= 2) Ax0 += compute_A21adj(false) * x2;
-
         if (S.Nsurf() == 1) { // Add flux part of Ax1, Ax2
           Real flux_tor, flux_pol;
           compute_flux(flux_tor, flux_pol, Bt0, normal);
@@ -2816,6 +2816,65 @@ template <class Real, Integer ORDER=10> class Stellarator {
         return x;
       };
 
+      if (0) { // Check u_t A v == v_t Aadj u
+        auto pack = [&S](Vector<Real>& x, const Vector<ElemBasis>& x0, Real x1, Real x2) {
+          const Long Nelem = S.NElem();
+          const Long Nnodes = ElemBasis::Size();
+          x.ReInit(Nelem*Nnodes+S.Nsurf());
+          for (Long i = 0; i < Nelem; i++) {
+            for (Long j = 0; j < Nnodes; j++) {
+              x[i*Nnodes+j] = x0[i][j];
+            }
+          }
+          if (S.Nsurf() >= 1) x[Nelem*Nnodes+0] = x1;
+          if (S.Nsurf() >= 2) x[Nelem*Nnodes+1] = x2;
+        };
+        auto unpack = [&S](Vector<ElemBasis>& x0, Real& x1, Real& x2, const Vector<Real>& x) {
+          const Long Nelem = S.NElem();
+          const Long Nnodes = ElemBasis::Size();
+          x0.ReInit(Nelem);
+          for (Long i = 0; i < Nelem; i++) {
+            for (Long j = 0; j < Nnodes; j++) {
+              x0[i][j] = x[i*Nnodes+j];
+            }
+          }
+          if (S.Nsurf() >= 1) x1 = x[Nelem*Nnodes+0];
+          if (S.Nsurf() >= 2) x2 = x[Nelem*Nnodes+1];
+        };
+        const Long Nelem = S.NElem();
+        const Long Nnodes = ElemBasis::Size();
+
+        Vector<ElemBasis> normal, area_elem;
+        compute_norm_area_elem(S, normal, area_elem);
+
+        Vector<Real> u, v;
+        Vector<ElemBasis> u0 = area_elem*0; Real u1 = 3.141, u2 = 0.4142;
+        Vector<ElemBasis> v0 = area_elem*0; Real v1 = 1.645, v2 = 3.6055;
+        { // Set u0, v0
+          auto X = S.GetElemList().ElemVector();
+          for (Long i = 0; i < Nelem; i++) {
+            for (Long j = 0; j < Nnodes; j++) {
+              u0[i][j] = X[i*COORD_DIM+0][j] + X[i*COORD_DIM+1][j] + X[i*COORD_DIM+2][j];
+              v0[i][j] = X[i*COORD_DIM+0][j] + X[i*COORD_DIM+1][j] + X[i*COORD_DIM+2][j];
+            }
+          }
+        }
+        pack(u,u0,u1,u2);
+        pack(v,v0,v1,v2);
+
+        Vector<Real> Av = compute_A(v);
+        Vector<Real> uA = compute_Aadj(u);
+
+        Vector<ElemBasis> Av0; Real Av1, Av2;
+        Vector<ElemBasis> uA0; Real uA1, uA2;
+        unpack(Av0, Av1, Av2, Av);
+        unpack(uA0, uA1, uA2, uA);
+
+        std::cout << compute_inner_prod(area_elem, u0, Av0) + u1*Av1 + (S.Nsurf()>=2?u2*Av2:0) << '\n';
+        std::cout << compute_inner_prod(area_elem, uA0, v0) + uA1*v1 + (S.Nsurf()>=2?uA2*v2:0) << '\n';
+        exit(0);
+      }
+
       /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -3618,199 +3677,6 @@ template <class Real, Integer ORDER=10> class Stellarator {
         alpha = (S.Nsurf() >= 1 ? x_[Nelem * Nnodes + 0] : 0);
         beta  = (S.Nsurf() >= 2 ? x_[Nelem * Nnodes + 1] : 0);
       };
-      auto compute_Aadj = [&S,&Bt0,&Bp0,&compute_flux] (const Vector<Real>& x) {
-        const Long Nelem = S.NElem();
-        const Long Nnodes = ElemBasis::Size();
-        SCTL_ASSERT(x.Dim() == Nelem*Nnodes+S.Nsurf());
-
-        Vector<ElemBasis> normal, area_elem;
-        compute_norm_area_elem(S, normal, area_elem);
-
-        Vector<ElemBasis> x0(Nelem);
-        for (Long i = 0; i < Nelem; i++) {
-          for (Long j = 0; j < Nnodes; j++) {
-            x0[i][j] = x[i*Nnodes+j];
-          }
-        }
-        Real x1 = (S.Nsurf() >= 1 ? x[Nelem*Nnodes + 0] : 0);
-        Real x2 = (S.Nsurf() >= 2 ? x[Nelem*Nnodes + 1] : 0);
-
-        Vector<ElemBasis> Ax0;
-        Real Ax1, Ax2;
-        { // Set Ax0, Ax1, Ax2
-          Vector<ElemBasis> x0_n(Nelem*COORD_DIM);
-          for (Long i = 0; i < Nelem; i++) {
-            for (Long j = 0; j < Nnodes; j++) {
-              x0_n[i*COORD_DIM+0][j] = x0[i][j] * normal[i*COORD_DIM+0][j];
-              x0_n[i*COORD_DIM+1][j] = x0[i][j] * normal[i*COORD_DIM+1][j];
-              x0_n[i*COORD_DIM+2][j] = x0[i][j] * normal[i*COORD_DIM+2][j];
-            }
-          }
-          EvalQuadrature(Ax0, S.quadrature_dUxF, S, x0_n, S.Laplace_dUxF);
-          Ax0 = x0*(-0.5) - Ax0;
-
-          Ax1 = (S.Nsurf() >= 1 ? compute_inner_prod(area_elem, compute_dot_prod(Bt0, normal), x0) : 0);
-          Ax2 = (S.Nsurf() >= 2 ? compute_inner_prod(area_elem, compute_dot_prod(Bp0, normal), x0) : 0);
-        }
-
-        auto compute_A21adj = [&S,&normal,&area_elem] (bool toroidal_flux) {
-          const Long Nelem = S.NElem();
-          const Long Nnodes = ElemBasis::Size();
-          Vector<ElemBasis> density(Nelem * COORD_DIM);
-          { // Set density
-            Real scal[2];
-            if (S.Nsurf() == 1) {
-              SCTL_ASSERT(toroidal_flux == true);
-              scal[0] = 1.0 / S.NTor(0);
-              scal[1] = 0;
-            } else if (S.Nsurf() == 2) {
-              if (toroidal_flux == true) {
-                scal[0] = -1.0 / S.NTor(0);
-                scal[1] = 1.0 / S.NTor(1);
-              } else {
-                scal[0] = 1.0 / S.NPol(0);
-                scal[1] = -1.0 / S.NPol(1);
-              }
-            } else {
-              SCTL_ASSERT(false);
-            }
-
-            Vector<ElemBasis> dX;
-            ElemBasis::Grad(dX, S.GetElemList().ElemVector());
-            for (Long k = 0; k < S.Nsurf(); k++) {
-              for (Long i_ = 0; i_ < S.NTor(k)*S.NPol(k); i_++) {
-                Long i = S.ElemDsp(k) + i_;
-                for (Long j = 0; j < Nnodes; j++) {
-                  Real s = scal[k] / area_elem[i][j];
-                  density[i*COORD_DIM+0][j] = dX[i*COORD_DIM*2+0+(toroidal_flux?1:0)][j] * s;
-                  density[i*COORD_DIM+1][j] = dX[i*COORD_DIM*2+2+(toroidal_flux?1:0)][j] * s;
-                  density[i*COORD_DIM+2][j] = dX[i*COORD_DIM*2+4+(toroidal_flux?1:0)][j] * s;
-                }
-              }
-            }
-          }
-
-          Vector<ElemBasis> Gdensity, nxGdensity(Nelem * COORD_DIM), A21adj;
-          EvalQuadrature(Gdensity, S.quadrature_FxU, S, density, S.Laplace_FxU);
-          for (Long i = 0; i < Nelem; i++) { // Set nxGdensity
-            for (Long j = 0; j < Nnodes; j++) {
-              Tensor<Real,true,COORD_DIM> Gdensity_, n;
-              Gdensity_(0) = Gdensity[i*COORD_DIM+0][j];
-              Gdensity_(1) = Gdensity[i*COORD_DIM+1][j];
-              Gdensity_(2) = Gdensity[i*COORD_DIM+2][j];
-
-              n(0) = normal[i*COORD_DIM+0][j];
-              n(1) = normal[i*COORD_DIM+1][j];
-              n(2) = normal[i*COORD_DIM+2][j];
-
-              nxGdensity[i*COORD_DIM+0][j] = n(1) * Gdensity_(2) - n(2) * Gdensity_(1);
-              nxGdensity[i*COORD_DIM+1][j] = n(2) * Gdensity_(0) - n(0) * Gdensity_(2);
-              nxGdensity[i*COORD_DIM+2][j] = n(0) * Gdensity_(1) - n(1) * Gdensity_(0);
-            }
-          }
-          EvalQuadrature(A21adj, S.quadrature_dUxF, S, nxGdensity, S.Laplace_dUxF);
-          return A21adj;
-        };
-        if (S.Nsurf() >= 1) Ax0 += compute_A21adj( true) * x1;
-        if (S.Nsurf() >= 2) Ax0 += compute_A21adj(false) * x2;
-
-        if (S.Nsurf() == 1) { // Add flux part of Ax1, Ax2
-          Real flux_tor, flux_pol;
-          compute_flux(flux_tor, flux_pol, Bt0, normal);
-          Ax1 += flux_tor * x1;
-          Ax2 += 0;
-        } else if (S.Nsurf() == 2) {
-          Real flux_tor, flux_pol;
-          compute_flux(flux_tor, flux_pol, Bt0, normal);
-          Ax1 += flux_tor * x1 + flux_pol * x2;
-          compute_flux(flux_tor, flux_pol, Bp0, normal);
-          Ax2 += flux_tor * x1 + flux_pol * x2;
-        } else {
-          SCTL_ASSERT(false);
-        }
-
-        Vector<Real> Ax(Nelem*Nnodes+S.Nsurf());
-        for (Long i = 0; i < Nelem; i++) {
-          for (Long j = 0; j < Nnodes; j++) {
-            Ax[i*Nnodes+j] = Ax0[i][j];
-          }
-        }
-        if (S.Nsurf() >= 1) Ax[Nelem*Nnodes + 0] = Ax1;
-        if (S.Nsurf() >= 2) Ax[Nelem*Nnodes + 1] = Ax2;
-        return Ax;
-      };
-      auto compute_invAadj = [&S,&comm,&compute_Aadj] (Vector<Real>& b) {
-        typename sctl::ParallelSolver<Real>::ParallelOp BIOp = [&compute_Aadj](sctl::Vector<Real>* Ax, const sctl::Vector<Real>& x) {
-          (*Ax) = compute_Aadj(x);
-        };
-        const Long Nelem = S.NElem();
-        const Long Nnodes = ElemBasis::Size();
-
-        Vector<Real> x(b.Dim());
-        x = 0;
-        ParallelSolver<Real> linear_solver(comm, true);
-        linear_solver(&x, BIOp, b, 1e-8, 100);
-        return x;
-      };
-
-      if (0) { // Check u_t A v == v_t Aadj u
-        auto pack = [&S](Vector<Real>& x, const Vector<ElemBasis>& x0, Real x1, Real x2) {
-          const Long Nelem = S.NElem();
-          const Long Nnodes = ElemBasis::Size();
-          x.ReInit(Nelem*Nnodes+S.Nsurf());
-          for (Long i = 0; i < Nelem; i++) {
-            for (Long j = 0; j < Nnodes; j++) {
-              x[i*Nnodes+j] = x0[i][j];
-            }
-          }
-          if (S.Nsurf() >= 1) x[Nelem*Nnodes+0] = x1;
-          if (S.Nsurf() >= 2) x[Nelem*Nnodes+1] = x2;
-        };
-        auto unpack = [&S](Vector<ElemBasis>& x0, Real& x1, Real& x2, const Vector<Real>& x) {
-          const Long Nelem = S.NElem();
-          const Long Nnodes = ElemBasis::Size();
-          x0.ReInit(Nelem);
-          for (Long i = 0; i < Nelem; i++) {
-            for (Long j = 0; j < Nnodes; j++) {
-              x0[i][j] = x[i*Nnodes+j];
-            }
-          }
-          if (S.Nsurf() >= 1) x1 = x[Nelem*Nnodes+0];
-          if (S.Nsurf() >= 2) x2 = x[Nelem*Nnodes+1];
-        };
-        const Long Nelem = S.NElem();
-        const Long Nnodes = ElemBasis::Size();
-
-        Vector<ElemBasis> normal, area_elem;
-        compute_norm_area_elem(S, normal, area_elem);
-
-        Vector<Real> u, v;
-        Vector<ElemBasis> u0 = area_elem*0; Real u1 = 3.141, u2 = 0.4142;
-        Vector<ElemBasis> v0 = area_elem*0; Real v1 = 1.645, v2 = 3.6055;
-        { // Set u0, v0
-          auto X = S.GetElemList().ElemVector();
-          for (Long i = 0; i < Nelem; i++) {
-            for (Long j = 0; j < Nnodes; j++) {
-              u0[i][j] = X[i*COORD_DIM+0][j] + X[i*COORD_DIM+1][j] + X[i*COORD_DIM+2][j];
-              v0[i][j] = X[i*COORD_DIM+0][j] + X[i*COORD_DIM+1][j] + X[i*COORD_DIM+2][j];
-            }
-          }
-        }
-        pack(u,u0,u1,u2);
-        pack(v,v0,v1,v2);
-
-        Vector<Real> Av = compute_A(v);
-        Vector<Real> uA = compute_Aadj(u);
-
-        Vector<ElemBasis> Av0; Real Av1, Av2;
-        Vector<ElemBasis> uA0; Real uA1, uA2;
-        unpack(Av0, Av1, Av2, Av);
-        unpack(uA0, uA1, uA2, uA);
-
-        std::cout << compute_inner_prod(area_elem, u0, Av0) + u1*Av1 + (S.Nsurf()>=2?u2*Av2:0) << '\n';
-        std::cout << compute_inner_prod(area_elem, uA0, v0) + uA1*v1 + (S.Nsurf()>=2?uA2*v2:0) << '\n';
-        exit(0);
-      }
 
       Vector<ElemBasis> dg_dnu = compute_gradient(S, pressure, flux_tor, flux_pol);
       { // Write VTU