MFEM  v4.2.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
bilinearform_ext.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 // Implementations of classes FABilinearFormExtension, EABilinearFormExtension,
13 // PABilinearFormExtension and MFBilinearFormExtension.
14 
15 #include "../general/forall.hpp"
16 #include "bilinearform.hpp"
17 #include "libceed/ceed.hpp"
18 #include "pgridfunc.hpp"
19 
20 namespace mfem
21 {
22 
24  : Operator(form->Size()), a(form)
25 {
26  // empty
27 }
28 
30 {
31  return a->GetProlongation();
32 }
33 
35 {
36  return a->GetRestriction();
37 }
38 
39 // Data and methods for partially-assembled bilinear forms
41  : BilinearFormExtension(form),
42  trialFes(a->FESpace()),
43  testFes(a->FESpace())
44 {
45  elem_restrict = NULL;
46  int_face_restrict_lex = NULL;
47  bdr_face_restrict_lex = NULL;
48 }
49 
51 {
52  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
53  const int integratorCount = integrators.Size();
54  for (int i = 0; i < integratorCount; ++i)
55  {
56  integrators[i]->AssembleMF(*a->FESpace());
57  }
58 }
59 
61 {
62  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
63 
64  const int iSz = integrators.Size();
65  if (elem_restrict && !DeviceCanUseCeed())
66  {
67  localY = 0.0;
68  for (int i = 0; i < iSz; ++i)
69  {
70  integrators[i]->AssembleDiagonalMF(localY);
71  }
72  const ElementRestriction* H1elem_restrict =
73  dynamic_cast<const ElementRestriction*>(elem_restrict);
74  if (H1elem_restrict)
75  {
76  H1elem_restrict->MultTransposeUnsigned(localY, y);
77  }
78  else
79  {
81  }
82  }
83  else
84  {
85  y.UseDevice(true); // typically this is a large vector, so store on device
86  y = 0.0;
87  for (int i = 0; i < iSz; ++i)
88  {
89  integrators[i]->AssembleDiagonalMF(y);
90  }
91  }
92 }
93 
95 {
96  FiniteElementSpace *fes = a->FESpace();
97  height = width = fes->GetVSize();
98  trialFes = fes;
99  testFes = fes;
100 
101  elem_restrict = nullptr;
102  int_face_restrict_lex = nullptr;
103  bdr_face_restrict_lex = nullptr;
104 }
105 
107  OperatorHandle &A)
108 {
109  Operator *oper;
110  Operator::FormSystemOperator(ess_tdof_list, oper);
111  A.Reset(oper); // A will own oper
112 }
113 
115  Vector &x, Vector &b,
116  OperatorHandle &A,
117  Vector &X, Vector &B,
118  int copy_interior)
119 {
120  Operator *oper;
121  Operator::FormLinearSystem(ess_tdof_list, x, b, oper, X, B, copy_interior);
122  A.Reset(oper); // A will own oper
123 }
124 
126 {
127  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
128 
129  const int iSz = integrators.Size();
130  if (DeviceCanUseCeed() || !elem_restrict)
131  {
132  y.UseDevice(true); // typically this is a large vector, so store on device
133  y = 0.0;
134  for (int i = 0; i < iSz; ++i)
135  {
136  integrators[i]->AddMultMF(x, y);
137  }
138  }
139  else
140  {
142  localY = 0.0;
143  for (int i = 0; i < iSz; ++i)
144  {
145  integrators[i]->AddMultMF(localX, localY);
146  }
148  }
149 
150  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
151  const int iFISz = intFaceIntegrators.Size();
152  if (int_face_restrict_lex && iFISz>0)
153  {
155  if (faceIntX.Size()>0)
156  {
157  faceIntY = 0.0;
158  for (int i = 0; i < iFISz; ++i)
159  {
160  intFaceIntegrators[i]->AddMultMF(faceIntX, faceIntY);
161  }
163  }
164  }
165 
166  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
167  const int bFISz = bdrFaceIntegrators.Size();
168  if (bdr_face_restrict_lex && bFISz>0)
169  {
171  if (faceBdrX.Size()>0)
172  {
173  faceBdrY = 0.0;
174  for (int i = 0; i < bFISz; ++i)
175  {
176  bdrFaceIntegrators[i]->AddMultMF(faceBdrX, faceBdrY);
177  }
179  }
180  }
181 }
182 
184 {
185  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
186  const int iSz = integrators.Size();
187  if (elem_restrict)
188  {
190  localY = 0.0;
191  for (int i = 0; i < iSz; ++i)
192  {
193  integrators[i]->AddMultTransposeMF(localX, localY);
194  }
196  }
197  else
198  {
199  y.UseDevice(true);
200  y = 0.0;
201  for (int i = 0; i < iSz; ++i)
202  {
203  integrators[i]->AddMultTransposeMF(x, y);
204  }
205  }
206 
207  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
208  const int iFISz = intFaceIntegrators.Size();
209  if (int_face_restrict_lex && iFISz>0)
210  {
212  if (faceIntX.Size()>0)
213  {
214  faceIntY = 0.0;
215  for (int i = 0; i < iFISz; ++i)
216  {
217  intFaceIntegrators[i]->AddMultTransposeMF(faceIntX, faceIntY);
218  }
220  }
221  }
222 
223  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
224  const int bFISz = bdrFaceIntegrators.Size();
225  if (bdr_face_restrict_lex && bFISz>0)
226  {
228  if (faceBdrX.Size()>0)
229  {
230  faceBdrY = 0.0;
231  for (int i = 0; i < bFISz; ++i)
232  {
233  bdrFaceIntegrators[i]->AddMultTransposeMF(faceBdrX, faceBdrY);
234  }
236  }
237  }
238 }
239 
240 // Data and methods for partially-assembled bilinear forms
242  : BilinearFormExtension(form),
243  trialFes(a->FESpace()),
244  testFes(a->FESpace())
245 {
246  elem_restrict = NULL;
247  int_face_restrict_lex = NULL;
248  bdr_face_restrict_lex = NULL;
249 }
250 
252 {
257  if (elem_restrict)
258  {
259  localX.SetSize(elem_restrict->Height(), Device::GetDeviceMemoryType());
260  localY.SetSize(elem_restrict->Height(), Device::GetDeviceMemoryType());
261  localY.UseDevice(true); // ensure 'localY = 0.0' is done on device
262  }
263 
264  // Construct face restriction operators only if the bilinear form has
265  // interior or boundary face integrators
266  if (int_face_restrict_lex == NULL && a->GetFBFI()->Size() > 0)
267  {
273  faceIntY.UseDevice(true); // ensure 'faceIntY = 0.0' is done on device
274  }
275 
276  if (bdr_face_restrict_lex == NULL && a->GetBFBFI()->Size() > 0)
277  {
281  m);
284  faceBdrY.UseDevice(true); // ensure 'faceBoundY = 0.0' is done on device
285  }
286 }
287 
289 {
291 
292  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
293  const int integratorCount = integrators.Size();
294  for (int i = 0; i < integratorCount; ++i)
295  {
296  integrators[i]->AssemblePA(*a->FESpace());
297  }
298 
299  MFEM_VERIFY(a->GetBBFI()->Size() == 0,
300  "Partial assembly does not support AddBoundaryIntegrator yet.");
301 
302  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
303  const int intFaceIntegratorCount = intFaceIntegrators.Size();
304  for (int i = 0; i < intFaceIntegratorCount; ++i)
305  {
306  intFaceIntegrators[i]->AssemblePAInteriorFaces(*a->FESpace());
307  }
308 
309  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
310  const int boundFaceIntegratorCount = bdrFaceIntegrators.Size();
311  for (int i = 0; i < boundFaceIntegratorCount; ++i)
312  {
313  bdrFaceIntegrators[i]->AssemblePABoundaryFaces(*a->FESpace());
314  }
315 }
316 
318 {
319  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
320 
321  const int iSz = integrators.Size();
322  if (elem_restrict && !DeviceCanUseCeed())
323  {
324  localY = 0.0;
325  for (int i = 0; i < iSz; ++i)
326  {
327  integrators[i]->AssembleDiagonalPA(localY);
328  }
329  const ElementRestriction* H1elem_restrict =
330  dynamic_cast<const ElementRestriction*>(elem_restrict);
331  if (H1elem_restrict)
332  {
333  H1elem_restrict->MultTransposeUnsigned(localY, y);
334  }
335  else
336  {
338  }
339  }
340  else
341  {
342  y.UseDevice(true); // typically this is a large vector, so store on device
343  y = 0.0;
344  for (int i = 0; i < iSz; ++i)
345  {
346  integrators[i]->AssembleDiagonalPA(y);
347  }
348  }
349 }
350 
352 {
353  FiniteElementSpace *fes = a->FESpace();
354  height = width = fes->GetVSize();
355  trialFes = fes;
356  testFes = fes;
357 
358  elem_restrict = nullptr;
359  int_face_restrict_lex = nullptr;
360  bdr_face_restrict_lex = nullptr;
361 }
362 
364  OperatorHandle &A)
365 {
366  Operator *oper;
367  Operator::FormSystemOperator(ess_tdof_list, oper);
368  A.Reset(oper); // A will own oper
369 }
370 
372  Vector &x, Vector &b,
373  OperatorHandle &A,
374  Vector &X, Vector &B,
375  int copy_interior)
376 {
377  Operator *oper;
378  Operator::FormLinearSystem(ess_tdof_list, x, b, oper, X, B, copy_interior);
379  A.Reset(oper); // A will own oper
380 }
381 
383 {
384  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
385 
386  const int iSz = integrators.Size();
387  if (DeviceCanUseCeed() || !elem_restrict)
388  {
389  y.UseDevice(true); // typically this is a large vector, so store on device
390  y = 0.0;
391  for (int i = 0; i < iSz; ++i)
392  {
393  integrators[i]->AddMultPA(x, y);
394  }
395  }
396  else
397  {
399  localY = 0.0;
400  for (int i = 0; i < iSz; ++i)
401  {
402  integrators[i]->AddMultPA(localX, localY);
403  }
405  }
406 
407  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
408  const int iFISz = intFaceIntegrators.Size();
409  if (int_face_restrict_lex && iFISz>0)
410  {
412  if (faceIntX.Size()>0)
413  {
414  faceIntY = 0.0;
415  for (int i = 0; i < iFISz; ++i)
416  {
417  intFaceIntegrators[i]->AddMultPA(faceIntX, faceIntY);
418  }
420  }
421  }
422 
423  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
424  const int bFISz = bdrFaceIntegrators.Size();
425  if (bdr_face_restrict_lex && bFISz>0)
426  {
428  if (faceBdrX.Size()>0)
429  {
430  faceBdrY = 0.0;
431  for (int i = 0; i < bFISz; ++i)
432  {
433  bdrFaceIntegrators[i]->AddMultPA(faceBdrX, faceBdrY);
434  }
436  }
437  }
438 }
439 
441 {
442  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
443  const int iSz = integrators.Size();
444  if (elem_restrict)
445  {
447  localY = 0.0;
448  for (int i = 0; i < iSz; ++i)
449  {
450  integrators[i]->AddMultTransposePA(localX, localY);
451  }
453  }
454  else
455  {
456  y.UseDevice(true);
457  y = 0.0;
458  for (int i = 0; i < iSz; ++i)
459  {
460  integrators[i]->AddMultTransposePA(x, y);
461  }
462  }
463 
464  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
465  const int iFISz = intFaceIntegrators.Size();
466  if (int_face_restrict_lex && iFISz>0)
467  {
469  if (faceIntX.Size()>0)
470  {
471  faceIntY = 0.0;
472  for (int i = 0; i < iFISz; ++i)
473  {
474  intFaceIntegrators[i]->AddMultTransposePA(faceIntX, faceIntY);
475  }
477  }
478  }
479 
480  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
481  const int bFISz = bdrFaceIntegrators.Size();
482  if (bdr_face_restrict_lex && bFISz>0)
483  {
485  if (faceBdrX.Size()>0)
486  {
487  faceBdrY = 0.0;
488  for (int i = 0; i < bFISz; ++i)
489  {
490  bdrFaceIntegrators[i]->AddMultTransposePA(faceBdrX, faceBdrY);
491  }
493  }
494  }
495 }
496 
497 // Data and methods for element-assembled bilinear forms
499  : PABilinearFormExtension(form),
500  factorize_face_terms(form->FESpace()->IsDGSpace())
501 {
502 }
503 
505 {
507 
508  ne = trialFes->GetMesh()->GetNE();
509  elemDofs = trialFes->GetFE(0)->GetDof();
510 
512  ea_data.UseDevice(true);
513 
514  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
515  const int integratorCount = integrators.Size();
516  for (int i = 0; i < integratorCount; ++i)
517  {
518  integrators[i]->AssembleEA(*a->FESpace(), ea_data, i);
519  }
520 
521  faceDofs = trialFes ->
522  GetTraceElement(0, trialFes->GetMesh()->GetFaceBaseGeometry(0)) ->
523  GetDof();
524 
525  MFEM_VERIFY(a->GetBBFI()->Size() == 0,
526  "Element assembly does not support AddBoundaryIntegrator yet.");
527 
528  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
529  const int intFaceIntegratorCount = intFaceIntegrators.Size();
530  if (intFaceIntegratorCount>0)
531  {
534  ea_data_ext.SetSize(2*nf_int*faceDofs*faceDofs, Device::GetMemoryType());
535  }
536  for (int i = 0; i < intFaceIntegratorCount; ++i)
537  {
538  intFaceIntegrators[i]->AssembleEAInteriorFaces(*a->FESpace(),
539  ea_data_int,
540  ea_data_ext,
541  i);
542  }
543 
544  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
545  const int boundFaceIntegratorCount = bdrFaceIntegrators.Size();
546  if (boundFaceIntegratorCount>0)
547  {
550  ea_data_bdr = 0.0;
551  }
552  for (int i = 0; i < boundFaceIntegratorCount; ++i)
553  {
554  bdrFaceIntegrators[i]->AssembleEABoundaryFaces(*a->FESpace(),ea_data_bdr,i);
555  }
556 
558  {
559  auto restFint = dynamic_cast<const L2FaceRestriction&>(*int_face_restrict_lex);
561  }
563  {
564  auto restFbdr = dynamic_cast<const L2FaceRestriction&>(*bdr_face_restrict_lex);
566  }
567 }
568 
570 {
571  // Apply the Element Restriction
572  const bool useRestrict = !DeviceCanUseCeed() && elem_restrict;
573  if (!useRestrict)
574  {
575  y.UseDevice(true); // typically this is a large vector, so store on device
576  y = 0.0;
577  }
578  else
579  {
581  localY = 0.0;
582  }
583  // Apply the Element Matrices
584  const int NDOFS = elemDofs;
585  auto X = Reshape(useRestrict?localX.Read():x.Read(), NDOFS, ne);
586  auto Y = Reshape(useRestrict?localY.ReadWrite():y.ReadWrite(), NDOFS, ne);
587  auto A = Reshape(ea_data.Read(), NDOFS, NDOFS, ne);
588  MFEM_FORALL(glob_j, ne*NDOFS,
589  {
590  const int e = glob_j/NDOFS;
591  const int j = glob_j%NDOFS;
592  double res = 0.0;
593  for (int i = 0; i < NDOFS; i++)
594  {
595  res += A(i, j, e)*X(i, e);
596  }
597  Y(j, e) += res;
598  });
599  // Apply the Element Restriction transposed
600  if (useRestrict)
601  {
603  }
604 
605  // Treatment of interior faces
606  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
607  const int iFISz = intFaceIntegrators.Size();
608  if (int_face_restrict_lex && iFISz>0)
609  {
610  // Apply the Interior Face Restriction
612  if (faceIntX.Size()>0)
613  {
614  faceIntY = 0.0;
615  // Apply the interior face matrices
616  const int NDOFS = faceDofs;
617  auto X = Reshape(faceIntX.Read(), NDOFS, 2, nf_int);
618  auto Y = Reshape(faceIntY.ReadWrite(), NDOFS, 2, nf_int);
620  {
621  auto A_int = Reshape(ea_data_int.Read(), NDOFS, NDOFS, 2, nf_int);
622  MFEM_FORALL(glob_j, nf_int*NDOFS,
623  {
624  const int f = glob_j/NDOFS;
625  const int j = glob_j%NDOFS;
626  double res = 0.0;
627  for (int i = 0; i < NDOFS; i++)
628  {
629  res += A_int(i, j, 0, f)*X(i, 0, f);
630  }
631  Y(j, 0, f) += res;
632  res = 0.0;
633  for (int i = 0; i < NDOFS; i++)
634  {
635  res += A_int(i, j, 1, f)*X(i, 1, f);
636  }
637  Y(j, 1, f) += res;
638  });
639  }
640  auto A_ext = Reshape(ea_data_ext.Read(), NDOFS, NDOFS, 2, nf_int);
641  MFEM_FORALL(glob_j, nf_int*NDOFS,
642  {
643  const int f = glob_j/NDOFS;
644  const int j = glob_j%NDOFS;
645  double res = 0.0;
646  for (int i = 0; i < NDOFS; i++)
647  {
648  res += A_ext(i, j, 0, f)*X(i, 0, f);
649  }
650  Y(j, 1, f) += res;
651  res = 0.0;
652  for (int i = 0; i < NDOFS; i++)
653  {
654  res += A_ext(i, j, 1, f)*X(i, 1, f);
655  }
656  Y(j, 0, f) += res;
657  });
658  // Apply the Interior Face Restriction transposed
660  }
661  }
662 
663  // Treatment of boundary faces
664  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
665  const int bFISz = bdrFaceIntegrators.Size();
666  if (!factorize_face_terms && bdr_face_restrict_lex && bFISz>0)
667  {
668  // Apply the Boundary Face Restriction
670  if (faceBdrX.Size()>0)
671  {
672  faceBdrY = 0.0;
673  // Apply the boundary face matrices
674  const int NDOFS = faceDofs;
675  auto X = Reshape(faceBdrX.Read(), NDOFS, nf_bdr);
676  auto Y = Reshape(faceBdrY.ReadWrite(), NDOFS, nf_bdr);
677  auto A = Reshape(ea_data_bdr.Read(), NDOFS, NDOFS, nf_bdr);
678  MFEM_FORALL(glob_j, nf_bdr*NDOFS,
679  {
680  const int f = glob_j/NDOFS;
681  const int j = glob_j%NDOFS;
682  double res = 0.0;
683  for (int i = 0; i < NDOFS; i++)
684  {
685  res += A(i, j, f)*X(i, f);
686  }
687  Y(j, f) += res;
688  });
689  // Apply the Boundary Face Restriction transposed
691  }
692  }
693 }
694 
696 {
697  // Apply the Element Restriction
698  const bool useRestrict = DeviceCanUseCeed() || !elem_restrict;
699  if (!useRestrict)
700  {
701  y.UseDevice(true); // typically this is a large vector, so store on device
702  y = 0.0;
703  }
704  else
705  {
707  localY = 0.0;
708  }
709  // Apply the Element Matrices transposed
710  const int NDOFS = elemDofs;
711  auto X = Reshape(useRestrict?localX.Read():x.Read(), NDOFS, ne);
712  auto Y = Reshape(useRestrict?localY.ReadWrite():y.ReadWrite(), NDOFS, ne);
713  auto A = Reshape(ea_data.Read(), NDOFS, NDOFS, ne);
714  MFEM_FORALL(glob_j, ne*NDOFS,
715  {
716  const int e = glob_j/NDOFS;
717  const int j = glob_j%NDOFS;
718  double res = 0.0;
719  for (int i = 0; i < NDOFS; i++)
720  {
721  res += A(j, i, e)*X(i, e);
722  }
723  Y(j, e) += res;
724  });
725  // Apply the Element Restriction transposed
726  if (useRestrict)
727  {
729  }
730 
731  // Treatment of interior faces
732  Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
733  const int iFISz = intFaceIntegrators.Size();
734  if (int_face_restrict_lex && iFISz>0)
735  {
736  // Apply the Interior Face Restriction
738  if (faceIntX.Size()>0)
739  {
740  faceIntY = 0.0;
741  // Apply the interior face matrices transposed
742  const int NDOFS = faceDofs;
743  auto X = Reshape(faceIntX.Read(), NDOFS, 2, nf_int);
744  auto Y = Reshape(faceIntY.ReadWrite(), NDOFS, 2, nf_int);
746  {
747  auto A_int = Reshape(ea_data_int.Read(), NDOFS, NDOFS, 2, nf_int);
748  MFEM_FORALL(glob_j, nf_int*NDOFS,
749  {
750  const int f = glob_j/NDOFS;
751  const int j = glob_j%NDOFS;
752  double res = 0.0;
753  for (int i = 0; i < NDOFS; i++)
754  {
755  res += A_int(j, i, 0, f)*X(i, 0, f);
756  }
757  Y(j, 0, f) += res;
758  res = 0.0;
759  for (int i = 0; i < NDOFS; i++)
760  {
761  res += A_int(j, i, 1, f)*X(i, 1, f);
762  }
763  Y(j, 1, f) += res;
764  });
765  }
766  auto A_ext = Reshape(ea_data_ext.Read(), NDOFS, NDOFS, 2, nf_int);
767  MFEM_FORALL(glob_j, nf_int*NDOFS,
768  {
769  const int f = glob_j/NDOFS;
770  const int j = glob_j%NDOFS;
771  double res = 0.0;
772  for (int i = 0; i < NDOFS; i++)
773  {
774  res += A_ext(j, i, 0, f)*X(i, 0, f);
775  }
776  Y(j, 1, f) += res;
777  res = 0.0;
778  for (int i = 0; i < NDOFS; i++)
779  {
780  res += A_ext(j, i, 1, f)*X(i, 1, f);
781  }
782  Y(j, 0, f) += res;
783  });
784  // Apply the Interior Face Restriction transposed
786  }
787  }
788 
789  // Treatment of boundary faces
790  Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
791  const int bFISz = bdrFaceIntegrators.Size();
792  if (!factorize_face_terms && bdr_face_restrict_lex && bFISz>0)
793  {
794  // Apply the Boundary Face Restriction
796  if (faceBdrX.Size()>0)
797  {
798  faceBdrY = 0.0;
799  // Apply the boundary face matrices transposed
800  const int NDOFS = faceDofs;
801  auto X = Reshape(faceBdrX.Read(), NDOFS, nf_bdr);
802  auto Y = Reshape(faceBdrY.ReadWrite(), NDOFS, nf_bdr);
803  auto A = Reshape(ea_data_bdr.Read(), NDOFS, NDOFS, nf_bdr);
804  MFEM_FORALL(glob_j, nf_bdr*NDOFS,
805  {
806  const int f = glob_j/NDOFS;
807  const int j = glob_j%NDOFS;
808  double res = 0.0;
809  for (int i = 0; i < NDOFS; i++)
810  {
811  res += A(j, i, f)*X(i, f);
812  }
813  Y(j, f) += res;
814  });
815  // Apply the Boundary Face Restriction transposed
817  }
818  }
819 }
820 
821 // Data and methods for fully-assembled bilinear forms
823  : EABilinearFormExtension(form),
824  mat(form->FESpace()->GetVSize(),form->FESpace()->GetVSize(),0),
825  face_mat(form->FESpace()->GetVSize(),0,0),
826  use_face_mat(false)
827 {
828 #ifdef MFEM_USE_MPI
829  if ( ParFiniteElementSpace* pfes =
830  dynamic_cast<ParFiniteElementSpace*>(form->FESpace()) )
831  {
832  if (pfes->IsDGSpace())
833  {
834  use_face_mat = true;
835  pfes->ExchangeFaceNbrData();
836  face_mat.SetWidth(pfes->GetFaceNbrVSize());
837  }
838  }
839 #endif
840 }
841 
843 {
845  FiniteElementSpace &fes = *a->FESpace();
846  if (fes.IsDGSpace())
847  {
848  const L2ElementRestriction *restE =
849  static_cast<const L2ElementRestriction*>(elem_restrict);
850  const L2FaceRestriction *restF =
851  static_cast<const L2FaceRestriction*>(int_face_restrict_lex);
852  // 1. Fill I
853  // 1.1 Increment with restE
854  restE->FillI(mat);
855  // 1.2 Increment with restF
856  if (restF) { restF->FillI(mat, face_mat); }
857  // 1.3 Sum the non-zeros in I
858  auto h_I = mat.HostReadWriteI();
859  int cpt = 0;
860  const int vd = fes.GetVDim();
861  const int ndofs = ne*elemDofs*vd;
862  for (int i = 0; i < ndofs; i++)
863  {
864  const int nnz = h_I[i];
865  h_I[i] = cpt;
866  cpt += nnz;
867  }
868  const int nnz = cpt;
869  h_I[ndofs] = nnz;
870  mat.GetMemoryJ().New(nnz, mat.GetMemoryJ().GetMemoryType());
871  mat.GetMemoryData().New(nnz, mat.GetMemoryData().GetMemoryType());
872  if (use_face_mat && restF)
873  {
874  auto h_I_face = face_mat.HostReadWriteI();
875  int cpt = 0;
876  for (int i = 0; i < ndofs; i++)
877  {
878  const int nnz = h_I_face[i];
879  h_I_face[i] = cpt;
880  cpt += nnz;
881  }
882  const int nnz_face = cpt;
883  h_I_face[ndofs] = nnz_face;
884  face_mat.GetMemoryJ().New(nnz_face,
885  face_mat.GetMemoryJ().GetMemoryType());
886  face_mat.GetMemoryData().New(nnz_face,
887  face_mat.GetMemoryData().GetMemoryType());
888  }
889  // 2. Fill J and Data
890  // 2.1 Fill J and Data with Elem ea_data
891  restE->FillJAndData(ea_data, mat);
892  // 2.2 Fill J and Data with Face ea_data_ext
893  if (restF) { restF->FillJAndData(ea_data_ext, mat, face_mat); }
894  // 2.3 Shift indirections in I back to original
895  auto I = mat.HostReadWriteI();
896  for (int i = ndofs; i > 0; i--)
897  {
898  I[i] = I[i-1];
899  }
900  I[0] = 0;
901  if (use_face_mat && restF)
902  {
903  auto I_face = face_mat.HostReadWriteI();
904  for (int i = ndofs; i > 0; i--)
905  {
906  I_face[i] = I_face[i-1];
907  }
908  I_face[0] = 0;
909  }
910  }
911  else // continuous Galerkin case
912  {
913  const ElementRestriction &rest =
914  static_cast<const ElementRestriction&>(*elem_restrict);
915  rest.FillSparseMatrix(ea_data, mat);
916  }
917 }
918 
920 {
921  mat.Mult(x, y);
922 #ifdef MFEM_USE_MPI
923  if (const ParFiniteElementSpace *pfes =
924  dynamic_cast<const ParFiniteElementSpace*>(testFes))
925  {
926  ParGridFunction x_gf;
927  x_gf.MakeRef(const_cast<ParFiniteElementSpace*>(pfes),
928  const_cast<Vector&>(x),0);
929  x_gf.ExchangeFaceNbrData();
930  Vector &shared_x = x_gf.FaceNbrData();
931  if (shared_x.Size()) { face_mat.AddMult(shared_x, y); }
932  }
933 #endif
934 }
935 
937 {
938  mat.MultTranspose(x, y);
939 #ifdef MFEM_USE_MPI
940  if (const ParFiniteElementSpace *pfes =
941  dynamic_cast<const ParFiniteElementSpace*>(testFes))
942  {
943  ParGridFunction x_gf;
944  x_gf.MakeRef(const_cast<ParFiniteElementSpace*>(pfes),
945  const_cast<Vector&>(x),0);
946  x_gf.ExchangeFaceNbrData();
947  Vector &shared_x = x_gf.FaceNbrData();
948  if (shared_x.Size()) { face_mat.AddMultTranspose(shared_x, y); }
949  }
950 #endif
951 }
952 
953 
955  : Operator(form->Height(), form->Width()), a(form)
956 {
957  // empty
958 }
959 
961 {
962  return a->GetProlongation();
963 }
964 
966 {
967  return a->GetRestriction();
968 }
969 
971 {
972  return a->GetOutputProlongation();
973 }
974 
976 {
977  return a->GetOutputRestriction();
978 }
979 
980 // Data and methods for partially-assembled bilinear forms
981 
983  MixedBilinearForm *form)
985  trialFes(form->TrialFESpace()),
986  testFes(form->TestFESpace()),
987  elem_restrict_trial(NULL),
988  elem_restrict_test(NULL)
989 {
990  Update();
991 }
992 
994 {
995  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
996  const int integratorCount = integrators.Size();
997  for (int i = 0; i < integratorCount; ++i)
998  {
999  integrators[i]->AssemblePA(*trialFes, *testFes);
1000  }
1001  MFEM_VERIFY(a->GetBBFI()->Size() == 0,
1002  "Partial assembly does not support AddBoundaryIntegrator yet.");
1003  MFEM_VERIFY(a->GetTFBFI()->Size() == 0,
1004  "Partial assembly does not support AddTraceFaceIntegrator yet.");
1005  MFEM_VERIFY(a->GetBTFBFI()->Size() == 0,
1006  "Partial assembly does not support AddBdrTraceFaceIntegrator yet.");
1007 }
1008 
1010 {
1011  trialFes = a->TrialFESpace();
1012  testFes = a->TestFESpace();
1013  height = testFes->GetVSize();
1014  width = trialFes->GetVSize();
1019  if (elem_restrict_trial)
1020  {
1021  localTrial.UseDevice(true);
1024 
1025  }
1026  if (elem_restrict_test)
1027  {
1028  localTest.UseDevice(true); // ensure 'localY = 0.0' is done on device
1030  }
1031 }
1032 
1034  const Array<int> &trial_tdof_list,
1035  const Array<int> &test_tdof_list,
1036  OperatorHandle &A)
1037 {
1038  Operator * oper;
1039  Operator::FormRectangularSystemOperator(trial_tdof_list, test_tdof_list,
1040  oper);
1041  A.Reset(oper); // A will own oper
1042 }
1043 
1045  const Array<int> &trial_tdof_list,
1046  const Array<int> &test_tdof_list,
1047  Vector &x, Vector &b,
1048  OperatorHandle &A,
1049  Vector &X, Vector &B)
1050 {
1051  Operator *oper;
1052  Operator::FormRectangularLinearSystem(trial_tdof_list, test_tdof_list, x, b,
1053  oper, X, B);
1054  A.Reset(oper); // A will own oper
1055 }
1056 
1057 void PAMixedBilinearFormExtension::SetupMultInputs(
1058  const Operator *elem_restrict_x,
1059  const Vector &x,
1060  Vector &localX,
1061  const Operator *elem_restrict_y,
1062  Vector &y,
1063  Vector &localY,
1064  const double c) const
1065 {
1066  // * G operation: localX = c*local(x)
1067  if (elem_restrict_x)
1068  {
1069  elem_restrict_x->Mult(x, localX);
1070  if (c != 1.0)
1071  {
1072  localX *= c;
1073  }
1074  }
1075  else
1076  {
1077  if (c == 1.0)
1078  {
1079  localX.SyncAliasMemory(x);
1080  }
1081  else
1082  {
1083  localX.Set(c, x);
1084  }
1085  }
1086  if (elem_restrict_y)
1087  {
1088  localY = 0.0;
1089  }
1090  else
1091  {
1092  y.UseDevice(true);
1093  localY.SyncAliasMemory(y);
1094  }
1095 }
1096 
1098 {
1099  y = 0.0;
1100  AddMult(x, y);
1101 }
1102 
1104  const double c) const
1105 {
1106  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
1107  const int iSz = integrators.Size();
1108 
1109  // * G operation
1110  SetupMultInputs(elem_restrict_trial, x, localTrial,
1111  elem_restrict_test, y, localTest, c);
1112 
1113  // * B^TDB operation
1114  for (int i = 0; i < iSz; ++i)
1115  {
1116  integrators[i]->AddMultPA(localTrial, localTest);
1117  }
1118 
1119  // * G^T operation
1120  if (elem_restrict_test)
1121  {
1122  tempY.SetSize(y.Size());
1124  y += tempY;
1125  }
1126 }
1127 
1129  Vector &y) const
1130 {
1131  y = 0.0;
1132  AddMultTranspose(x, y);
1133 }
1134 
1136  const double c) const
1137 {
1138  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
1139  const int iSz = integrators.Size();
1140 
1141  // * G operation
1142  SetupMultInputs(elem_restrict_test, x, localTest,
1144 
1145  // * B^TD^TB operation
1146  for (int i = 0; i < iSz; ++i)
1147  {
1148  integrators[i]->AddMultTransposePA(localTest, localTrial);
1149  }
1150 
1151  // * G^T operation
1152  if (elem_restrict_trial)
1153  {
1154  tempY.SetSize(y.Size());
1156  y += tempY;
1157  }
1158 }
1159 
1161  Vector &diag) const
1162 {
1163  Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
1164 
1165  const int iSz = integrators.Size();
1166 
1167  if (elem_restrict_trial)
1168  {
1169  const ElementRestriction* H1elem_restrict_trial =
1170  dynamic_cast<const ElementRestriction*>(elem_restrict_trial);
1171  if (H1elem_restrict_trial)
1172  {
1173  H1elem_restrict_trial->MultUnsigned(D, localTrial);
1174  }
1175  else
1176  {
1178  }
1179  }
1180 
1181  if (elem_restrict_test)
1182  {
1183  localTest = 0.0;
1184  for (int i = 0; i < iSz; ++i)
1185  {
1186  if (elem_restrict_trial)
1187  {
1188  integrators[i]->AssembleDiagonalPA_ADAt(localTrial, localTest);
1189  }
1190  else
1191  {
1192  integrators[i]->AssembleDiagonalPA_ADAt(D, localTest);
1193  }
1194  }
1195  const ElementRestriction* H1elem_restrict_test =
1196  dynamic_cast<const ElementRestriction*>(elem_restrict_test);
1197  if (H1elem_restrict_test)
1198  {
1199  H1elem_restrict_test->MultTransposeUnsigned(localTest, diag);
1200  }
1201  else
1202  {
1204  }
1205  }
1206  else
1207  {
1208  diag.UseDevice(true); // typically this is a large vector, so store on device
1209  diag = 0.0;
1210  for (int i = 0; i < iSz; ++i)
1211  {
1212  if (elem_restrict_trial)
1213  {
1214  integrators[i]->AssembleDiagonalPA_ADAt(localTrial, diag);
1215  }
1216  else
1217  {
1218  integrators[i]->AssembleDiagonalPA_ADAt(D, diag);
1219  }
1220  }
1221  }
1222 }
1223 
1224 } // namespace mfem
int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type.
Definition: fespace.hpp:444
int Size() const
Return the logical size of the array.
Definition: array.hpp:124
const Operator * bdr_face_restrict_lex
void FormRectangularSystemOperator(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, Operator *&A)
Return in A a parallel (on truedofs) version of this rectangular operator (including constraints)...
Definition: operator.cpp:172
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition: fespace.hpp:400
void AssembleDiagonal_ADAt(const Vector &D, Vector &diag) const
Assemble the diagonal of ADA^T for a diagonal vector D.
Array< BilinearFormIntegrator * > * GetBBFI()
Access all the integrators added with AddBoundaryIntegrator().
L2FaceValues
Definition: restriction.hpp:26
void FormRectangularSystemOperator(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, OperatorHandle &A)
Setup OperatorHandle A to contain constrained linear operator.
void MultTransposeUnsigned(const Vector &x, Vector &y) const
Compute MultTranspose without applying signs based on DOF orientations.
virtual const Operator * GetProlongation() const
Get the input finite element space prolongation matrix.
const FiniteElementSpace * testFes
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
FiniteElementSpace * FESpace()
Return the FE space associated with the BilinearForm.
virtual void FillI(SparseMatrix &mat, SparseMatrix &face_mat) const
Array< BilinearFormIntegrator * > * GetDBFI()
Access all the integrators added with AddDomainIntegrator().
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:459
MFBilinearFormExtension(BilinearForm *form)
Array< BilinearFormIntegrator * > * GetBFBFI()
Access all integrators added with AddBdrFaceIntegrator().
void Assemble()
Assemble at the level given for the BilinearFormExtension subclass.
void Assemble()
Assemble at the level given for the BilinearFormExtension subclass.
void AddMultTranspose(const Vector &x, Vector &y, const double c=1.0) const
y += c*A^T*x
Pointer to an Operator of a specified type.
Definition: handle.hpp:33
void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:89
PAMixedBilinearFormExtension(MixedBilinearForm *form)
void MultTranspose(const Vector &x, Vector &y) const
y = A^T*x
void AddMult(const Vector &x, Vector &y, const double a=1.0) const
y += A * x (default) or y += a * A * x
Definition: sparsemat.cpp:601
int Size() const
Returns the size of the vector.
Definition: vector.hpp:160
void AddFaceMatricesToElementMatrices(Vector &fea_data, Vector &ea_data) const
This methods adds the DG face matrices to the element matrices.
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:737
void AddMultTranspose(const Vector &x, Vector &y, const double a=1.0) const
y += At * x (default) or y += a * At * x
Definition: sparsemat.cpp:728
virtual const Operator * GetRestriction() const
Get the finite element space restriction matrix.
virtual const Operator * GetRestriction() const
Get the finite element space restriction matrix.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Geometry::Type GetFaceBaseGeometry(int i) const
Definition: mesh.hpp:829
Abstract parallel finite element space.
Definition: pfespace.hpp:28
virtual const Operator * GetProlongation() const
Get the finite element space prolongation operator.
BilinearFormExtension(BilinearForm *form)
bool UsesTensorBasis(const FiniteElementSpace &fes)
Definition: fespace.hpp:983
Array< BilinearFormIntegrator * > * GetFBFI()
Access all integrators added with AddInteriorFaceIntegrator().
virtual const Operator * GetRestriction() const
Get the input finite element space restriction matrix.
Memory< double > & GetMemoryData()
Definition: sparsemat.hpp:220
Data and methods for partially-assembled bilinear forms.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition: operator.hpp:92
Class extending the MixedBilinearForm class to support different AssemblyLevels.
Memory< int > & GetMemoryJ()
Definition: sparsemat.hpp:204
void FormRectangularLinearSystem(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, Vector &x, Vector &b, Operator *&A, Vector &X, Vector &B)
Form a column-constrained linear system using a matrix-free approach.
Definition: operator.cpp:68
const Operator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition: fespace.cpp:894
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition: dtensor.hpp:134
virtual void MakeRef(FiniteElementSpace *f, double *v)
Make the ParGridFunction reference external data on a new FiniteElementSpace.
Definition: pgridfunc.cpp:102
virtual const Operator * GetOutputProlongation() const
Get the output finite element space restriction matrix.
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:388
virtual const Operator * GetProlongation() const
Get the finite element space prolongation matrix.
void Assemble()
Partial assembly of all internal integrators.
Native ordering as defined by the FiniteElement.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:65
void FillI(SparseMatrix &mat) const
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:314
Operator that extracts Face degrees of freedom.
void SetWidth(int width_=-1)
Change the width of a SparseMatrix.
Definition: sparsemat.cpp:371
const FiniteElementSpace * trialFes
double b
Definition: lissajous.cpp:42
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Definition: device.hpp:261
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition: device.hpp:265
BilinearForm * a
Not owned.
void AssembleDiagonal(Vector &diag) const
void AddMult(const Vector &x, Vector &y, const double c=1.0) const
y += c*A*x
FiniteElementSpace * TestFESpace()
Return the test FE space associated with the BilinearForm.
virtual const Operator * GetOutputRestriction() const
Get the test finite element space restriction matrix.
Array< BilinearFormIntegrator * > * GetBTFBFI()
Access all integrators added with AddBdrTraceFaceIntegrator().
Class extending the BilinearForm class to support different AssemblyLevels.
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
Definition: fespace.hpp:710
void MultUnsigned(const Vector &x, Vector &y) const
Compute Mult without applying signs based on DOF orientations.
virtual const Operator * GetProlongation() const
Get the finite element space prolongation matrix.
FABilinearFormExtension(BilinearForm *form)
const FiniteElementSpace * testFes
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:389
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B, int copy_interior=0)
void FormRectangularLinearSystem(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B)
Array< BilinearFormIntegrator * > * GetTFBFI()
Access all integrators added with AddTraceFaceIntegrator().
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Array< BilinearFormIntegrator * > * GetBBFI()
Access all integrators added with AddBoundaryIntegrator().
void Assemble()
Assemble at the level given for the BilinearFormExtension subclass.
Vector & FaceNbrData()
Definition: pgridfunc.hpp:203
virtual const Operator * GetFaceRestriction(ElementDofOrdering e_ordering, FaceType, L2FaceValues mul=L2FaceValues::DoubleValued) const
Return an Operator that converts L-vectors to E-vectors on each face.
Definition: fespace.cpp:922
void SetupRestrictionOperators(const L2FaceValues m)
void Mult(const Vector &x, Vector &y) const
y = A*x
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Data and methods for element-assembled bilinear forms.
virtual const Operator * GetRestriction() const
Get the finite element space restriction operator.
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B, int copy_interior=0)
Operator that converts FiniteElementSpace L-vectors to E-vectors.
Definition: restriction.hpp:31
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:87
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition: fe.hpp:315
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
Definition: sparsemat.cpp:594
const FiniteElementSpace * trialFes
void Assemble()
Assemble at the level given for the BilinearFormExtension subclass.
void FillJAndData(const Vector &ea_data, SparseMatrix &mat) const
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, Operator *&A, Vector &X, Vector &B, int copy_interior=0)
Form a constrained linear system using a matrix-free approach.
Definition: operator.cpp:51
Vector & Set(const double a, const Vector &x)
(*this) = a * x
Definition: vector.cpp:228
EABilinearFormExtension(BilinearForm *form)
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:27
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
double a
Definition: lissajous.cpp:41
MixedBilinearForm * a
Not owned.
A &quot;square matrix&quot; operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
virtual const Operator * GetOutputProlongation() const
Get the test finite element space prolongation matrix.
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:372
virtual const Operator * GetOutputRestriction() const
Get the output finite element space restriction matrix.
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
const Operator * int_face_restrict_lex
void FormSystemOperator(const Array< int > &ess_tdof_list, Operator *&A)
Return in A a parallel (on truedofs) version of this square operator.
Definition: operator.cpp:164
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
Definition: fespace.hpp:65
void Update()
Update internals for when a new MixedBilinearForm is given to this class.
void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
Definition: sparsemat.cpp:721
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th element in t...
Definition: fespace.cpp:1798
Lexicographic ordering for tensor-product FiniteElements.
virtual void FillJAndData(const Vector &ea_data, SparseMatrix &mat, SparseMatrix &face_mat) const
void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Vector data type.
Definition: vector.hpp:51
const FiniteElementSpace * trialFes
const FiniteElementSpace * testFes
Array< BilinearFormIntegrator * > * GetDBFI()
Access all integrators added with AddDomainIntegrator().
int * HostReadWriteI()
Definition: sparsemat.hpp:200
void AssembleDiagonal(Vector &diag) const
Class for parallel grid function.
Definition: pgridfunc.hpp:32
Abstract operator.
Definition: operator.hpp:24
FiniteElementSpace * TrialFESpace()
Return the trial FE space associated with the BilinearForm.
MixedBilinearFormExtension(MixedBilinearForm *form)
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A)
Operator that converts L2 FiniteElementSpace L-vectors to E-vectors.
Definition: restriction.hpp:84
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A)
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:28
void FillSparseMatrix(const Vector &mat_ea, SparseMatrix &mat) const
Fill a Sparse Matrix with Element Matrices.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
Definition: handle.hpp:137
double f(const Vector &p)
void SyncAliasMemory(const Vector &v)
Update the alias memory location of the vector to match v.
Definition: vector.hpp:193