|
@@ -3755,6 +3755,113 @@ template <class Real, Integer ORDER=10> class Stellarator {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ for (Long i = 0; i < S.Nsurf(); i++) { // filter dXdt
|
|
|
+ const Long Nt0 = S.NTor(i);
|
|
|
+ const Long Np0 = S.NPol(i);
|
|
|
+ const Long Nelem = Nt0 * Np0;
|
|
|
+ const Long offset = S.ElemDsp(i);
|
|
|
+ const Long Nnodes = ElemBasis::Size();
|
|
|
+ const Long INTERP_ORDER = 12;
|
|
|
+ const Long Nt = Nt0*ORDER/5;
|
|
|
+ const Long Np = Np0*ORDER/5;
|
|
|
+ for (Long k = 0; k < COORD_DIM; k++) {
|
|
|
+ Matrix<Real> M(Nt, Np); M = 0;
|
|
|
+ const auto& quad_wts = ElemBasis::QuadWts();
|
|
|
+ const Matrix<Real>& Mnodes = Basis<Real,1,ORDER>::Nodes();
|
|
|
+ for (Long tt = 0; tt < Nt0; tt++) { // Set M
|
|
|
+ for (Long pp = 0; pp < Np0; pp++) {
|
|
|
+ for (Long t = 0; t < ORDER; t++) {
|
|
|
+ for (Long p = 0; p < ORDER; p++) {
|
|
|
+ Real theta = (tt + Mnodes[0][t]) / Nt0;
|
|
|
+ Real phi = (pp + Mnodes[0][p]) / Np0;
|
|
|
+ Long i = (Long)(theta * Nt);
|
|
|
+ Long j = (Long)(phi * Np);
|
|
|
+ Real x = theta * Nt - i;
|
|
|
+ Real y = phi * Np - j;
|
|
|
+
|
|
|
+ Long elem_idx = tt * Np0 + pp;
|
|
|
+ Long node_idx = p * ORDER + t;
|
|
|
+
|
|
|
+ Vector<Real> Interp0(INTERP_ORDER);
|
|
|
+ Vector<Real> Interp1(INTERP_ORDER);
|
|
|
+ { // Set Interp0, Interp1
|
|
|
+ auto node = [] (Long i) {
|
|
|
+ return (Real)i - (INTERP_ORDER-1)/2;
|
|
|
+ };
|
|
|
+ for (Long i = 0; i < INTERP_ORDER; i++) {
|
|
|
+ Real wt_x = 1, wt_y = 1;
|
|
|
+ for (Long j = 0; j < INTERP_ORDER; j++) {
|
|
|
+ if (j != i) {
|
|
|
+ wt_x *= (x - node(j)) / (node(i) - node(j));
|
|
|
+ wt_y *= (y - node(j)) / (node(i) - node(j));
|
|
|
+ }
|
|
|
+ Interp0[i] = wt_x;
|
|
|
+ Interp1[i] = wt_y;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Long ii = 0; ii < INTERP_ORDER; ii++) {
|
|
|
+ for (Long jj = 0; jj < INTERP_ORDER; jj++) {
|
|
|
+ Long idx_i = (i + ii-(INTERP_ORDER-1)/2 + Nt) % Nt;
|
|
|
+ Long idx_j = (j + jj-(INTERP_ORDER-1)/2 + Np) % Np;
|
|
|
+ M[idx_i][idx_j] += dXdt[(offset+elem_idx)*COORD_DIM+k][node_idx] * quad_wts[node_idx] * Interp0[ii] * Interp1[jj] / (Nt0 * Np0) * (Nt * Np);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Long tt = 0; tt < Nt0; tt++) {
|
|
|
+ for (Long pp = 0; pp < Np0; pp++) {
|
|
|
+ for (Long t = 0; t < ORDER; t++) {
|
|
|
+ for (Long p = 0; p < ORDER; p++) {
|
|
|
+ Matrix<Real> Mnodes = Basis<Real,1,ORDER>::Nodes();
|
|
|
+ Real theta = (tt + Mnodes[0][t]) / Nt0;
|
|
|
+ Real phi = (pp + Mnodes[0][p]) / Np0;
|
|
|
+ Long i = (Long)(theta * Nt);
|
|
|
+ Long j = (Long)(phi * Np);
|
|
|
+ Real x = theta * Nt - i;
|
|
|
+ Real y = phi * Np - j;
|
|
|
+
|
|
|
+ Vector<Real> Interp0(INTERP_ORDER);
|
|
|
+ Vector<Real> Interp1(INTERP_ORDER);
|
|
|
+ { // Set Interp0, Interp1
|
|
|
+ auto node = [] (Long i) {
|
|
|
+ return (Real)i - (INTERP_ORDER-1)/2;
|
|
|
+ };
|
|
|
+ for (Long i = 0; i < INTERP_ORDER; i++) {
|
|
|
+ Real wt_x = 1, wt_y = 1;
|
|
|
+ for (Long j = 0; j < INTERP_ORDER; j++) {
|
|
|
+ if (j != i) {
|
|
|
+ wt_x *= (x - node(j)) / (node(i) - node(j));
|
|
|
+ wt_y *= (y - node(j)) / (node(i) - node(j));
|
|
|
+ }
|
|
|
+ Interp0[i] = wt_x;
|
|
|
+ Interp1[i] = wt_y;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Real f0 = 0;
|
|
|
+ for (Long ii = 0; ii < INTERP_ORDER; ii++) {
|
|
|
+ for (Long jj = 0; jj < INTERP_ORDER; jj++) {
|
|
|
+ Long idx_i = (i + ii-(INTERP_ORDER-1)/2 + Nt) % Nt;
|
|
|
+ Long idx_j = (j + jj-(INTERP_ORDER-1)/2 + Np) % Np;
|
|
|
+ f0 += Interp0[ii] * Interp1[jj] * M[idx_i][idx_j];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Long elem_idx = tt * Np0 + pp;
|
|
|
+ Long node_idx = p * ORDER + t;
|
|
|
+ dXdt[(offset+elem_idx)*COORD_DIM+k][node_idx] = f0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
{ // Update S, dt
|
|
|
Stellarator<Real,ORDER> S0 = S, S1 = S, S2 = S;
|