File: polynomials_rt_bubbles.cc

package info (click to toggle)
deal.ii 9.7.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 326,024 kB
  • sloc: cpp: 440,899; ansic: 77,337; python: 3,307; perl: 1,041; sh: 1,022; xml: 252; makefile: 97; javascript: 14
file content (864 lines) | stat: -rw-r--r-- 47,179 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
// ------------------------------------------------------------------------
//
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) 2018 - 2024 by the deal.II authors
//
// This file is part of the deal.II library.
//
// Part of the source code is dual licensed under Apache-2.0 WITH
// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
// governing the source code and code contributions can be found in
// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
//
// ------------------------------------------------------------------------


#include <deal.II/base/polynomials_rt_bubbles.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/thread_management.h>

#include <iomanip>
#include <iostream>
#include <memory>

DEAL_II_NAMESPACE_OPEN


template <int dim>
PolynomialsRT_Bubbles<dim>::PolynomialsRT_Bubbles(const unsigned int k)
  : TensorPolynomialsBase<dim>(k, n_polynomials(k))
  , raviart_thomas_space(k - 1)
  , monomials(k + 2)
{
  Assert(dim >= 2, ExcImpossibleInDim(dim));

  for (unsigned int i = 0; i < monomials.size(); ++i)
    monomials[i] = Polynomials::Monomial<double>(i);
}



template <int dim>
void
PolynomialsRT_Bubbles<dim>::evaluate(
  const Point<dim>            &unit_point,
  std::vector<Tensor<1, dim>> &values,
  std::vector<Tensor<2, dim>> &grads,
  std::vector<Tensor<3, dim>> &grad_grads,
  std::vector<Tensor<4, dim>> &third_derivatives,
  std::vector<Tensor<5, dim>> &fourth_derivatives) const
{
  Assert(values.size() == this->n() || values.empty(),
         ExcDimensionMismatch(values.size(), this->n()));
  Assert(grads.size() == this->n() || grads.empty(),
         ExcDimensionMismatch(grads.size(), this->n()));
  Assert(grad_grads.size() == this->n() || grad_grads.empty(),
         ExcDimensionMismatch(grad_grads.size(), this->n()));
  Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
         ExcDimensionMismatch(third_derivatives.size(), this->n()));
  Assert(fourth_derivatives.size() == this->n() || fourth_derivatives.empty(),
         ExcDimensionMismatch(fourth_derivatives.size(), this->n()));

  // Third and fourth derivatives are not implemented
  (void)third_derivatives;
  Assert(third_derivatives.empty(), ExcNotImplemented());
  (void)fourth_derivatives;
  Assert(fourth_derivatives.empty(), ExcNotImplemented());

  const unsigned int n_sub     = raviart_thomas_space.n();
  const unsigned int my_degree = this->degree();

  // Guard access to the scratch arrays in the following block
  // using a mutex to make sure they are not used by multiple threads
  // at once
  {
    static std::mutex           mutex;
    std::lock_guard<std::mutex> lock(mutex);

    static std::vector<Tensor<1, dim>> p_values;
    static std::vector<Tensor<2, dim>> p_grads;
    static std::vector<Tensor<3, dim>> p_grad_grads;
    static std::vector<Tensor<4, dim>> p_third_derivatives;
    static std::vector<Tensor<5, dim>> p_fourth_derivatives;

    p_values.resize((values.empty()) ? 0 : n_sub);
    p_grads.resize((grads.empty()) ? 0 : n_sub);
    p_grad_grads.resize((grad_grads.empty()) ? 0 : n_sub);

    // This is the Raviart-Thomas part of the space
    raviart_thomas_space.evaluate(unit_point,
                                  p_values,
                                  p_grads,
                                  p_grad_grads,
                                  p_third_derivatives,
                                  p_fourth_derivatives);
    for (unsigned int i = 0; i < p_values.size(); ++i)
      values[i] = p_values[i];
    for (unsigned int i = 0; i < p_grads.size(); ++i)
      grads[i] = p_grads[i];
    for (unsigned int i = 0; i < p_grad_grads.size(); ++i)
      grad_grads[i] = p_grad_grads[i];
  }

  // Next we compute the polynomials and derivatives
  // of the curl part of the space
  const unsigned int n_derivatives = 3;
  double             monoval_plus[dim][n_derivatives + 1];
  double             monoval_i[dim][n_derivatives + 1];


  if constexpr (dim <= 1)
    {
      (void)monoval_plus;
      (void)monoval_i;
    }

  unsigned int start = n_sub;
  if constexpr (dim == 2)
    {
      // In 2d the curl part of the space is spanned by the vectors
      // of two types. The first one is
      //    [ x^i * [y^(k+1)]'  ]
      //    [ -[x^i]' * y^(k+1) ]
      // The second one can be obtained from the first by a cyclic
      // rotation of the coordinates.
      //  monoval_i = x^i,
      //  monoval_plus = x^(k+1)
      for (unsigned int d = 0; d < dim; ++d)
        monomials[my_degree + 1].value(unit_point[d],
                                       n_derivatives,
                                       monoval_plus[d]);

      for (unsigned int i = 0; i <= my_degree; ++i, ++start)
        {
          for (unsigned int d = 0; d < dim; ++d)
            monomials[i].value(unit_point[d], n_derivatives, monoval_i[d]);

          if (values.size() != 0)
            {
              values[start][0] = monoval_i[0][0] * monoval_plus[1][1];
              values[start][1] = -monoval_i[0][1] * monoval_plus[1][0];

              values[start + my_degree + 1][0] =
                -monoval_plus[0][0] * monoval_i[1][1];
              values[start + my_degree + 1][1] =
                monoval_plus[0][1] * monoval_i[1][0];
            }

          if (grads.size() != 0)
            {
              grads[start][0][0] = monoval_i[0][1] * monoval_plus[1][1];
              grads[start][0][1] = monoval_i[0][0] * monoval_plus[1][2];
              grads[start][1][0] = -monoval_i[0][2] * monoval_plus[1][0];
              grads[start][1][1] = -monoval_i[0][1] * monoval_plus[1][1];

              grads[start + my_degree + 1][0][0] =
                -monoval_plus[0][1] * monoval_i[1][1];
              grads[start + my_degree + 1][0][1] =
                -monoval_plus[0][0] * monoval_i[1][2];
              grads[start + my_degree + 1][1][0] =
                monoval_plus[0][2] * monoval_i[1][0];
              grads[start + my_degree + 1][1][1] =
                monoval_plus[0][1] * monoval_i[1][1];
            }

          if (grad_grads.size() != 0)
            {
              grad_grads[start][0][0][0] = monoval_i[0][2] * monoval_plus[1][1];
              grad_grads[start][0][0][1] = monoval_i[0][1] * monoval_plus[1][2];
              grad_grads[start][0][1][0] = monoval_i[0][1] * monoval_plus[1][2];
              grad_grads[start][0][1][1] = monoval_i[0][0] * monoval_plus[1][3];
              grad_grads[start][1][0][0] =
                -monoval_i[0][3] * monoval_plus[1][0];
              grad_grads[start][1][0][1] =
                -monoval_i[0][2] * monoval_plus[1][1];
              grad_grads[start][1][1][0] =
                -monoval_i[0][2] * monoval_plus[1][1];
              grad_grads[start][1][1][1] =
                -monoval_i[0][1] * monoval_plus[1][2];

              grad_grads[start + my_degree + 1][0][0][0] =
                -monoval_plus[0][2] * monoval_i[1][1];
              grad_grads[start + my_degree + 1][0][0][1] =
                -monoval_plus[0][1] * monoval_i[1][2];
              grad_grads[start + my_degree + 1][0][1][0] =
                -monoval_plus[0][1] * monoval_i[1][2];
              grad_grads[start + my_degree + 1][0][1][1] =
                -monoval_plus[0][0] * monoval_i[1][3];
              grad_grads[start + my_degree + 1][1][0][0] =
                monoval_plus[0][3] * monoval_i[1][0];
              grad_grads[start + my_degree + 1][1][0][1] =
                monoval_plus[0][2] * monoval_i[1][1];
              grad_grads[start + my_degree + 1][1][1][0] =
                monoval_plus[0][2] * monoval_i[1][1];
              grad_grads[start + my_degree + 1][1][1][1] =
                monoval_plus[0][1] * monoval_i[1][2];
            }
        }
      Assert(start == this->n() - my_degree - 1, ExcInternalError());
    }
  else if constexpr (dim == 3)
    {
      double monoval[dim][n_derivatives + 1];
      double monoval_j[dim][n_derivatives + 1];
      double monoval_jplus[dim][n_derivatives + 1];

      // In 3d the first type of basis vector is
      //  [ x^i * y^j * z^k * (j+k+2) ]
      //  [  -[x^i]' * y^(j+1) * z^k  ]
      //  [  -[x^i]' * y^j * z^(k+1)  ],
      // For the second type of basis vector y and z
      // are swapped. Then for each of these,
      // two more are obtained by the cyclic rotation
      // of the coordinates.
      //  monoval = x^k,   monoval_plus = x^(k+1)
      //  monoval_* = x^*, monoval_jplus = x^(j+1)
      for (unsigned int d = 0; d < dim; ++d)
        {
          monomials[my_degree + 1].value(unit_point[d],
                                         n_derivatives,
                                         monoval_plus[d]);
          monomials[my_degree].value(unit_point[d], n_derivatives, monoval[d]);
        }

      const unsigned int n_curls = (my_degree + 1) * (2 * my_degree + 1);
      // Span of $\tilde{B}$
      for (unsigned int i = 0; i <= my_degree; ++i)
        {
          for (unsigned int d = 0; d < dim; ++d)
            monomials[i].value(unit_point[d], n_derivatives, monoval_i[d]);

          for (unsigned int j = 0; j <= my_degree; ++j)
            {
              for (unsigned int d = 0; d < dim; ++d)
                {
                  monomials[j].value(unit_point[d],
                                     n_derivatives,
                                     monoval_j[d]);
                  monomials[j + 1].value(unit_point[d],
                                         n_derivatives,
                                         monoval_jplus[d]);
                }

              if (values.size() != 0)
                {
                  values[start][0] = monoval_i[0][0] * monoval_j[1][0] *
                                     monoval[2][0] *
                                     static_cast<double>(j + my_degree + 2);
                  values[start][1] =
                    -monoval_i[0][1] * monoval_jplus[1][0] * monoval[2][0];
                  values[start][2] =
                    -monoval_i[0][1] * monoval_j[1][0] * monoval_plus[2][0];

                  values[start + n_curls][0] =
                    -monoval_jplus[0][0] * monoval_i[1][1] * monoval[2][0];
                  values[start + n_curls][1] =
                    monoval_j[0][0] * monoval_i[1][0] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  values[start + n_curls][2] =
                    -monoval_j[0][0] * monoval_i[1][1] * monoval_plus[2][0];

                  values[start + 2 * n_curls][0] =
                    -monoval_jplus[0][0] * monoval[1][0] * monoval_i[2][1];
                  values[start + 2 * n_curls][1] =
                    -monoval_j[0][0] * monoval_plus[1][0] * monoval_i[2][1];
                  values[start + 2 * n_curls][2] =
                    monoval_j[0][0] * monoval[1][0] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);

                  // Only unique triples of powers (i j k)
                  // and (i k j) are allowed, 0 <= i,j <= k
                  if (j != my_degree)
                    {
                      values[start + 1][0] =
                        monoval_i[0][0] * monoval[1][0] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      values[start + 1][1] =
                        -monoval_i[0][1] * monoval_plus[1][0] * monoval_j[2][0];
                      values[start + 1][2] =
                        -monoval_i[0][1] * monoval[1][0] * monoval_jplus[2][0];

                      values[start + n_curls + 1][0] =
                        -monoval_plus[0][0] * monoval_i[1][1] * monoval_j[2][0];
                      values[start + n_curls + 1][1] =
                        monoval[0][0] * monoval_i[1][0] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      values[start + n_curls + 1][2] =
                        -monoval[0][0] * monoval_i[1][1] * monoval_jplus[2][0];

                      values[start + 2 * n_curls + 1][0] =
                        -monoval_plus[0][0] * monoval_j[1][0] * monoval_i[2][1];
                      values[start + 2 * n_curls + 1][1] =
                        -monoval[0][0] * monoval_jplus[1][0] * monoval_i[2][1];
                      values[start + 2 * n_curls + 1][2] =
                        monoval[0][0] * monoval_j[1][0] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                    }
                }

              if (grads.size() != 0)
                {
                  grads[start][0][0] = monoval_i[0][1] * monoval_j[1][0] *
                                       monoval[2][0] *
                                       static_cast<double>(j + my_degree + 2);
                  grads[start][0][1] = monoval_i[0][0] * monoval_j[1][1] *
                                       monoval[2][0] *
                                       static_cast<double>(j + my_degree + 2);
                  grads[start][0][2] = monoval_i[0][0] * monoval_j[1][0] *
                                       monoval[2][1] *
                                       static_cast<double>(j + my_degree + 2);
                  grads[start][1][0] =
                    -monoval_i[0][2] * monoval_jplus[1][0] * monoval[2][0];
                  grads[start][1][1] =
                    -monoval_i[0][1] * monoval_jplus[1][1] * monoval[2][0];
                  grads[start][1][2] =
                    -monoval_i[0][1] * monoval_jplus[1][0] * monoval[2][1];
                  grads[start][2][0] =
                    -monoval_i[0][2] * monoval_j[1][0] * monoval_plus[2][0];
                  grads[start][2][1] =
                    -monoval_i[0][1] * monoval_j[1][1] * monoval_plus[2][0];
                  grads[start][2][2] =
                    -monoval_i[0][1] * monoval_j[1][0] * monoval_plus[2][1];

                  grads[start + n_curls][0][0] =
                    -monoval_jplus[0][1] * monoval_i[1][1] * monoval[2][0];
                  grads[start + n_curls][0][1] =
                    -monoval_jplus[0][0] * monoval_i[1][2] * monoval[2][0];
                  grads[start + n_curls][0][2] =
                    -monoval_jplus[0][0] * monoval_i[1][1] * monoval[2][1];
                  grads[start + n_curls][1][0] =
                    monoval_j[0][1] * monoval_i[1][0] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grads[start + n_curls][1][1] =
                    monoval_j[0][0] * monoval_i[1][1] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grads[start + n_curls][1][2] =
                    monoval_j[0][0] * monoval_i[1][0] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grads[start + n_curls][2][0] =
                    -monoval_j[0][1] * monoval_i[1][1] * monoval_plus[2][0];
                  grads[start + n_curls][2][1] =
                    -monoval_j[0][0] * monoval_i[1][2] * monoval_plus[2][0];
                  grads[start + n_curls][2][2] =
                    -monoval_j[0][0] * monoval_i[1][1] * monoval_plus[2][1];

                  grads[start + 2 * n_curls][0][0] =
                    -monoval_jplus[0][1] * monoval[1][0] * monoval_i[2][1];
                  grads[start + 2 * n_curls][0][1] =
                    -monoval_jplus[0][0] * monoval[1][1] * monoval_i[2][1];
                  grads[start + 2 * n_curls][0][2] =
                    -monoval_jplus[0][0] * monoval[1][0] * monoval_i[2][2];
                  grads[start + 2 * n_curls][1][0] =
                    -monoval_j[0][1] * monoval_plus[1][0] * monoval_i[2][1];
                  grads[start + 2 * n_curls][1][1] =
                    -monoval_j[0][0] * monoval_plus[1][1] * monoval_i[2][1];
                  grads[start + 2 * n_curls][1][2] =
                    -monoval_j[0][0] * monoval_plus[1][0] * monoval_i[2][2];
                  grads[start + 2 * n_curls][2][0] =
                    monoval_j[0][1] * monoval[1][0] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grads[start + 2 * n_curls][2][1] =
                    monoval_j[0][0] * monoval[1][1] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grads[start + 2 * n_curls][2][2] =
                    monoval_j[0][0] * monoval[1][0] * monoval_i[2][1] *
                    static_cast<double>(j + my_degree + 2);

                  if (j != my_degree)
                    {
                      grads[start + 1][0][0] =
                        monoval_i[0][1] * monoval[1][0] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + 1][0][1] =
                        monoval_i[0][0] * monoval[1][1] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + 1][0][2] =
                        monoval_i[0][0] * monoval[1][0] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + 1][1][0] =
                        -monoval_i[0][2] * monoval_plus[1][0] * monoval_j[2][0];
                      grads[start + 1][1][1] =
                        -monoval_i[0][1] * monoval_plus[1][1] * monoval_j[2][0];
                      grads[start + 1][1][2] =
                        -monoval_i[0][1] * monoval_plus[1][0] * monoval_j[2][1];
                      grads[start + 1][2][0] =
                        -monoval_i[0][2] * monoval[1][0] * monoval_jplus[2][0];
                      grads[start + 1][2][1] =
                        -monoval_i[0][1] * monoval[1][1] * monoval_jplus[2][0];
                      grads[start + 1][2][2] =
                        -monoval_i[0][1] * monoval[1][0] * monoval_jplus[2][1];

                      grads[start + n_curls + 1][0][0] =
                        -monoval_plus[0][1] * monoval_i[1][1] * monoval_j[2][0];
                      grads[start + n_curls + 1][0][1] =
                        -monoval_plus[0][0] * monoval_i[1][2] * monoval_j[2][0];
                      grads[start + n_curls + 1][0][2] =
                        -monoval_plus[0][0] * monoval_i[1][1] * monoval_j[2][1];
                      grads[start + n_curls + 1][1][0] =
                        monoval[0][1] * monoval_i[1][0] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + n_curls + 1][1][1] =
                        monoval[0][0] * monoval_i[1][1] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + n_curls + 1][1][2] =
                        monoval[0][0] * monoval_i[1][0] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + n_curls + 1][2][0] =
                        -monoval[0][1] * monoval_i[1][1] * monoval_jplus[2][0];
                      grads[start + n_curls + 1][2][1] =
                        -monoval[0][0] * monoval_i[1][2] * monoval_jplus[2][0];
                      grads[start + n_curls + 1][2][2] =
                        -monoval[0][0] * monoval_i[1][1] * monoval_jplus[2][1];

                      grads[start + 2 * n_curls + 1][0][0] =
                        -monoval_plus[0][1] * monoval_j[1][0] * monoval_i[2][1];
                      grads[start + 2 * n_curls + 1][0][1] =
                        -monoval_plus[0][0] * monoval_j[1][1] * monoval_i[2][1];
                      grads[start + 2 * n_curls + 1][0][2] =
                        -monoval_plus[0][0] * monoval_j[1][0] * monoval_i[2][2];
                      grads[start + 2 * n_curls + 1][1][0] =
                        -monoval[0][1] * monoval_jplus[1][0] * monoval_i[2][1];
                      grads[start + 2 * n_curls + 1][1][1] =
                        -monoval[0][0] * monoval_jplus[1][1] * monoval_i[2][1];
                      grads[start + 2 * n_curls + 1][1][2] =
                        -monoval[0][0] * monoval_jplus[1][0] * monoval_i[2][2];
                      grads[start + 2 * n_curls + 1][2][0] =
                        monoval[0][1] * monoval_j[1][0] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + 2 * n_curls + 1][2][1] =
                        monoval[0][0] * monoval_j[1][1] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grads[start + 2 * n_curls + 1][2][2] =
                        monoval[0][0] * monoval_j[1][0] * monoval_i[2][1] *
                        static_cast<double>(j + my_degree + 2);
                    }
                }

              if (grad_grads.size() != 0)
                {
                  grad_grads[start][0][0][0] =
                    monoval_i[0][2] * monoval_j[1][0] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][0][1] =
                    monoval_i[0][1] * monoval_j[1][1] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][0][2] =
                    monoval_i[0][1] * monoval_j[1][0] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][1][0] =
                    monoval_i[0][1] * monoval_j[1][1] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][1][1] =
                    monoval_i[0][0] * monoval_j[1][2] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][1][2] =
                    monoval_i[0][0] * monoval_j[1][1] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][2][0] =
                    monoval_i[0][1] * monoval_j[1][0] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][2][1] =
                    monoval_i[0][0] * monoval_j[1][1] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][0][2][2] =
                    monoval_i[0][0] * monoval_j[1][0] * monoval[2][2] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start][1][0][0] =
                    -monoval_i[0][3] * monoval_jplus[1][0] * monoval[2][0];
                  grad_grads[start][1][0][1] =
                    -monoval_i[0][2] * monoval_jplus[1][1] * monoval[2][0];
                  grad_grads[start][1][0][2] =
                    -monoval_i[0][2] * monoval_jplus[1][0] * monoval[2][1];
                  grad_grads[start][1][1][0] =
                    -monoval_i[0][2] * monoval_jplus[1][1] * monoval[2][0];
                  grad_grads[start][1][1][1] =
                    -monoval_i[0][1] * monoval_jplus[1][2] * monoval[2][0];
                  grad_grads[start][1][1][2] =
                    -monoval_i[0][1] * monoval_jplus[1][1] * monoval[2][1];
                  grad_grads[start][1][2][0] =
                    -monoval_i[0][2] * monoval_jplus[1][0] * monoval[2][1];
                  grad_grads[start][1][2][1] =
                    -monoval_i[0][1] * monoval_jplus[1][1] * monoval[2][1];
                  grad_grads[start][1][2][2] =
                    -monoval_i[0][1] * monoval_jplus[1][0] * monoval[2][2];
                  grad_grads[start][2][0][0] =
                    -monoval_i[0][3] * monoval_j[1][0] * monoval_plus[2][0];
                  grad_grads[start][2][0][1] =
                    -monoval_i[0][2] * monoval_j[1][1] * monoval_plus[2][0];
                  grad_grads[start][2][0][2] =
                    -monoval_i[0][2] * monoval_j[1][0] * monoval_plus[2][1];
                  grad_grads[start][2][1][0] =
                    -monoval_i[0][2] * monoval_j[1][1] * monoval_plus[2][0];
                  grad_grads[start][2][1][1] =
                    -monoval_i[0][1] * monoval_j[1][2] * monoval_plus[2][0];
                  grad_grads[start][2][1][2] =
                    -monoval_i[0][1] * monoval_j[1][1] * monoval_plus[2][1];
                  grad_grads[start][2][2][0] =
                    -monoval_i[0][2] * monoval_j[1][0] * monoval_plus[2][1];
                  grad_grads[start][2][2][1] =
                    -monoval_i[0][1] * monoval_j[1][1] * monoval_plus[2][1];
                  grad_grads[start][2][2][2] =
                    -monoval_i[0][1] * monoval_j[1][0] * monoval_plus[2][2];

                  grad_grads[start + n_curls][0][0][0] =
                    -monoval_jplus[0][2] * monoval_i[1][1] * monoval[2][0];
                  grad_grads[start + n_curls][0][0][1] =
                    -monoval_jplus[0][1] * monoval_i[1][2] * monoval[2][0];
                  grad_grads[start + n_curls][0][0][2] =
                    -monoval_jplus[0][1] * monoval_i[1][1] * monoval[2][1];
                  grad_grads[start + n_curls][0][1][0] =
                    -monoval_jplus[0][1] * monoval_i[1][2] * monoval[2][0];
                  grad_grads[start + n_curls][0][1][1] =
                    -monoval_jplus[0][0] * monoval_i[1][3] * monoval[2][0];
                  grad_grads[start + n_curls][0][1][2] =
                    -monoval_jplus[0][0] * monoval_i[1][2] * monoval[2][1];
                  grad_grads[start + n_curls][0][2][0] =
                    -monoval_jplus[0][1] * monoval_i[1][1] * monoval[2][1];
                  grad_grads[start + n_curls][0][2][1] =
                    -monoval_jplus[0][0] * monoval_i[1][2] * monoval[2][1];
                  grad_grads[start + n_curls][0][2][2] =
                    -monoval_jplus[0][0] * monoval_i[1][1] * monoval[2][2];
                  grad_grads[start + n_curls][1][0][0] =
                    monoval_j[0][2] * monoval_i[1][0] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][0][1] =
                    monoval_j[0][1] * monoval_i[1][1] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][0][2] =
                    monoval_j[0][1] * monoval_i[1][0] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][1][0] =
                    monoval_j[0][1] * monoval_i[1][1] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][1][1] =
                    monoval_j[0][0] * monoval_i[1][2] * monoval[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][1][2] =
                    monoval_j[0][0] * monoval_i[1][1] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][2][0] =
                    monoval_j[0][1] * monoval_i[1][0] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][2][1] =
                    monoval_j[0][0] * monoval_i[1][1] * monoval[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][1][2][2] =
                    monoval_j[0][0] * monoval_i[1][0] * monoval[2][2] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + n_curls][2][0][0] =
                    -monoval_j[0][2] * monoval_i[1][1] * monoval_plus[2][0];
                  grad_grads[start + n_curls][2][0][1] =
                    -monoval_j[0][1] * monoval_i[1][2] * monoval_plus[2][0];
                  grad_grads[start + n_curls][2][0][2] =
                    -monoval_j[0][1] * monoval_i[1][1] * monoval_plus[2][1];
                  grad_grads[start + n_curls][2][1][0] =
                    -monoval_j[0][1] * monoval_i[1][2] * monoval_plus[2][0];
                  grad_grads[start + n_curls][2][1][1] =
                    -monoval_j[0][0] * monoval_i[1][3] * monoval_plus[2][0];
                  grad_grads[start + n_curls][2][1][2] =
                    -monoval_j[0][0] * monoval_i[1][2] * monoval_plus[2][1];
                  grad_grads[start + n_curls][2][2][0] =
                    -monoval_j[0][1] * monoval_i[1][1] * monoval_plus[2][1];
                  grad_grads[start + n_curls][2][2][1] =
                    -monoval_j[0][0] * monoval_i[1][2] * monoval_plus[2][1];
                  grad_grads[start + n_curls][2][2][2] =
                    -monoval_j[0][0] * monoval_i[1][1] * monoval_plus[2][2];

                  grad_grads[start + 2 * n_curls][0][0][0] =
                    -monoval_jplus[0][2] * monoval[1][0] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][0][0][1] =
                    -monoval_jplus[0][1] * monoval[1][1] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][0][0][2] =
                    -monoval_jplus[0][1] * monoval[1][0] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][0][1][0] =
                    -monoval_jplus[0][1] * monoval[1][1] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][0][1][1] =
                    -monoval_jplus[0][0] * monoval[1][2] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][0][1][2] =
                    -monoval_jplus[0][0] * monoval[1][1] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][0][2][0] =
                    -monoval_jplus[0][1] * monoval[1][0] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][0][2][1] =
                    -monoval_jplus[0][0] * monoval[1][1] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][0][2][2] =
                    -monoval_jplus[0][0] * monoval[1][0] * monoval_i[2][3];
                  grad_grads[start + 2 * n_curls][1][0][0] =
                    -monoval_j[0][2] * monoval_plus[1][0] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][1][0][1] =
                    -monoval_j[0][1] * monoval_plus[1][1] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][1][0][2] =
                    -monoval_j[0][1] * monoval_plus[1][0] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][1][1][0] =
                    -monoval_j[0][1] * monoval_plus[1][1] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][1][1][1] =
                    -monoval_j[0][0] * monoval_plus[1][2] * monoval_i[2][1];
                  grad_grads[start + 2 * n_curls][1][1][2] =
                    -monoval_j[0][0] * monoval_plus[1][1] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][1][2][0] =
                    -monoval_j[0][1] * monoval_plus[1][0] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][1][2][1] =
                    -monoval_j[0][0] * monoval_plus[1][1] * monoval_i[2][2];
                  grad_grads[start + 2 * n_curls][1][2][2] =
                    -monoval_j[0][0] * monoval_plus[1][0] * monoval_i[2][3];
                  grad_grads[start + 2 * n_curls][2][0][0] =
                    monoval_j[0][2] * monoval[1][0] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][0][1] =
                    monoval_j[0][1] * monoval[1][1] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][0][2] =
                    monoval_j[0][1] * monoval[1][0] * monoval_i[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][1][0] =
                    monoval_j[0][1] * monoval[1][1] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][1][1] =
                    monoval_j[0][0] * monoval[1][2] * monoval_i[2][0] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][1][2] =
                    monoval_j[0][0] * monoval[1][1] * monoval_i[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][2][0] =
                    monoval_j[0][1] * monoval[1][0] * monoval_i[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][2][1] =
                    monoval_j[0][0] * monoval[1][1] * monoval_i[2][1] *
                    static_cast<double>(j + my_degree + 2);
                  grad_grads[start + 2 * n_curls][2][2][2] =
                    monoval_j[0][0] * monoval[1][0] * monoval_i[2][2] *
                    static_cast<double>(j + my_degree + 2);

                  if (j != my_degree)
                    {
                      grad_grads[start + 1][0][0][0] =
                        monoval_i[0][2] * monoval[1][0] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][0][1] =
                        monoval_i[0][1] * monoval[1][1] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][0][2] =
                        monoval_i[0][1] * monoval[1][0] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][1][0] =
                        monoval_i[0][1] * monoval[1][1] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][1][1] =
                        monoval_i[0][0] * monoval[1][2] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][1][2] =
                        monoval_i[0][0] * monoval[1][1] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][2][0] =
                        monoval_i[0][1] * monoval[1][0] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][2][1] =
                        monoval_i[0][0] * monoval[1][1] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][0][2][2] =
                        monoval_i[0][0] * monoval[1][0] * monoval_j[2][2] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 1][1][0][0] =
                        -monoval_i[0][3] * monoval_plus[1][0] * monoval_j[2][0];
                      grad_grads[start + 1][1][0][1] =
                        -monoval_i[0][2] * monoval_plus[1][1] * monoval_j[2][0];
                      grad_grads[start + 1][1][0][2] =
                        -monoval_i[0][2] * monoval_plus[1][0] * monoval_j[2][1];
                      grad_grads[start + 1][1][1][0] =
                        -monoval_i[0][2] * monoval_plus[1][1] * monoval_j[2][0];
                      grad_grads[start + 1][1][1][1] =
                        -monoval_i[0][1] * monoval_plus[1][2] * monoval_j[2][0];
                      grad_grads[start + 1][1][1][2] =
                        -monoval_i[0][1] * monoval_plus[1][1] * monoval_j[2][1];
                      grad_grads[start + 1][1][2][0] =
                        -monoval_i[0][2] * monoval_plus[1][0] * monoval_j[2][1];
                      grad_grads[start + 1][1][2][1] =
                        -monoval_i[0][1] * monoval_plus[1][1] * monoval_j[2][1];
                      grad_grads[start + 1][1][2][2] =
                        -monoval_i[0][1] * monoval_plus[1][0] * monoval_j[2][2];
                      grad_grads[start + 1][2][0][0] =
                        -monoval_i[0][3] * monoval[1][0] * monoval_jplus[2][0];
                      grad_grads[start + 1][2][0][1] =
                        -monoval_i[0][2] * monoval[1][1] * monoval_jplus[2][0];
                      grad_grads[start + 1][2][0][2] =
                        -monoval_i[0][2] * monoval[1][0] * monoval_jplus[2][1];
                      grad_grads[start + 1][2][1][0] =
                        -monoval_i[0][2] * monoval[1][1] * monoval_jplus[2][0];
                      grad_grads[start + 1][2][1][1] =
                        -monoval_i[0][1] * monoval[1][2] * monoval_jplus[2][0];
                      grad_grads[start + 1][2][1][2] =
                        -monoval_i[0][1] * monoval[1][1] * monoval_jplus[2][1];
                      grad_grads[start + 1][2][2][0] =
                        -monoval_i[0][2] * monoval[1][0] * monoval_jplus[2][1];
                      grad_grads[start + 1][2][2][1] =
                        -monoval_i[0][1] * monoval[1][1] * monoval_jplus[2][1];
                      grad_grads[start + 1][2][2][2] =
                        -monoval_i[0][1] * monoval[1][0] * monoval_jplus[2][2];

                      grad_grads[start + n_curls + 1][0][0][0] =
                        -monoval_plus[0][2] * monoval_i[1][1] * monoval_j[2][0];
                      grad_grads[start + n_curls + 1][0][0][1] =
                        -monoval_plus[0][1] * monoval_i[1][2] * monoval_j[2][0];
                      grad_grads[start + n_curls + 1][0][0][2] =
                        -monoval_plus[0][1] * monoval_i[1][1] * monoval_j[2][1];
                      grad_grads[start + n_curls + 1][0][1][0] =
                        -monoval_plus[0][1] * monoval_i[1][2] * monoval_j[2][0];
                      grad_grads[start + n_curls + 1][0][1][1] =
                        -monoval_plus[0][0] * monoval_i[1][3] * monoval_j[2][0];
                      grad_grads[start + n_curls + 1][0][1][2] =
                        -monoval_plus[0][0] * monoval_i[1][2] * monoval_j[2][1];
                      grad_grads[start + n_curls + 1][0][2][0] =
                        -monoval_plus[0][1] * monoval_i[1][1] * monoval_j[2][1];
                      grad_grads[start + n_curls + 1][0][2][1] =
                        -monoval_plus[0][0] * monoval_i[1][2] * monoval_j[2][1];
                      grad_grads[start + n_curls + 1][0][2][2] =
                        -monoval_plus[0][0] * monoval_i[1][1] * monoval_j[2][2];
                      grad_grads[start + n_curls + 1][1][0][0] =
                        monoval[0][2] * monoval_i[1][0] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][0][1] =
                        monoval[0][1] * monoval_i[1][1] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][0][2] =
                        monoval[0][1] * monoval_i[1][0] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][1][0] =
                        monoval[0][1] * monoval_i[1][1] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][1][1] =
                        monoval[0][0] * monoval_i[1][2] * monoval_j[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][1][2] =
                        monoval[0][0] * monoval_i[1][1] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][2][0] =
                        monoval[0][1] * monoval_i[1][0] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][2][1] =
                        monoval[0][0] * monoval_i[1][1] * monoval_j[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][1][2][2] =
                        monoval[0][0] * monoval_i[1][0] * monoval_j[2][2] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + n_curls + 1][2][0][0] =
                        -monoval[0][2] * monoval_i[1][1] * monoval_jplus[2][0];
                      grad_grads[start + n_curls + 1][2][0][1] =
                        -monoval[0][1] * monoval_i[1][2] * monoval_jplus[2][0];
                      grad_grads[start + n_curls + 1][2][0][2] =
                        -monoval[0][1] * monoval_i[1][1] * monoval_jplus[2][1];
                      grad_grads[start + n_curls + 1][2][1][0] =
                        -monoval[0][1] * monoval_i[1][2] * monoval_jplus[2][0];
                      grad_grads[start + n_curls + 1][2][1][1] =
                        -monoval[0][0] * monoval_i[1][3] * monoval_jplus[2][0];
                      grad_grads[start + n_curls + 1][2][1][2] =
                        -monoval[0][0] * monoval_i[1][2] * monoval_jplus[2][1];
                      grad_grads[start + n_curls + 1][2][2][0] =
                        -monoval[0][1] * monoval_i[1][1] * monoval_jplus[2][1];
                      grad_grads[start + n_curls + 1][2][2][1] =
                        -monoval[0][0] * monoval_i[1][2] * monoval_jplus[2][1];
                      grad_grads[start + n_curls + 1][2][2][2] =
                        -monoval[0][0] * monoval_i[1][1] * monoval_jplus[2][2];

                      grad_grads[start + 2 * n_curls + 1][0][0][0] =
                        -monoval_plus[0][2] * monoval_j[1][0] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][0][0][1] =
                        -monoval_plus[0][1] * monoval_j[1][1] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][0][0][2] =
                        -monoval_plus[0][1] * monoval_j[1][0] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][0][1][0] =
                        -monoval_plus[0][1] * monoval_j[1][1] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][0][1][1] =
                        -monoval_plus[0][0] * monoval_j[1][2] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][0][1][2] =
                        -monoval_plus[0][0] * monoval_j[1][1] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][0][2][0] =
                        -monoval_plus[0][1] * monoval_j[1][0] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][0][2][1] =
                        -monoval_plus[0][0] * monoval_j[1][1] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][0][2][2] =
                        -monoval_plus[0][0] * monoval_j[1][0] * monoval_i[2][3];
                      grad_grads[start + 2 * n_curls + 1][1][0][0] =
                        -monoval[0][2] * monoval_jplus[1][0] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][1][0][1] =
                        -monoval[0][1] * monoval_jplus[1][1] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][1][0][2] =
                        -monoval[0][1] * monoval_jplus[1][0] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][1][1][0] =
                        -monoval[0][1] * monoval_jplus[1][1] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][1][1][1] =
                        -monoval[0][0] * monoval_jplus[1][2] * monoval_i[2][1];
                      grad_grads[start + 2 * n_curls + 1][1][1][2] =
                        -monoval[0][0] * monoval_jplus[1][1] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][1][2][0] =
                        -monoval[0][1] * monoval_jplus[1][0] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][1][2][1] =
                        -monoval[0][0] * monoval_jplus[1][1] * monoval_i[2][2];
                      grad_grads[start + 2 * n_curls + 1][1][2][2] =
                        -monoval[0][0] * monoval_jplus[1][0] * monoval_i[2][3];
                      grad_grads[start + 2 * n_curls + 1][2][0][0] =
                        monoval[0][2] * monoval_j[1][0] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][0][1] =
                        monoval[0][1] * monoval_j[1][1] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][0][2] =
                        monoval[0][1] * monoval_j[1][0] * monoval_i[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][1][0] =
                        monoval[0][1] * monoval_j[1][1] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][1][1] =
                        monoval[0][0] * monoval_j[1][2] * monoval_i[2][0] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][1][2] =
                        monoval[0][0] * monoval_j[1][1] * monoval_i[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][2][0] =
                        monoval[0][1] * monoval_j[1][0] * monoval_i[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][2][1] =
                        monoval[0][0] * monoval_j[1][1] * monoval_i[2][1] *
                        static_cast<double>(j + my_degree + 2);
                      grad_grads[start + 2 * n_curls + 1][2][2][2] =
                        monoval[0][0] * monoval_j[1][0] * monoval_i[2][2] *
                        static_cast<double>(j + my_degree + 2);
                    }
                }

              if (j == my_degree)
                start += 1;
              else
                start += 2;
            }
        }
      Assert(start == this->n() - 2 * n_curls, ExcInternalError());
    }
}



template <int dim>
unsigned int
PolynomialsRT_Bubbles<dim>::n_polynomials(const unsigned int k)
{
  if (dim == 1 || dim == 2 || dim == 3)
    return dim * Utilities::fixed_power<dim>(k + 1);

  DEAL_II_NOT_IMPLEMENTED();
  return 0;
}


template <int dim>
std::unique_ptr<TensorPolynomialsBase<dim>>
PolynomialsRT_Bubbles<dim>::clone() const
{
  return std::make_unique<PolynomialsRT_Bubbles<dim>>(*this);
}


template class PolynomialsRT_Bubbles<1>;
template class PolynomialsRT_Bubbles<2>;
template class PolynomialsRT_Bubbles<3>;


DEAL_II_NAMESPACE_CLOSE