MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
complex_fem.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, 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#include "complex_fem.hpp"
13#include "../general/forall.hpp"
14#include "../general/text.hpp"
15
16using namespace std;
17
18namespace mfem
19{
20
22 : Vector(2*(f->GetVSize())), fes(f), fec_owned(NULL)
23{
24 UseDevice(true);
25 this->Vector::operator=(0.0);
26
27 gfr = new GridFunction();
28 gfr->MakeRef(fes, *this, 0);
29
30 gfi = new GridFunction();
31 gfi->MakeRef(fes, *this, fes->GetVSize());
32
34}
35
37 : Vector(), fes(NULL), fec_owned(NULL)
38{
39 string buff;
40
41 // Grid functions are stored on the device
42 UseDevice(true);
43
44 input >> std::ws;
45 getline(input, buff); // 'ComplexGridFunction'
46 filter_dos(buff);
47 if (buff != "ComplexGridFunction")
48 {
49 MFEM_ABORT("unrecognized file header: " << buff);
50 }
51
53 fec_owned = fes->Load(m, input);
54
55 skip_comment_lines(input, '#');
56 istream::int_type next_char = input.peek();
57 if (next_char == 'N') // First letter of "NURBS_patches"
58 {
59 getline(input, buff);
60 filter_dos(buff);
61 if (buff == "NURBS_patches")
62 {
63 MFEM_ABORT("NURBS not yet supported with ComplexGridFunction objects");
64 }
65 else
66 {
67 MFEM_ABORT("unknown section: " << buff);
68 }
69 }
70 else
71 {
72 Vector::Load(input, 2*fes->GetVSize());
73
74 // if the mesh is a legacy (v1.1) NC mesh, it has old vertex ordering
75 if (fes->Nonconforming() &&
77 {
78 // LegacyNCReorder();
79 MFEM_ABORT("LegacyNCReorder not supported for "
80 "ComplexGridFunction objects");
81 }
82 }
83
84 gfr = new GridFunction();
85 gfr->MakeRef(fes, *this, 0);
86
87 gfi = new GridFunction();
88 gfi->MakeRef(fes, *this, fes->GetVSize());
89
91}
92
94{
95 delete gfr; delete gfi;
96
97 if (fec_owned)
98 {
99 delete fes;
100 delete fec_owned;
101 fec_owned = NULL;
102 }
103}
104
105void
107{
108 if (fes->GetSequence() == fes_sequence)
109 {
110 return; // space and grid function are in sync, no-op
111 }
113
114 const int vsize = fes->GetVSize();
115
116 const Operator *T = fes->GetUpdateOperator();
117 if (T)
118 {
119 // Update the individual GridFunction objects. This will allocate new data
120 // arrays for each GridFunction.
121 gfr->Update();
122 gfi->Update();
123
124 // Our data array now contains old data as well as being the wrong size so
125 // reallocate it.
126 UseDevice(true);
127 this->SetSize(2 * vsize);
128 this->Vector::operator=(0.0);
129
130 // Create temporary vectors which point to the new data array
131 Vector gf_r; gf_r.MakeRef(*this, 0, vsize);
132 Vector gf_i; gf_i.MakeRef(*this, vsize, vsize);
133
134 // Copy the updated GridFunctions into the new data array
135 gf_r = *gfr;
136 gf_i = *gfi;
137 gf_r.SyncAliasMemory(*this);
138 gf_i.SyncAliasMemory(*this);
139
140 // Replace the individual data arrays with pointers into the new data
141 // array
142 gfr->MakeRef(*this, 0, vsize);
143 gfi->MakeRef(*this, vsize, vsize);
144 }
145 else
146 {
147 // The existing data will not be transferred to the new GridFunctions so
148 // delete it and allocate a new array
149 UseDevice(true);
150 this->SetSize(2 * vsize);
151 this->Vector::operator=(0.0);
152
153 // Point the individual GridFunctions to the new data array
154 gfr->MakeRef(*this, 0, vsize);
155 gfi->MakeRef(*this, vsize, vsize);
156
157 // These updates will only set the proper 'sequence' value within the
158 // individual GridFunction objects because their sizes are already correct
159 gfr->Update();
160 gfi->Update();
161 }
162}
163
165{
166 const FiniteElement *fe = fes->GetTypicalFE();
167 if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
168 {
169 return fes->GetVDim();
170 }
171 return fes->GetVDim()*std::max(fes->GetMesh()->SpaceDimension(),
172 fe->GetRangeDim());
173}
174
175void
177 Coefficient &imag_coeff)
178{
179 gfr->SyncMemory(*this);
180 gfi->SyncMemory(*this);
181 gfr->ProjectCoefficient(real_coeff);
182 gfi->ProjectCoefficient(imag_coeff);
183 gfr->SyncAliasMemory(*this);
184 gfi->SyncAliasMemory(*this);
185}
186
187void
189 VectorCoefficient &imag_vcoeff)
190{
191 gfr->SyncMemory(*this);
192 gfi->SyncMemory(*this);
193 gfr->ProjectCoefficient(real_vcoeff);
194 gfi->ProjectCoefficient(imag_vcoeff);
195 gfr->SyncAliasMemory(*this);
196 gfi->SyncAliasMemory(*this);
197}
198
199void
201 Coefficient &imag_coeff,
202 Array<int> &attr)
203{
204 gfr->SyncMemory(*this);
205 gfi->SyncMemory(*this);
206 gfr->ProjectBdrCoefficient(real_coeff, attr);
207 gfi->ProjectBdrCoefficient(imag_coeff, attr);
208 gfr->SyncAliasMemory(*this);
209 gfi->SyncAliasMemory(*this);
210}
211
212void
214 VectorCoefficient &imag_vcoeff,
215 Array<int> &attr)
216{
217 gfr->SyncMemory(*this);
218 gfi->SyncMemory(*this);
219 gfr->ProjectBdrCoefficientNormal(real_vcoeff, attr);
220 gfi->ProjectBdrCoefficientNormal(imag_vcoeff, attr);
221 gfr->SyncAliasMemory(*this);
222 gfi->SyncAliasMemory(*this);
223}
224
225void
227 &real_vcoeff,
229 &imag_vcoeff,
230 Array<int> &attr)
231{
232 gfr->SyncMemory(*this);
233 gfi->SyncMemory(*this);
234 gfr->ProjectBdrCoefficientTangent(real_vcoeff, attr);
235 gfi->ProjectBdrCoefficientTangent(imag_vcoeff, attr);
236 gfr->SyncAliasMemory(*this);
237 gfi->SyncAliasMemory(*this);
238}
239
240real_t
242 Coefficient &exsolr,
243 Coefficient &exsoli,
245 const IntegrationRule *irs[],
246 const Array<int> *elems) const
247{
248 real_t error = 0.0;
249 const FiniteElement *fe;
251 Vector valsr;
252 Vector valsi;
253
254 const GridFunction& gf_r = real();
255 const GridFunction& gf_i = imag();
256
257 for (int i = 0; i < fes->GetNE(); i++)
258 {
259 if (elems != NULL && (*elems)[i] == 0) { continue; }
260 fe = fes->GetFE(i);
261 const IntegrationRule *ir;
262 if (irs)
263 {
264 ir = irs[fe->GetGeomType()];
265 }
266 else
267 {
268 int intorder = 2*fe->GetOrder() + 3;
269 ir = &(IntRules.Get(fe->GetGeomType(), intorder));
270 }
271 real_t elem_error = 0.0;
272 gf_r.GetValues(i, *ir, valsr);
273 gf_i.GetValues(i, *ir, valsi);
275 for (int j = 0; j < ir->GetNPoints(); j++)
276 {
277 const IntegrationPoint &ip = ir->IntPoint(j);
278 T->SetIntPoint(&ip);
279 real_t diffr = valsr(j) - exsolr.Eval(*T, ip);
280 real_t diffi = valsi(j) - exsoli.Eval(*T, ip);
281 real_t diff = hypot(diffr, diffi);
282 if (p < infinity())
283 {
284 diff = pow(diff, p);
285 if (weight)
286 {
287 diff *= weight->Eval(*T, ip);
288 }
289 elem_error += ip.weight * T->Weight() * diff;
290 }
291 else
292 {
293 if (weight)
294 {
295 diff *= weight->Eval(*T, ip);
296 }
297 error = std::max(error, diff);
298 }
299 }
300 if (p < infinity())
301 {
302 // negative quadrature weights may cause the error to be negative
303 error += fabs(elem_error);
304 }
305 }
306
307 if (p < infinity())
308 {
309 error = pow(error, 1./p);
310 }
311
312 return error;
313}
314
315void ComplexGridFunction::Save(std::ostream &os) const
316{
317 os << "ComplexGridFunction\n";
318 fes->Save(os);
319 os << '\n';
321 {
322 Vector::Print(os, 1);
323 }
324 else
325 {
326 Vector::Print(os, fes->GetVDim());
327 }
328 os.flush();
329}
330
331void ComplexGridFunction::Save(const char *fname, int precision) const
332{
333 ofstream ofs(fname);
334 ofs.precision(precision);
335 Save(ofs);
336}
337
338std::ostream &operator<<(std::ostream &os, const ComplexGridFunction &sol)
339{
340 sol.Save(os);
341 return os;
342}
343
344
347 : Vector(2*(fes->GetVSize())),
348 conv(convention)
349{
350 UseDevice(true);
351 this->Vector::operator=(0.0);
352
353 lfr = new LinearForm();
354 lfr->MakeRef(fes, *this, 0);
355
356 lfi = new LinearForm();
357 lfi->MakeRef(fes, *this, fes->GetVSize());
358}
359
361 LinearForm *lf_r, LinearForm *lf_i,
363 : Vector(2*(fes->GetVSize())),
364 conv(convention)
365{
366 UseDevice(true);
367 this->Vector::operator=(0.0);
368
369 lfr = new LinearForm(fes, lf_r);
370 lfi = new LinearForm(fes, lf_i);
371
372 lfr->MakeRef(fes, *this, 0);
373 lfi->MakeRef(fes, *this, fes->GetVSize());
374}
375
377{
378 delete lfr;
379 delete lfi;
380}
381
382void
384 LinearFormIntegrator *lfi_imag)
385{
386 if ( lfi_real ) { lfr->AddDomainIntegrator(lfi_real); }
387 if ( lfi_imag ) { lfi->AddDomainIntegrator(lfi_imag); }
388}
389
390void
392 LinearFormIntegrator *lfi_imag,
393 Array<int> &elem_attr_marker)
394{
395 if ( lfi_real ) { lfr->AddDomainIntegrator(lfi_real, elem_attr_marker); }
396 if ( lfi_imag ) { lfi->AddDomainIntegrator(lfi_imag, elem_attr_marker); }
397}
398
399void
401 LinearFormIntegrator *lfi_imag)
402{
403 if ( lfi_real ) { lfr->AddBoundaryIntegrator(lfi_real); }
404 if ( lfi_imag ) { lfi->AddBoundaryIntegrator(lfi_imag); }
405}
406
407void
409 LinearFormIntegrator *lfi_imag,
410 Array<int> &bdr_attr_marker)
411{
412 if ( lfi_real ) { lfr->AddBoundaryIntegrator(lfi_real, bdr_attr_marker); }
413 if ( lfi_imag ) { lfi->AddBoundaryIntegrator(lfi_imag, bdr_attr_marker); }
414}
415
416void
418 LinearFormIntegrator *lfi_imag)
419{
420 if ( lfi_real ) { lfr->AddBdrFaceIntegrator(lfi_real); }
421 if ( lfi_imag ) { lfi->AddBdrFaceIntegrator(lfi_imag); }
422}
423
424void
426 LinearFormIntegrator *lfi_imag,
427 Array<int> &bdr_attr_marker)
428{
429 if ( lfi_real ) { lfr->AddBdrFaceIntegrator(lfi_real, bdr_attr_marker); }
430 if ( lfi_imag ) { lfi->AddBdrFaceIntegrator(lfi_imag, bdr_attr_marker); }
431}
432
433void
435{
437 this->Update(fes);
438}
439
440void
442{
443 UseDevice(true);
444 SetSize(2 * fes->GetVSize());
445 this->Vector::operator=(0.0);
446
447 lfr->MakeRef(fes, *this, 0);
448 lfi->MakeRef(fes, *this, fes->GetVSize());
449}
450
451void
453{
454 lfr->SyncMemory(*this);
455 lfi->SyncMemory(*this);
456 lfr->Assemble();
457 lfi->Assemble();
458 if (conv == ComplexOperator::BLOCK_SYMMETRIC) { *lfi *= -1.0; }
459 lfr->SyncAliasMemory(*this);
460 lfi->SyncAliasMemory(*this);
461}
462
463complex<real_t>
465{
466 real_t s = (conv == ComplexOperator::HERMITIAN) ? 1.0 : -1.0;
467 lfr->SyncMemory(*this);
468 lfi->SyncMemory(*this);
469 return complex<real_t>((*lfr)(gf.real()) - s * (*lfi)(gf.imag()),
470 (*lfr)(gf.imag()) + s * (*lfi)(gf.real()));
471}
472
473
474bool SesquilinearForm::RealInteg()
475{
476 int nint = blfr->GetFBFI()->Size() + blfr->GetDBFI()->Size() +
477 blfr->GetBBFI()->Size() + blfr->GetBFBFI()->Size();
478 return (nint != 0);
479}
480
481bool SesquilinearForm::ImagInteg()
482{
483 int nint = blfi->GetFBFI()->Size() + blfi->GetDBFI()->Size() +
484 blfi->GetBBFI()->Size() + blfi->GetBFBFI()->Size();
485 return (nint != 0);
486}
487
490 : conv(convention),
491 blfr(new BilinearForm(f)),
492 blfi(new BilinearForm(f))
493{}
494
496 BilinearForm *bfr, BilinearForm *bfi,
498 : conv(convention),
499 blfr(new BilinearForm(f,bfr)),
500 blfi(new BilinearForm(f,bfi))
501{}
502
504{
505 diag_policy = dpolicy;
506}
507
509{
510 delete blfr;
511 delete blfi;
512}
513
515 BilinearFormIntegrator *bfi_imag)
516{
517 if (bfi_real) { blfr->AddDomainIntegrator(bfi_real); }
518 if (bfi_imag) { blfi->AddDomainIntegrator(bfi_imag); }
519}
520
522 BilinearFormIntegrator *bfi_imag,
523 Array<int> & elem_marker)
524{
525 if (bfi_real) { blfr->AddDomainIntegrator(bfi_real, elem_marker); }
526 if (bfi_imag) { blfi->AddDomainIntegrator(bfi_imag, elem_marker); }
527}
528
529void
531 BilinearFormIntegrator *bfi_imag)
532{
533 if (bfi_real) { blfr->AddBoundaryIntegrator(bfi_real); }
534 if (bfi_imag) { blfi->AddBoundaryIntegrator(bfi_imag); }
535}
536
537void
539 BilinearFormIntegrator *bfi_imag,
540 Array<int> & bdr_marker)
541{
542 if (bfi_real) { blfr->AddBoundaryIntegrator(bfi_real, bdr_marker); }
543 if (bfi_imag) { blfi->AddBoundaryIntegrator(bfi_imag, bdr_marker); }
544}
545
546void
548 BilinearFormIntegrator *bfi_imag)
549{
550 if (bfi_real) { blfr->AddInteriorFaceIntegrator(bfi_real); }
551 if (bfi_imag) { blfi->AddInteriorFaceIntegrator(bfi_imag); }
552}
553
555 BilinearFormIntegrator *bfi_imag)
556{
557 if (bfi_real) { blfr->AddBdrFaceIntegrator(bfi_real); }
558 if (bfi_imag) { blfi->AddBdrFaceIntegrator(bfi_imag); }
559}
560
562 BilinearFormIntegrator *bfi_imag,
563 Array<int> &bdr_marker)
564{
565 if (bfi_real) { blfr->AddBdrFaceIntegrator(bfi_real, bdr_marker); }
566 if (bfi_imag) { blfi->AddBdrFaceIntegrator(bfi_imag, bdr_marker); }
567}
568
569void
571{
572 blfr->Assemble(skip_zeros);
573 blfi->Assemble(skip_zeros);
574}
575
576void
578{
579 blfr->Finalize(skip_zeros);
580 blfi->Finalize(skip_zeros);
581}
582
585{
586 return new ComplexSparseMatrix(&blfr->SpMat(),
587 &blfi->SpMat(),
588 false, false, conv);
589}
590
591void
592SesquilinearForm::BuildComplexOperator(OperatorHandle &A_r,
593 OperatorHandle &A_i,
594 OperatorHandle &A) const
595{
596 // A = A_r + i A_i
597 A.Clear();
598 if ((!A_r.Ptr() || A_r.Type() == Operator::MFEM_SPARSEMAT) &&
599 (!A_i.Ptr() || A_i.Type() == Operator::MFEM_SPARSEMAT))
600 {
601 ComplexSparseMatrix * A_sp =
603 A_i.As<SparseMatrix>(),
604 A_r.OwnsOperator(),
605 A_i.OwnsOperator(),
606 conv);
607 A.Reset<ComplexSparseMatrix>(A_sp, true);
608 }
609 else
610 {
611 ComplexOperator * A_op =
612 new ComplexOperator(A_r.Ptr(),
613 A_i.Ptr(),
614 A_r.OwnsOperator(),
615 A_i.OwnsOperator(),
616 conv);
617 A.Reset<ComplexOperator>(A_op, true);
618 }
619 A_r.SetOperatorOwner(false);
620 A_i.SetOperatorOwner(false);
621}
622
623void
625 Vector &x, Vector &b,
627 Vector &X, Vector &B,
628 int ci)
629{
630 FiniteElementSpace *fes = blfr->FESpace();
631 const int vsize = fes->GetVSize();
632
633 // Allocate temporary vector
634 Vector b_0;
635 b_0.UseDevice(true);
636 b_0.SetSize(vsize);
637 b_0 = 0.0;
638
639 // Extract the real and imaginary parts of the input vectors
640 MFEM_ASSERT(x.Size() == 2 * vsize, "Input GridFunction of incorrect size!");
641 x.Read();
642 Vector x_r; x_r.MakeRef(x, 0, vsize);
643 Vector x_i; x_i.MakeRef(x, vsize, vsize);
644
645 MFEM_ASSERT(b.Size() == 2 * vsize, "Input LinearForm of incorrect size!");
646 b.Read();
647 Vector b_r; b_r.MakeRef(b, 0, vsize);
648 Vector b_i; b_i.MakeRef(b, vsize, vsize);
649
650 if (conv == ComplexOperator::BLOCK_SYMMETRIC) { b_i *= -1.0; }
651
652 const int tvsize = fes->GetTrueVSize();
653 OperatorHandle A_r, A_i;
654
655 X.UseDevice(true);
656 X.SetSize(2 * tvsize);
657 X = 0.0;
658
659 B.UseDevice(true);
660 B.SetSize(2 * tvsize);
661 B = 0.0;
662
663 Vector X_r; X_r.MakeRef(X, 0, tvsize);
664 Vector X_i; X_i.MakeRef(X, tvsize, tvsize);
665 Vector B_r; B_r.MakeRef(B, 0, tvsize);
666 Vector B_i; B_i.MakeRef(B, tvsize, tvsize);
667
668 Vector X_0, B_0;
669
670 if (RealInteg())
671 {
672 blfr->SetDiagonalPolicy(diag_policy);
673
674 b_0 = b_r;
675 blfr->FormLinearSystem(ess_tdof_list, x_r, b_0, A_r, X_0, B_0, ci);
676 X_r = X_0; B_r = B_0;
677
678 b_0 = b_i;
679 blfr->FormLinearSystem(ess_tdof_list, x_i, b_0, A_r, X_0, B_0, ci);
680 X_i = X_0; B_i = B_0;
681
682 if (ImagInteg())
683 {
685
686 b_0 = 0.0;
687 blfi->FormLinearSystem(ess_tdof_list, x_i, b_0, A_i, X_0, B_0, false);
688 B_r -= B_0;
689
690 b_0 = 0.0;
691 blfi->FormLinearSystem(ess_tdof_list, x_r, b_0, A_i, X_0, B_0, false);
692 B_i += B_0;
693 }
694 }
695 else if (ImagInteg())
696 {
697 blfi->SetDiagonalPolicy(diag_policy);
698
699 b_0 = b_i;
700 blfi->FormLinearSystem(ess_tdof_list, x_r, b_0, A_i, X_0, B_0, ci);
701 X_r = X_0; B_i = B_0;
702
703 b_0 = b_r; b_0 *= -1.0;
704 blfi->FormLinearSystem(ess_tdof_list, x_i, b_0, A_i, X_0, B_0, ci);
705 X_i = X_0; B_r = B_0; B_r *= -1.0;
706 }
707 else
708 {
709 MFEM_ABORT("Real and Imaginary part of the Sesquilinear form are empty");
710 }
711
712 if (RealInteg() && ImagInteg())
713 {
714 // Modify RHS and off-diagonal blocks (imaginary parts of the matrix) to
715 // conform with standard essential BC treatment
716 if (A_i.Is<ConstrainedOperator>())
717 {
718 const int n = ess_tdof_list.Size();
719 auto d_B_r = B_r.Write();
720 auto d_B_i = B_i.Write();
721 auto d_X_r = X_r.Read();
722 auto d_X_i = X_i.Read();
723 auto d_idx = ess_tdof_list.Read();
724 mfem::forall(n, [=] MFEM_HOST_DEVICE (int i)
725 {
726 const int j = d_idx[i];
727 d_B_r[j] = d_X_r[j];
728 d_B_i[j] = d_X_i[j];
729 });
732 }
733 }
734
736 {
737 B_i *= -1.0;
738 b_i *= -1.0;
739 }
740
741 x_r.SyncAliasMemory(x);
742 x_i.SyncAliasMemory(x);
743 b_r.SyncAliasMemory(b);
744 b_i.SyncAliasMemory(b);
745
746 X_r.SyncAliasMemory(X);
747 X_i.SyncAliasMemory(X);
748 B_r.SyncAliasMemory(B);
749 B_i.SyncAliasMemory(B);
750
751 BuildComplexOperator(A_r, A_i, A);
752}
753
754void
757
758{
759 OperatorHandle A_r, A_i;
760 if (RealInteg())
761 {
762 blfr->SetDiagonalPolicy(diag_policy);
764 }
765 if (ImagInteg())
766 {
767 blfi->SetDiagonalPolicy(RealInteg() ?
769 diag_policy);
771 }
772 if (!RealInteg() && !ImagInteg())
773 {
774 MFEM_ABORT("Both Real and Imaginary part of the Sesquilinear form are empty");
775 }
776
777 if (RealInteg() && ImagInteg())
778 {
779 // Modify off-diagonal blocks (imaginary parts of the matrix) to conform
780 // with standard essential BC treatment
781 if (A_i.Is<ConstrainedOperator>())
782 {
785 }
786 }
787
788 BuildComplexOperator(A_r, A_i, A);
789}
790
791void
793 Vector &x)
794{
795 FiniteElementSpace *fes = blfr->FESpace();
796
797 const SparseMatrix *P = fes->GetConformingProlongation();
798 if (!P)
799 {
800 x = X;
801 return;
802 }
803
804 const int vsize = fes->GetVSize();
805 const int tvsize = X.Size() / 2;
806
807 X.Read();
808 Vector X_r; X_r.MakeRef(const_cast<Vector&>(X), 0, tvsize);
809 Vector X_i; X_i.MakeRef(const_cast<Vector&>(X), tvsize, tvsize);
810
811 x.Write();
812 Vector x_r; x_r.MakeRef(x, 0, vsize);
813 Vector x_i; x_i.MakeRef(x, vsize, vsize);
814
815 // Apply conforming prolongation
816 P->Mult(X_r, x_r);
817 P->Mult(X_i, x_i);
818
819 x_r.SyncAliasMemory(x);
820 x_i.SyncAliasMemory(x);
821}
822
823void
825{
826 if ( blfr ) { blfr->Update(nfes); }
827 if ( blfi ) { blfi->Update(nfes); }
828}
829
830bool
831MixedSesquilinearForm::RealInteg()
832{
833 int nint = mblfr->GetDBFI()->Size() + mblfr->GetBBFI()->Size() +
834 mblfr->GetFBFI()->Size() + mblfr->GetBFBFI()->Size() +
835 mblfr->GetTFBFI()->Size() + mblfr->GetBTFBFI()->Size();
836 return (nint != 0);
837}
838
839bool
840MixedSesquilinearForm::ImagInteg()
841{
842 int nint = mblfi->GetDBFI()->Size() + mblfi->GetBBFI()->Size() +
843 mblfi->GetFBFI()->Size() + mblfi->GetBFBFI()->Size() +
844 mblfi->GetTFBFI()->Size() + mblfi->GetBTFBFI()->Size();
845 return (nint != 0);
846}
847
849 FiniteElementSpace * test_fes,
851 : conv(convention),
852 mblfr(new mfem::MixedBilinearForm(trial_fes, test_fes)),
853 mblfi(new mfem::MixedBilinearForm(trial_fes, test_fes))
854{
855}
856
858 FiniteElementSpace * test_fes,
859 MixedBilinearForm * bfr,
860 MixedBilinearForm * bfi,
862 : conv(convention),
863 mblfr(new MixedBilinearForm(trial_fes, test_fes, bfr)),
864 mblfi(new MixedBilinearForm(trial_fes, test_fes, bfi))
865{
866}
867
869{
870 delete mblfr;
871 delete mblfi;
872}
873
874void
876 BilinearFormIntegrator * bfi_imag)
877{
878 if (bfi_real)
879 {
880 mblfr->AddDomainIntegrator(bfi_real);
881 }
882 if (bfi_imag)
883 {
884 mblfi->AddDomainIntegrator(bfi_imag);
885 }
886}
887
888void
890 BilinearFormIntegrator * bfi_imag,
891 Array<int> & elem_marker)
892{
893 if (bfi_real)
894 {
895 mblfr->AddDomainIntegrator(bfi_real, elem_marker);
896 }
897 if (bfi_imag)
898 {
899 mblfi->AddDomainIntegrator(bfi_imag, elem_marker);
900 }
901}
902
903void
905 BilinearFormIntegrator * bfi_imag)
906{
907 if (bfi_real)
908 {
909 mblfr->AddBoundaryIntegrator(bfi_real);
910 }
911 if (bfi_imag)
912 {
913 mblfi->AddBoundaryIntegrator(bfi_imag);
914 }
915}
916
917void
919 BilinearFormIntegrator * bfi_imag,
920 Array<int> & bdr_marker)
921{
922 if (bfi_real)
923 {
924 mblfr->AddBoundaryIntegrator(bfi_real, bdr_marker);
925 }
926 if (bfi_imag)
927 {
928 mblfi->AddBoundaryIntegrator(bfi_imag, bdr_marker);
929 }
930}
931
932void
934 bfi_real,
935 BilinearFormIntegrator * bfi_imag)
936{
937 if (bfi_real)
938 {
939 mblfr->AddInteriorFaceIntegrator(bfi_real);
940 }
941 if (bfi_imag)
942 {
943 mblfi->AddInteriorFaceIntegrator(bfi_imag);
944 }
945}
946
947void
949 BilinearFormIntegrator * bfi_imag)
950{
951 if (bfi_real)
952 {
953 mblfr->AddBdrFaceIntegrator(bfi_real);
954 }
955 if (bfi_imag)
956 {
957 mblfi->AddBdrFaceIntegrator(bfi_imag);
958 }
959}
960
961void
963 BilinearFormIntegrator * bfi_imag,
964 Array<int> & bdr_marker)
965{
966 if (bfi_real)
967 {
968 mblfr->AddBdrFaceIntegrator(bfi_real, bdr_marker);
969 }
970 if (bfi_imag)
971 {
972 mblfi->AddBdrFaceIntegrator(bfi_imag, bdr_marker);
973 }
974}
975
977 bfi_real,
978 BilinearFormIntegrator * bfi_imag)
979{
980 if (bfi_real)
981 {
982 mblfr->AddTraceFaceIntegrator(bfi_real);
983 }
984 if (bfi_imag)
985 {
986 mblfi->AddTraceFaceIntegrator(bfi_imag);
987 }
988}
989
991 *bfi_real,
992 BilinearFormIntegrator *bfi_imag)
993{
994 if (bfi_real)
995 {
996 mblfr->AddBdrTraceFaceIntegrator(bfi_real);
997 }
998 if (bfi_imag)
999 {
1000 mblfi->AddBdrTraceFaceIntegrator(bfi_imag);
1001 }
1002}
1003
1005 *bfi_real,
1006 BilinearFormIntegrator *bfi_imag,
1007 Array<int> &bdr_marker)
1008{
1009 if (bfi_real)
1010 {
1011 mblfr->AddBdrTraceFaceIntegrator(bfi_real, bdr_marker);
1012 }
1013 if (bfi_imag)
1014 {
1015 mblfi->AddBdrTraceFaceIntegrator(bfi_imag, bdr_marker);
1016 }
1017}
1018
1019void
1021{
1022 mblfr->Assemble(skip_zeros);
1023 mblfi->Assemble(skip_zeros);
1024}
1025
1026void
1028{
1029 mblfr->Finalize(skip_zeros);
1030 mblfi->Finalize(skip_zeros);
1031}
1032
1035{
1036 return new mfem::ComplexSparseMatrix(
1037 &mblfr->SpMat(), &mblfi->SpMat(), false, false, conv);
1038}
1039
1040void
1042 ess_trial_tdof_list,
1043 const Array<int> & ess_test_tdof_list,
1044 Vector & x,
1045 Vector & b,
1046 OperatorHandle & A,
1047 Vector & X,
1048 Vector & B)
1049{
1050 FiniteElementSpace * fes_trial = mblfr->TrialFESpace();
1051 FiniteElementSpace * fes_test = mblfr->TestFESpace();
1052 const int vsize_trial = fes_trial->GetVSize();
1053 const int vsize_test = fes_test->GetVSize();
1054
1055 // Allocate temporary Vector
1056 Vector b_0;
1057 b_0.UseDevice(true);
1058 b_0.SetSize(vsize_test);
1059 b_0 = 0.0;
1060
1061 // Extract the real and imaginary parts of the input Vectors
1062 MFEM_ASSERT(x.Size() == 2 * vsize_trial,
1063 "Input GridFunction of incorrect size!");
1064 x.Read();
1065 Vector x_r;
1066 x_r.MakeRef(x, 0, vsize_trial);
1067 Vector x_i;
1068 x_i.MakeRef(x, vsize_trial, vsize_trial);
1069
1070 MFEM_ASSERT(b.Size() == 2 * vsize_test, "Input LinearForm of incorrect size!");
1071 b.Read();
1072 Vector b_r;
1073 b_r.MakeRef(b, 0, vsize_test);
1074 Vector b_i;
1075 b_i.MakeRef(b, vsize_test, vsize_test);
1076
1078 {
1079 b_i *= -1.0;
1080 }
1081
1082 const int tvsize_trial = fes_trial->GetTrueVSize();
1083 const int tvsize_test = fes_test->GetTrueVSize();
1084 OperatorHandle A_r, A_i;
1085
1086 X.UseDevice(true);
1087 X.SetSize(2 * tvsize_trial);
1088 X = 0.0;
1089
1090 B.UseDevice(true);
1091 B.SetSize(2 * tvsize_test);
1092 B = 0.0;
1093
1094 Vector X_r;
1095 X_r.MakeRef(X, 0, tvsize_trial);
1096 Vector X_i;
1097 X_i.MakeRef(X, tvsize_trial, tvsize_trial);
1098 Vector B_r;
1099 B_r.MakeRef(B, 0, tvsize_test);
1100 Vector B_i;
1101 B_i.MakeRef(B, tvsize_test, tvsize_test);
1102
1103 Vector X_0, B_0;
1104
1105 if (RealInteg())
1106 {
1107 b_0 = b_r;
1109 ess_trial_tdof_list, ess_test_tdof_list, x_r, b_0, A_r, X_0, B_0);
1110 X_r = X_0;
1111 B_r = B_0;
1112
1113 b_0 = b_i;
1115 ess_trial_tdof_list, ess_test_tdof_list, x_i, b_0, A_r, X_0, B_0);
1116 X_i = X_0;
1117 B_i = B_0;
1118
1119 if (ImagInteg())
1120 {
1121 b_0 = 0.0;
1123 ess_trial_tdof_list, ess_test_tdof_list, x_i, b_0, A_i, X_0, B_0);
1124 B_r -= B_0;
1125
1126 b_0 = 0.0;
1128 ess_trial_tdof_list, ess_test_tdof_list, x_r, b_0, A_i, X_0, B_0);
1129 B_i += B_0;
1130 }
1131 }
1132 else if (ImagInteg())
1133 {
1134 b_0 = b_i;
1136 ess_trial_tdof_list, ess_test_tdof_list, x_r, b_0, A_i, X_0, B_0);
1137 X_r = X_0;
1138 B_i = B_0;
1139
1140 b_0 = b_r;
1141 b_0 *= -1.0;
1143 ess_trial_tdof_list, ess_test_tdof_list, x_i, b_0, A_i, X_0, B_0);
1144 X_i = X_0;
1145 B_r = B_0;
1146 B_r *= -1.0;
1147 }
1148 else
1149 {
1150 MFEM_ABORT("Real and Imaginary part of the Mixed Sesquilinear form are empty");
1151 }
1152
1154 {
1155 B_i *= -1.0;
1156 b_i *= -1.0;
1157 }
1158
1159 x_r.SyncAliasMemory(x);
1160 x_i.SyncAliasMemory(x);
1161 b_r.SyncAliasMemory(b);
1162 b_i.SyncAliasMemory(b);
1163
1164 X_r.SyncAliasMemory(X);
1165 X_i.SyncAliasMemory(X);
1166 B_r.SyncAliasMemory(B);
1167 B_i.SyncAliasMemory(B);
1168
1169 // A = A_r + i A_i
1170 A.Clear();
1171 if ((!A_r.Ptr() || A_r.Type() == Operator::MFEM_SPARSEMAT) &&
1172 (!A_i.Ptr() || A_i.Type() == Operator::MFEM_SPARSEMAT))
1173 {
1174 ComplexSparseMatrix * A_hyp =
1176 A_i.As<SparseMatrix>(),
1177 A_r.OwnsOperator(),
1178 A_i.OwnsOperator(),
1179 conv);
1180 A.Reset<ComplexSparseMatrix>(A_hyp, true);
1181 }
1182 else
1183 {
1184 ComplexOperator * A_op = new ComplexOperator(A_r.As<Operator>(),
1185 A_i.As<Operator>(),
1186 A_r.OwnsOperator(),
1187 A_i.OwnsOperator(),
1188 conv);
1189 A.Reset<ComplexOperator>(A_op, true);
1190 }
1191 A_r.SetOperatorOwner(false);
1192 A_i.SetOperatorOwner(false);
1193}
1194
1195void
1197 ess_trial_tdof_list,
1198 const mfem::Array<int> & ess_test_tdof_list,
1200{
1201 OperatorHandle A_r, A_i;
1202 if (RealInteg())
1203 {
1204 mblfr->FormRectangularSystemMatrix(ess_trial_tdof_list, ess_test_tdof_list,
1205 A_r);
1206 }
1207 if (ImagInteg())
1208 {
1209 mblfi->FormRectangularSystemMatrix(ess_trial_tdof_list, ess_test_tdof_list,
1210 A_i);
1211 }
1212 if (!RealInteg() && !ImagInteg())
1213 {
1214 MFEM_ABORT("Both Real and Imaginary part of the Mixed Sesquilinear form are empty");
1215 }
1216
1217 // A = A_r + i A_i
1218 A.Clear();
1219 if ((!A_r.Ptr() || A_r.Type() == Operator::MFEM_SPARSEMAT) &&
1220 (!A_i.Ptr() || A_i.Type() == Operator::MFEM_SPARSEMAT))
1221 {
1222 ComplexSparseMatrix * A_hyp =
1224 A_i.As<SparseMatrix>(),
1225 A_r.OwnsOperator(),
1226 A_i.OwnsOperator(),
1227 conv);
1228 A.Reset<ComplexSparseMatrix>(A_hyp, true);
1229 }
1230 else
1231 {
1232 ComplexOperator * A_op = new ComplexOperator(A_r.As<Operator>(),
1233 A_i.As<Operator>(),
1234 A_r.OwnsOperator(),
1235 A_i.OwnsOperator(),
1236 conv);
1237 A.Reset<ComplexOperator>(A_op, true);
1238 }
1239 A_r.SetOperatorOwner(false);
1240 A_i.SetOperatorOwner(false);
1241}
1242
1243void
1245{
1246 mblfr->Update();
1247 mblfi->Update();
1248}
1249
1250
1251#ifdef MFEM_USE_MPI
1252
1254 : Vector(2*(pf->GetVSize())), pfes(pf), fec_owned(NULL)
1255{
1256 UseDevice(true);
1257 this->Vector::operator=(0.0);
1258
1259 pgfr = new ParGridFunction();
1260 pgfr->MakeRef(pfes, *this, 0);
1261
1262 pgfi = new ParGridFunction();
1263 pgfi->MakeRef(pfes, *this, pfes->GetVSize());
1264
1266}
1267
1269 : Vector(), pfes(NULL), fec_owned(NULL)
1270{
1271 string buff;
1272
1273 // Grid functions are stored on the device
1274 UseDevice(true);
1275
1276 input >> std::ws;
1277 getline(input, buff); // 'ParComplexGridFunction'
1278 filter_dos(buff);
1279 if (buff != "ParComplexGridFunction")
1280 {
1281 MFEM_ABORT("unrecognized file header: " << buff);
1282 }
1283
1285 fec_owned = fes->Load(m, input);
1286
1288 fes->GetOrdering());
1289
1290 delete fes;
1291
1292 skip_comment_lines(input, '#');
1293 istream::int_type next_char = input.peek();
1294 if (next_char == 'N') // First letter of "NURBS_patches"
1295 {
1296 getline(input, buff);
1297 filter_dos(buff);
1298 if (buff == "NURBS_patches")
1299 {
1300 MFEM_ABORT("NURBS not yet supported with ComplexGridFunction objects");
1301 }
1302 else
1303 {
1304 MFEM_ABORT("unknown section: " << buff);
1305 }
1306 }
1307 else
1308 {
1309 int vsize = pfes->GetVSize();
1310 Vector::Load(input, 2*vsize);
1311
1312 real_t *h_data = HostReadWrite();
1313 pfes->ApplyDofSigns(h_data);
1314 pfes->ApplyDofSigns(h_data + vsize);
1315
1316
1317 // if the mesh is a legacy (v1.1) NC mesh, it has old vertex ordering
1318 if (pfes->Nonconforming() &&
1320 {
1321 // LegacyNCReorder();
1322 MFEM_ABORT("LegacyNCReorder not supported for "
1323 "ComplexGridFunction objects");
1324 }
1325 }
1326
1327 pgfr = new ParGridFunction();
1328 pgfr->MakeRef(pfes, *this, 0);
1329
1330 pgfi = new ParGridFunction();
1331 pgfi->MakeRef(pfes, *this, pfes->GetVSize());
1332
1334}
1335
1337{
1338 delete pgfr; delete pgfi;
1339
1340 if (fec_owned)
1341 {
1342 delete pfes;
1343 delete fec_owned;
1344 fec_owned = NULL;
1345 }
1346}
1347
1348void
1350{
1351 if (pfes->GetSequence() == fes_sequence)
1352 {
1353 return; // space and grid function are in sync, no-op
1354 }
1356
1357 const int vsize = pfes->GetVSize();
1358
1359 const Operator *T = pfes->GetUpdateOperator();
1360 if (T)
1361 {
1362 // Update the individual GridFunction objects. This will allocate new data
1363 // arrays for each GridFunction.
1364 pgfr->Update();
1365 pgfi->Update();
1366
1367 // Our data array now contains old data as well as being the wrong size so
1368 // reallocate it.
1369 UseDevice(true);
1370 this->SetSize(2 * vsize);
1371 this->Vector::operator=(0.0);
1372
1373 // Create temporary vectors which point to the new data array
1374 Vector gf_r; gf_r.MakeRef(*this, 0, vsize);
1375 Vector gf_i; gf_i.MakeRef(*this, vsize, vsize);
1376
1377 // Copy the updated GridFunctions into the new data array
1378 gf_r = *pgfr; gf_r.SyncAliasMemory(*this);
1379 gf_i = *pgfi; gf_i.SyncAliasMemory(*this);
1380
1381 // Replace the individual data arrays with pointers into the new data
1382 // array
1383 pgfr->MakeRef(*this, 0, vsize);
1384 pgfi->MakeRef(*this, vsize, vsize);
1385 }
1386 else
1387 {
1388 // The existing data will not be transferred to the new GridFunctions so
1389 // delete it and allocate a new array
1390 UseDevice(true);
1391 this->SetSize(2 * vsize);
1392 this->Vector::operator=(0.0);
1393
1394 // Point the individual GridFunctions to the new data array
1395 pgfr->MakeRef(*this, 0, vsize);
1396 pgfi->MakeRef(*this, vsize, vsize);
1397
1398 // These updates will only set the proper 'sequence' value within the
1399 // individual GridFunction objects because their sizes are already correct
1400 pgfr->Update();
1401 pgfi->Update();
1402 }
1403}
1404
1406{
1407 const FiniteElement *fe = pfes->GetTypicalFE();
1408 if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
1409 {
1410 return pfes->GetVDim();
1411 }
1412 return pfes->GetVDim()*std::max(pfes->GetMesh()->SpaceDimension(),
1413 fe->GetRangeDim());
1414}
1415
1416void
1418 Coefficient &imag_coeff)
1419{
1420 pgfr->SyncMemory(*this);
1421 pgfi->SyncMemory(*this);
1422 pgfr->ProjectCoefficient(real_coeff);
1423 pgfi->ProjectCoefficient(imag_coeff);
1424 pgfr->SyncAliasMemory(*this);
1425 pgfi->SyncAliasMemory(*this);
1426}
1427
1428void
1430 VectorCoefficient &imag_vcoeff)
1431{
1432 pgfr->SyncMemory(*this);
1433 pgfi->SyncMemory(*this);
1434 pgfr->ProjectCoefficient(real_vcoeff);
1435 pgfi->ProjectCoefficient(imag_vcoeff);
1436 pgfr->SyncAliasMemory(*this);
1437 pgfi->SyncAliasMemory(*this);
1438}
1439
1440void
1442 Coefficient &imag_coeff,
1443 Array<int> &attr)
1444{
1445 pgfr->SyncMemory(*this);
1446 pgfi->SyncMemory(*this);
1447 pgfr->ProjectBdrCoefficient(real_coeff, attr);
1448 pgfi->ProjectBdrCoefficient(imag_coeff, attr);
1449 pgfr->SyncAliasMemory(*this);
1450 pgfi->SyncAliasMemory(*this);
1451}
1452
1453void
1455 &real_vcoeff,
1457 &imag_vcoeff,
1458 Array<int> &attr)
1459{
1460 pgfr->SyncMemory(*this);
1461 pgfi->SyncMemory(*this);
1462 pgfr->ProjectBdrCoefficientNormal(real_vcoeff, attr);
1463 pgfi->ProjectBdrCoefficientNormal(imag_vcoeff, attr);
1464 pgfr->SyncAliasMemory(*this);
1465 pgfi->SyncAliasMemory(*this);
1466}
1467
1468void
1470 &real_vcoeff,
1472 &imag_vcoeff,
1473 Array<int> &attr)
1474{
1475 pgfr->SyncMemory(*this);
1476 pgfi->SyncMemory(*this);
1477 pgfr->ProjectBdrCoefficientTangent(real_vcoeff, attr);
1478 pgfi->ProjectBdrCoefficientTangent(imag_vcoeff, attr);
1479 pgfr->SyncAliasMemory(*this);
1480 pgfi->SyncAliasMemory(*this);
1481}
1482
1483void
1485{
1486 const int tvsize = pfes->GetTrueVSize();
1487
1488 tv->Read();
1489 Vector tvr; tvr.MakeRef(const_cast<Vector&>(*tv), 0, tvsize);
1490 Vector tvi; tvi.MakeRef(const_cast<Vector&>(*tv), tvsize, tvsize);
1491
1492 pgfr->SyncMemory(*this);
1493 pgfi->SyncMemory(*this);
1494 pgfr->Distribute(tvr);
1495 pgfi->Distribute(tvi);
1496 pgfr->SyncAliasMemory(*this);
1497 pgfi->SyncAliasMemory(*this);
1498}
1499
1500void
1502{
1503 const int tvsize = pfes->GetTrueVSize();
1504
1505 tv.Write();
1506 Vector tvr; tvr.MakeRef(tv, 0, tvsize);
1507 Vector tvi; tvi.MakeRef(tv, tvsize, tvsize);
1508
1509 pgfr->SyncMemory(*this);
1510 pgfi->SyncMemory(*this);
1511 pgfr->ParallelProject(tvr);
1512 pgfi->ParallelProject(tvi);
1513 pgfr->SyncAliasMemory(*this);
1514 pgfi->SyncAliasMemory(*this);
1515
1516 tvr.SyncAliasMemory(tv);
1517 tvi.SyncAliasMemory(tv);
1518}
1519
1520void ParComplexGridFunction::Save(std::ostream &os) const
1521{
1522 os << "ParComplexGridFunction\n";
1523 pfes->Save(os);
1524 os << '\n';
1525
1526 int vsize = pfes->GetVSize();
1527 // We use const_cast + HostRead (instead of HostReadWrite) because we only
1528 // need to change the host data temporarily and this way we do not invalidate
1529 // the data if it is on device. If we use HostReadWrite here, later calls to
1530 // Read or ReadWrite will need to copy the data from host to device. With the
1531 // approach used here, the host-to-device copy is avoided.
1532 real_t *h_data = const_cast<real_t*>(HostRead());
1533 pfes->ApplyDofSigns(h_data);
1534 pfes->ApplyDofSigns(h_data + vsize);
1535
1537 {
1538 Vector::Print(os, 1);
1539 }
1540 else
1541 {
1542 Vector::Print(os, pfes->GetVDim());
1543 }
1544
1545 pfes->ApplyDofSigns(h_data);
1546 pfes->ApplyDofSigns(h_data + vsize);
1547
1548 os.flush();
1549}
1550
1551void ParComplexGridFunction::Save(const char *fname, int precision) const
1552{
1553 int rank = pfes->GetMyRank();
1554 ostringstream fname_with_suffix;
1555 fname_with_suffix << fname << "." << setfill('0') << setw(6) << rank;
1556 ofstream ofs(fname_with_suffix.str().c_str());
1557 ofs.precision(precision);
1558 Save(ofs);
1559}
1560
1561std::ostream &operator<<(std::ostream &os, const ParComplexGridFunction &sol)
1562{
1563 sol.Save(os);
1564 return os;
1565}
1566
1567
1570 convention)
1571 : Vector(2*(pfes->GetVSize())),
1572 conv(convention)
1573{
1574 UseDevice(true);
1575 this->Vector::operator=(0.0);
1576
1577 plfr = new ParLinearForm();
1578 plfr->MakeRef(pfes, *this, 0);
1579
1580 plfi = new ParLinearForm();
1581 plfi->MakeRef(pfes, *this, pfes->GetVSize());
1582
1583 HYPRE_BigInt *tdof_offsets_fes = pfes->GetTrueDofOffsets();
1584
1585 int n = (HYPRE_AssumedPartitionCheck()) ? 2 : pfes->GetNRanks();
1586 tdof_offsets = new HYPRE_BigInt[n+1];
1587
1588 for (int i = 0; i <= n; i++)
1589 {
1590 tdof_offsets[i] = 2 * tdof_offsets_fes[i];
1591 }
1592}
1593
1594
1596 ParLinearForm *plf_r,
1597 ParLinearForm *plf_i,
1599 convention)
1600 : Vector(2*(pfes->GetVSize())),
1601 conv(convention)
1602{
1603 UseDevice(true);
1604 this->Vector::operator=(0.0);
1605
1606 plfr = new ParLinearForm(pfes, plf_r);
1607 plfi = new ParLinearForm(pfes, plf_i);
1608
1609 plfr->MakeRef(pfes, *this, 0);
1610 plfi->MakeRef(pfes, *this, pfes->GetVSize());
1611
1612 HYPRE_BigInt *tdof_offsets_fes = pfes->GetTrueDofOffsets();
1613
1614 int n = (HYPRE_AssumedPartitionCheck()) ? 2 : pfes->GetNRanks();
1615 tdof_offsets = new HYPRE_BigInt[n+1];
1616
1617 for (int i = 0; i <= n; i++)
1618 {
1619 tdof_offsets[i] = 2 * tdof_offsets_fes[i];
1620 }
1621}
1622
1624{
1625 delete plfr;
1626 delete plfi;
1627 delete [] tdof_offsets;
1628}
1629
1630void
1632 LinearFormIntegrator *lfi_imag)
1633{
1634 if ( lfi_real ) { plfr->AddDomainIntegrator(lfi_real); }
1635 if ( lfi_imag ) { plfi->AddDomainIntegrator(lfi_imag); }
1636}
1637
1638void
1640 LinearFormIntegrator *lfi_imag,
1641 Array<int> &elem_attr_marker)
1642{
1643 if ( lfi_real ) { plfr->AddDomainIntegrator(lfi_real, elem_attr_marker); }
1644 if ( lfi_imag ) { plfi->AddDomainIntegrator(lfi_imag, elem_attr_marker); }
1645}
1646
1647void
1649 LinearFormIntegrator *lfi_imag)
1650{
1651 if ( lfi_real ) { plfr->AddBoundaryIntegrator(lfi_real); }
1652 if ( lfi_imag ) { plfi->AddBoundaryIntegrator(lfi_imag); }
1653}
1654
1655void
1657 LinearFormIntegrator *lfi_imag,
1658 Array<int> &bdr_attr_marker)
1659{
1660 if ( lfi_real ) { plfr->AddBoundaryIntegrator(lfi_real, bdr_attr_marker); }
1661 if ( lfi_imag ) { plfi->AddBoundaryIntegrator(lfi_imag, bdr_attr_marker); }
1662}
1663
1664void
1666 LinearFormIntegrator *lfi_imag)
1667{
1668 if ( lfi_real ) { plfr->AddBdrFaceIntegrator(lfi_real); }
1669 if ( lfi_imag ) { plfi->AddBdrFaceIntegrator(lfi_imag); }
1670}
1671
1672void
1674 LinearFormIntegrator *lfi_imag,
1675 Array<int> &bdr_attr_marker)
1676{
1677 if ( lfi_real ) { plfr->AddBdrFaceIntegrator(lfi_real, bdr_attr_marker); }
1678 if ( lfi_imag ) { plfi->AddBdrFaceIntegrator(lfi_imag, bdr_attr_marker); }
1679}
1680
1681void
1683{
1684 ParFiniteElementSpace *pfes = (pf != NULL) ? pf : plfr->ParFESpace();
1685
1686 UseDevice(true);
1687 SetSize(2 * pfes->GetVSize());
1688 this->Vector::operator=(0.0);
1689
1690 plfr->MakeRef(pfes, *this, 0);
1691 plfi->MakeRef(pfes, *this, pfes->GetVSize());
1692}
1693
1694void
1696{
1697 plfr->SyncMemory(*this);
1698 plfi->SyncMemory(*this);
1699 plfr->Assemble();
1700 plfi->Assemble();
1701 if (conv == ComplexOperator::BLOCK_SYMMETRIC) { *plfi *= -1.0; }
1702 plfr->SyncAliasMemory(*this);
1703 plfi->SyncAliasMemory(*this);
1704}
1705
1706void
1708{
1709 const int tvsize = plfr->ParFESpace()->GetTrueVSize();
1710
1711 tv.Write();
1712 Vector tvr; tvr.MakeRef(tv, 0, tvsize);
1713 Vector tvi; tvi.MakeRef(tv, tvsize, tvsize);
1714
1715 plfr->SyncMemory(*this);
1716 plfi->SyncMemory(*this);
1717 plfr->ParallelAssemble(tvr);
1718 plfi->ParallelAssemble(tvi);
1719 plfr->SyncAliasMemory(*this);
1720 plfi->SyncAliasMemory(*this);
1721
1722 tvr.SyncAliasMemory(tv);
1723 tvi.SyncAliasMemory(tv);
1724}
1725
1728{
1729 const ParFiniteElementSpace *pfes = plfr->ParFESpace();
1730 const int tvsize = pfes->GetTrueVSize();
1731
1732 HypreParVector *tv = new HypreParVector(pfes->GetComm(),
1733 2*(pfes->GlobalTrueVSize()),
1734 tdof_offsets);
1735
1736 tv->Write();
1737 Vector tvr; tvr.MakeRef(*tv, 0, tvsize);
1738 Vector tvi; tvi.MakeRef(*tv, tvsize, tvsize);
1739
1740 plfr->SyncMemory(*this);
1741 plfi->SyncMemory(*this);
1742 plfr->ParallelAssemble(tvr);
1743 plfi->ParallelAssemble(tvi);
1744 plfr->SyncAliasMemory(*this);
1745 plfi->SyncAliasMemory(*this);
1746
1747 tvr.SyncAliasMemory(*tv);
1748 tvi.SyncAliasMemory(*tv);
1749
1750 return tv;
1751}
1752
1753complex<real_t>
1755{
1756 plfr->SyncMemory(*this);
1757 plfi->SyncMemory(*this);
1758 real_t s = (conv == ComplexOperator::HERMITIAN) ? 1.0 : -1.0;
1759 return complex<real_t>((*plfr)(gf.real()) - s * (*plfi)(gf.imag()),
1760 (*plfr)(gf.imag()) + s * (*plfi)(gf.real()));
1761}
1762
1763
1764bool ParSesquilinearForm::RealInteg()
1765{
1766 int nint = pblfr->GetFBFI()->Size() + pblfr->GetDBFI()->Size() +
1767 pblfr->GetBBFI()->Size() + pblfr->GetBFBFI()->Size();
1768 return (nint != 0);
1769}
1770
1771bool ParSesquilinearForm::ImagInteg()
1772{
1773 int nint = pblfi->GetFBFI()->Size() + pblfi->GetDBFI()->Size() +
1774 pblfi->GetBBFI()->Size() + pblfi->GetBFBFI()->Size();
1775 return (nint != 0);
1776}
1777
1780 convention)
1781 : conv(convention),
1782 pblfr(new ParBilinearForm(pf)),
1783 pblfi(new ParBilinearForm(pf))
1784{}
1785
1787 ParBilinearForm *pbfr,
1788 ParBilinearForm *pbfi,
1789 ComplexOperator::Convention convention)
1790 : conv(convention),
1791 pblfr(new ParBilinearForm(pf,pbfr)),
1792 pblfi(new ParBilinearForm(pf,pbfi))
1793{}
1794
1796{
1797 delete pblfr;
1798 delete pblfi;
1799}
1800
1802 BilinearFormIntegrator *bfi_imag)
1803{
1804 if (bfi_real) { pblfr->AddDomainIntegrator(bfi_real); }
1805 if (bfi_imag) { pblfi->AddDomainIntegrator(bfi_imag); }
1806}
1807
1809 BilinearFormIntegrator *bfi_imag,
1810 Array<int> & elem_marker)
1811{
1812 if (bfi_real) { pblfr->AddDomainIntegrator(bfi_real, elem_marker); }
1813 if (bfi_imag) { pblfi->AddDomainIntegrator(bfi_imag, elem_marker); }
1814}
1815
1816void
1818 BilinearFormIntegrator *bfi_imag)
1819{
1820 if (bfi_real) { pblfr->AddBoundaryIntegrator(bfi_real); }
1821 if (bfi_imag) { pblfi->AddBoundaryIntegrator(bfi_imag); }
1822}
1823
1824void
1826 BilinearFormIntegrator *bfi_imag,
1827 Array<int> & bdr_marker)
1828{
1829 if (bfi_real) { pblfr->AddBoundaryIntegrator(bfi_real, bdr_marker); }
1830 if (bfi_imag) { pblfi->AddBoundaryIntegrator(bfi_imag, bdr_marker); }
1831}
1832
1833void
1835 BilinearFormIntegrator *bfi_imag)
1836{
1837 if (bfi_real) { pblfr->AddInteriorFaceIntegrator(bfi_real); }
1838 if (bfi_imag) { pblfi->AddInteriorFaceIntegrator(bfi_imag); }
1839}
1840
1841void
1843 BilinearFormIntegrator *bfi_imag)
1844{
1845 if (bfi_real) { pblfr->AddBdrFaceIntegrator(bfi_real); }
1846 if (bfi_imag) { pblfi->AddBdrFaceIntegrator(bfi_imag); }
1847}
1848
1849void
1851 BilinearFormIntegrator *bfi_imag,
1852 Array<int> &bdr_marker)
1853{
1854 if (bfi_real) { pblfr->AddBdrFaceIntegrator(bfi_real, bdr_marker); }
1855 if (bfi_imag) { pblfi->AddBdrFaceIntegrator(bfi_imag, bdr_marker); }
1856}
1857
1858void
1860{
1861 pblfr->Assemble(skip_zeros);
1862 pblfi->Assemble(skip_zeros);
1863}
1864
1865void
1867{
1868 pblfr->Finalize(skip_zeros);
1869 pblfi->Finalize(skip_zeros);
1870}
1871
1874{
1875 return new ComplexHypreParMatrix(pblfr->ParallelAssemble(),
1876 pblfi->ParallelAssemble(),
1877 true, true, conv);
1878}
1879
1880void
1881ParSesquilinearForm::BuildComplexOperator(OperatorHandle &A_r,
1882 OperatorHandle &A_i,
1883 OperatorHandle &A) const
1884{
1885 // A = A_r + i A_i
1886 A.Clear();
1887 if ((!A_r.Ptr() || A_r.Type() == Operator::Hypre_ParCSR) &&
1888 (!A_i.Ptr() || A_i.Type() == Operator::Hypre_ParCSR))
1889 {
1890 ComplexHypreParMatrix * A_hyp =
1892 A_i.As<HypreParMatrix>(),
1893 A_r.OwnsOperator(),
1894 A_i.OwnsOperator(),
1895 conv);
1896 A.Reset<ComplexHypreParMatrix>(A_hyp, true);
1897 }
1898 else
1899 {
1900 ComplexOperator * A_op =
1901 new ComplexOperator(A_r.As<Operator>(),
1902 A_i.As<Operator>(),
1903 A_r.OwnsOperator(),
1904 A_i.OwnsOperator(),
1905 conv);
1906 A.Reset<ComplexOperator>(A_op, true);
1907 }
1908 A_r.SetOperatorOwner(false);
1909 A_i.SetOperatorOwner(false);
1910}
1911
1912namespace
1913{
1914struct ZeroDiagonalHypreKernel
1915{
1916 const int *ess_tdof_list;
1917 const HYPRE_Int *diag_i;
1919
1920 void MFEM_HOST_DEVICE operator()(int k) const
1921 {
1922 const int j = ess_tdof_list[k];
1923 diag_data[diag_i[j]] = 0.0;
1924 }
1925};
1926}
1927
1928void
1929ParSesquilinearForm::SetImaginaryEssentialDiagonalToZero(
1930 const Array<int> &ess_tdof_list, OperatorHandle &A)
1931{
1932 if (A.Type() == Operator::Hypre_ParCSR)
1933 {
1934 const int n = ess_tdof_list.Size();
1935 HypreParMatrix *Ah;
1936 A.Get(Ah);
1937 hypre_ParCSRMatrix *Aih = *Ah;
1938 Ah->HypreReadWrite();
1939 const int *d_ess_tdof_list =
1940 ess_tdof_list.GetMemory().Read(GetHypreForallMemoryClass(), n);
1941 HYPRE_Int *d_diag_i = Aih->diag->i;
1942 real_t *d_diag_data = Aih->diag->data;
1943 mfem::hypre_forall(n, ZeroDiagonalHypreKernel
1944 {
1945 d_ess_tdof_list, d_diag_i, d_diag_data
1946 });
1947 }
1948 else
1949 {
1950 A.As<ConstrainedOperator>()->SetDiagonalPolicy
1952 }
1953}
1954
1955void
1957 Vector &x, Vector &b,
1958 OperatorHandle &A,
1959 Vector &X, Vector &B,
1960 int ci)
1961{
1962 ParFiniteElementSpace *pfes = pblfr->ParFESpace();
1963 const int vsize = pfes->GetVSize();
1964
1965 // Allocate temporary vector
1966 Vector b_0;
1967 b_0.UseDevice(true);
1968 b_0.SetSize(vsize);
1969 b_0 = 0.0;
1970
1971 // Extract the real and imaginary parts of the input vectors
1972 MFEM_ASSERT(x.Size() == 2 * vsize, "Input GridFunction of incorrect size!");
1973 x.Read();
1974 Vector x_r; x_r.MakeRef(x, 0, vsize);
1975 Vector x_i; x_i.MakeRef(x, vsize, vsize);
1976
1977 MFEM_ASSERT(b.Size() == 2 * vsize, "Input LinearForm of incorrect size!");
1978 b.Read();
1979 Vector b_r; b_r.MakeRef(b, 0, vsize);
1980 Vector b_i; b_i.MakeRef(b, vsize, vsize);
1981
1982 if (conv == ComplexOperator::BLOCK_SYMMETRIC) { b_i *= -1.0; }
1983
1984 const int tvsize = pfes->GetTrueVSize();
1985 OperatorHandle A_r, A_i;
1986
1987 X.UseDevice(true);
1988 X.SetSize(2 * tvsize);
1989 X = 0.0;
1990
1991 B.UseDevice(true);
1992 B.SetSize(2 * tvsize);
1993 B = 0.0;
1994
1995 Vector X_r; X_r.MakeRef(X, 0, tvsize);
1996 Vector X_i; X_i.MakeRef(X, tvsize, tvsize);
1997 Vector B_r; B_r.MakeRef(B, 0, tvsize);
1998 Vector B_i; B_i.MakeRef(B, tvsize, tvsize);
1999
2000 Vector X_0, B_0;
2001
2002 if (RealInteg())
2003 {
2004 b_0 = b_r;
2005 pblfr->FormLinearSystem(ess_tdof_list, x_r, b_0, A_r, X_0, B_0, ci);
2006 X_r = X_0; B_r = B_0;
2007
2008 b_0 = b_i;
2009 pblfr->FormLinearSystem(ess_tdof_list, x_i, b_0, A_r, X_0, B_0, ci);
2010 X_i = X_0; B_i = B_0;
2011
2012 if (ImagInteg())
2013 {
2014 b_0 = 0.0;
2015 pblfi->FormLinearSystem(ess_tdof_list, x_i, b_0, A_i, X_0, B_0, false);
2016 B_r -= B_0;
2017
2018 b_0 = 0.0;
2019 pblfi->FormLinearSystem(ess_tdof_list, x_r, b_0, A_i, X_0, B_0, false);
2020 B_i += B_0;
2021 }
2022 }
2023 else if (ImagInteg())
2024 {
2025 b_0 = b_i;
2026 pblfi->FormLinearSystem(ess_tdof_list, x_r, b_0, A_i, X_0, B_0, ci);
2027 X_r = X_0; B_i = B_0;
2028
2029 b_0 = b_r; b_0 *= -1.0;
2030 pblfi->FormLinearSystem(ess_tdof_list, x_i, b_0, A_i, X_0, B_0, ci);
2031 X_i = X_0; B_r = B_0; B_r *= -1.0;
2032 }
2033 else
2034 {
2035 MFEM_ABORT("Real and Imaginary part of the Sesquilinear form are empty");
2036 }
2037
2038 if (RealInteg() && ImagInteg())
2039 {
2040 // Modify RHS to conform with standard essential BC treatment
2041 const int n = ess_tdof_list.Size();
2042 auto d_B_r = B_r.Write();
2043 auto d_B_i = B_i.Write();
2044 auto d_X_r = X_r.Read();
2045 auto d_X_i = X_i.Read();
2046 auto d_idx = ess_tdof_list.Read();
2047 mfem::forall(n, [=] MFEM_HOST_DEVICE (int i)
2048 {
2049 const int j = d_idx[i];
2050 d_B_r[j] = d_X_r[j];
2051 d_B_i[j] = d_X_i[j];
2052 });
2053 // Modify off-diagonal blocks (imaginary parts of the matrix) to conform
2054 // with standard essential BC treatment
2055 SetImaginaryEssentialDiagonalToZero(ess_tdof_list, A_i);
2056 }
2057
2059 {
2060 B_i *= -1.0;
2061 b_i *= -1.0;
2062 }
2063
2064 x_r.SyncAliasMemory(x);
2065 x_i.SyncAliasMemory(x);
2066 b_r.SyncAliasMemory(b);
2067 b_i.SyncAliasMemory(b);
2068
2069 X_r.SyncAliasMemory(X);
2070 X_i.SyncAliasMemory(X);
2071 B_r.SyncAliasMemory(B);
2072 B_i.SyncAliasMemory(B);
2073
2074 BuildComplexOperator(A_r, A_i, A);
2075}
2076
2077void
2079 OperatorHandle &A)
2080{
2081 OperatorHandle A_r, A_i;
2082 if (RealInteg())
2083 {
2084 pblfr->FormSystemMatrix(ess_tdof_list, A_r);
2085 }
2086 if (ImagInteg())
2087 {
2088 pblfi->FormSystemMatrix(ess_tdof_list, A_i);
2089 }
2090 if (!RealInteg() && !ImagInteg())
2091 {
2092 MFEM_ABORT("Both Real and Imaginary part of the Sesquilinear form are empty");
2093 }
2094
2095 if (RealInteg() && ImagInteg())
2096 {
2097 // Modify off-diagonal blocks (imaginary parts of the matrix) to conform
2098 // with standard essential BC treatment
2099 SetImaginaryEssentialDiagonalToZero(ess_tdof_list, A_i);
2100 }
2101
2102 BuildComplexOperator(A_r, A_i, A);
2103}
2104
2105void
2107 Vector &x)
2108{
2109 ParFiniteElementSpace *pfes = pblfr->ParFESpace();
2110
2111 const Operator &P = *pfes->GetProlongationMatrix();
2112
2113 const int vsize = pfes->GetVSize();
2114 const int tvsize = X.Size() / 2;
2115
2116 X.Read();
2117 Vector X_r; X_r.MakeRef(const_cast<Vector&>(X), 0, tvsize);
2118 Vector X_i; X_i.MakeRef(const_cast<Vector&>(X), tvsize, tvsize);
2119
2120 x.Write();
2121 Vector x_r; x_r.MakeRef(x, 0, vsize);
2122 Vector x_i; x_i.MakeRef(x, vsize, vsize);
2123
2124 // Apply conforming prolongation
2125 P.Mult(X_r, x_r);
2126 P.Mult(X_i, x_i);
2127
2128 x_r.SyncAliasMemory(x);
2129 x_i.SyncAliasMemory(x);
2130}
2131
2132void
2134{
2135 if ( pblfr ) { pblfr->Update(nfes); }
2136 if ( pblfi ) { pblfi->Update(nfes); }
2137}
2138
2139bool
2140ParMixedSesquilinearForm::RealInteg()
2141{
2142 int nint = pmblfr->GetDBFI()->Size() + pmblfr->GetBBFI()->Size() +
2143 pmblfr->GetFBFI()->Size() + pmblfr->GetBFBFI()->Size() +
2144 pmblfr->GetTFBFI()->Size() + pmblfr->GetBTFBFI()->Size();
2145 return (nint != 0);
2146}
2147
2148bool
2149ParMixedSesquilinearForm::ImagInteg()
2150{
2151 int nint = pmblfi->GetDBFI()->Size() + pmblfi->GetBBFI()->Size() +
2152 pmblfi->GetFBFI()->Size() + pmblfi->GetBFBFI()->Size() +
2153 pmblfi->GetTFBFI()->Size() + pmblfi->GetBTFBFI()->Size();
2154 return (nint != 0);
2155}
2156
2158 trial_fes,
2159 ParFiniteElementSpace * test_fes,
2160 ComplexOperator::Convention convention)
2161 : conv(convention),
2162 pmblfr(new ParMixedBilinearForm(trial_fes, test_fes)),
2163 pmblfi(new ParMixedBilinearForm(trial_fes, test_fes))
2164{
2165}
2166
2168 trial_fes,
2169 ParFiniteElementSpace * test_fes,
2170 ParMixedBilinearForm * pbfr,
2171 ParMixedBilinearForm * pbfi,
2172 ComplexOperator::Convention convention)
2173 : conv(convention),
2174 pmblfr(new ParMixedBilinearForm(trial_fes, test_fes, pbfr)),
2175 pmblfi(new ParMixedBilinearForm(trial_fes, test_fes, pbfi))
2176{
2177}
2178
2180{
2181 delete pmblfr;
2182 delete pmblfi;
2183}
2184
2185void
2187 BilinearFormIntegrator * bfi_imag)
2188{
2189 if (bfi_real)
2190 {
2191 pmblfr->AddDomainIntegrator(bfi_real);
2192 }
2193 if (bfi_imag)
2194 {
2195 pmblfi->AddDomainIntegrator(bfi_imag);
2196 }
2197}
2198
2199void
2201 BilinearFormIntegrator * bfi_imag,
2202 Array<int> & elem_marker)
2203{
2204 if (bfi_real)
2205 {
2206 pmblfr->AddDomainIntegrator(bfi_real, elem_marker);
2207 }
2208 if (bfi_imag)
2209 {
2210 pmblfi->AddDomainIntegrator(bfi_imag, elem_marker);
2211 }
2212}
2213
2214void
2216 bfi_real,
2217 BilinearFormIntegrator * bfi_imag)
2218{
2219 if (bfi_real)
2220 {
2221 pmblfr->AddBoundaryIntegrator(bfi_real);
2222 }
2223 if (bfi_imag)
2224 {
2225 pmblfi->AddBoundaryIntegrator(bfi_imag);
2226 }
2227}
2228
2229void
2231 bfi_real,
2232 BilinearFormIntegrator * bfi_imag,
2233 Array<int> & bdr_marker)
2234{
2235 if (bfi_real)
2236 {
2237 pmblfr->AddBoundaryIntegrator(bfi_real, bdr_marker);
2238 }
2239 if (bfi_imag)
2240 {
2241 pmblfi->AddBoundaryIntegrator(bfi_imag, bdr_marker);
2242 }
2243}
2244
2245void
2247 bfi_real,
2248 BilinearFormIntegrator * bfi_imag)
2249{
2250 if (bfi_real)
2251 {
2252 pmblfr->AddInteriorFaceIntegrator(bfi_real);
2253 }
2254 if (bfi_imag)
2255 {
2256 pmblfi->AddInteriorFaceIntegrator(bfi_imag);
2257 }
2258}
2259
2260void
2262 bfi_real,
2263 BilinearFormIntegrator * bfi_imag)
2264{
2265 if (bfi_real)
2266 {
2267 pmblfr->AddBdrFaceIntegrator(bfi_real);
2268 }
2269 if (bfi_imag)
2270 {
2271 pmblfi->AddBdrFaceIntegrator(bfi_imag);
2272 }
2273}
2274
2275void
2277 bfi_real,
2278 BilinearFormIntegrator * bfi_imag,
2279 Array<int> & bdr_marker)
2280{
2281 if (bfi_real)
2282 {
2283 pmblfr->AddBdrFaceIntegrator(bfi_real, bdr_marker);
2284 }
2285 if (bfi_imag)
2286 {
2287 pmblfi->AddBdrFaceIntegrator(bfi_imag, bdr_marker);
2288 }
2289}
2290
2292 bfi_real,
2293 BilinearFormIntegrator * bfi_imag)
2294{
2295 if (bfi_real)
2296 {
2297 pmblfr->AddTraceFaceIntegrator(bfi_real);
2298 }
2299 if (bfi_imag)
2300 {
2301 pmblfi->AddTraceFaceIntegrator(bfi_imag);
2302 }
2303}
2304
2306 BilinearFormIntegrator *bfi_real,
2307 BilinearFormIntegrator *bfi_imag)
2308{
2309 if (bfi_real)
2310 {
2311 pmblfr->AddBdrTraceFaceIntegrator(bfi_real);
2312 }
2313 if (bfi_imag)
2314 {
2315 pmblfi->AddBdrTraceFaceIntegrator(bfi_imag);
2316 }
2317}
2318
2320 BilinearFormIntegrator *bfi_real,
2321 BilinearFormIntegrator *bfi_imag,
2322 Array<int> &bdr_marker)
2323{
2324 if (bfi_real)
2325 {
2326 pmblfr->AddBdrTraceFaceIntegrator(bfi_real, bdr_marker);
2327 }
2328 if (bfi_imag)
2329 {
2330 pmblfi->AddBdrTraceFaceIntegrator(bfi_imag, bdr_marker);
2331 }
2332}
2333
2334void
2336{
2337 pmblfr->Assemble(skip_zeros);
2338 pmblfi->Assemble(skip_zeros);
2339}
2340
2341void
2343{
2344 pmblfr->Finalize(skip_zeros);
2345 pmblfi->Finalize(skip_zeros);
2346}
2347
2350{
2351 return new ComplexHypreParMatrix(
2352 pmblfr->ParallelAssemble(), pmblfi->ParallelAssemble(), true, true, conv);
2353}
2354
2355void
2357 ess_trial_tdof_list,
2358 const Array<int> & ess_test_tdof_list,
2359 Vector & x,
2360 Vector & b,
2361 OperatorHandle & A,
2362 Vector & X,
2363 Vector & B)
2364{
2365 FiniteElementSpace * pfes_trial = pmblfr->TrialFESpace();
2366 FiniteElementSpace * pfes_test = pmblfr->TestFESpace();
2367 const int vsize_trial = pfes_trial->GetVSize();
2368 const int vsize_test = pfes_test->GetVSize();
2369
2370 // Allocate temporary Vector
2371 Vector b_0;
2372 b_0.UseDevice(true);
2373 b_0.SetSize(vsize_test);
2374 b_0 = 0.0;
2375
2376 // Extract the real and imaginary parts of the input Vectors
2377 MFEM_ASSERT(x.Size() == 2 * vsize_trial,
2378 "Input GridFunction of incorrect size!");
2379 x.Read();
2380 Vector x_r;
2381 x_r.MakeRef(x, 0, vsize_trial);
2382 Vector x_i;
2383 x_i.MakeRef(x, vsize_trial, vsize_trial);
2384
2385 MFEM_ASSERT(b.Size() == 2 * vsize_test, "Input LinearForm of incorrect size!");
2386 b.Read();
2387 Vector b_r;
2388 b_r.MakeRef(b, 0, vsize_test);
2389 Vector b_i;
2390 b_i.MakeRef(b, vsize_test, vsize_test);
2391
2393 {
2394 b_i *= -1.0;
2395 }
2396
2397 const int tvsize_trial = pfes_trial->GetTrueVSize();
2398 const int tvsize_test = pfes_test->GetTrueVSize();
2399 OperatorHandle A_r, A_i;
2400
2401 X.UseDevice(true);
2402 X.SetSize(2 * tvsize_trial);
2403 X = 0.0;
2404
2405 B.UseDevice(true);
2406 B.SetSize(2 * tvsize_test);
2407 B = 0.0;
2408
2409 Vector X_r;
2410 X_r.MakeRef(X, 0, tvsize_trial);
2411 Vector X_i;
2412 X_i.MakeRef(X, tvsize_trial, tvsize_trial);
2413 Vector B_r;
2414 B_r.MakeRef(B, 0, tvsize_test);
2415 Vector B_i;
2416 B_i.MakeRef(B, tvsize_test, tvsize_test);
2417
2418 Vector X_0, B_0;
2419
2420 if (RealInteg())
2421 {
2422 b_0 = b_r;
2424 ess_trial_tdof_list, ess_test_tdof_list, x_r, b_0, A_r, X_0, B_0);
2425 X_r = X_0;
2426 B_r = B_0;
2427
2428 b_0 = b_i;
2430 ess_trial_tdof_list, ess_test_tdof_list, x_i, b_0, A_r, X_0, B_0);
2431 X_i = X_0;
2432 B_i = B_0;
2433
2434 if (ImagInteg())
2435 {
2436 b_0 = 0.0;
2438 ess_trial_tdof_list, ess_test_tdof_list, x_i, b_0, A_i, X_0, B_0);
2439 B_r -= B_0;
2440
2441 b_0 = 0.0;
2443 ess_trial_tdof_list, ess_test_tdof_list, x_r, b_0, A_i, X_0, B_0);
2444 B_i += B_0;
2445 }
2446 }
2447 else if (ImagInteg())
2448 {
2449 b_0 = b_i;
2451 ess_trial_tdof_list, ess_test_tdof_list, x_r, b_0, A_i, X_0, B_0);
2452 X_r = X_0;
2453 B_i = B_0;
2454
2455 b_0 = b_r;
2456 b_0 *= -1.0;
2458 ess_trial_tdof_list, ess_test_tdof_list, x_i, b_0, A_i, X_0, B_0);
2459 X_i = X_0;
2460 B_r = B_0;
2461 B_r *= -1.0;
2462 }
2463 else
2464 {
2465 MFEM_ABORT("Real and Imaginary part of the Mixed Sesquilinear form are empty");
2466 }
2467
2469 {
2470 B_i *= -1.0;
2471 b_i *= -1.0;
2472 }
2473
2474 x_r.SyncAliasMemory(x);
2475 x_i.SyncAliasMemory(x);
2476 b_r.SyncAliasMemory(b);
2477 b_i.SyncAliasMemory(b);
2478
2479 X_r.SyncAliasMemory(X);
2480 X_i.SyncAliasMemory(X);
2481 B_r.SyncAliasMemory(B);
2482 B_i.SyncAliasMemory(B);
2483
2484 // A = A_r + i A_i
2485 A.Clear();
2486 if ((!A_r.Ptr() || A_r.Type() == Operator::Hypre_ParCSR) &&
2487 (!A_i.Ptr() || A_i.Type() == Operator::Hypre_ParCSR))
2488 {
2489 ComplexHypreParMatrix * A_hyp =
2491 A_i.As<HypreParMatrix>(),
2492 A_r.OwnsOperator(),
2493 A_i.OwnsOperator(),
2494 conv);
2495 A.Reset<ComplexHypreParMatrix>(A_hyp, true);
2496 }
2497 else
2498 {
2499 ComplexOperator * A_op = new ComplexOperator(A_r.As<Operator>(),
2500 A_i.As<Operator>(),
2501 A_r.OwnsOperator(),
2502 A_i.OwnsOperator(),
2503 conv);
2504 A.Reset<ComplexOperator>(A_op, true);
2505 }
2506 A_r.SetOperatorOwner(false);
2507 A_i.SetOperatorOwner(false);
2508}
2509
2510void
2512 ess_trial_tdof_list,
2513 const Array<int> & ess_test_tdof_list,
2514 OperatorHandle & A)
2515{
2516 OperatorHandle A_r, A_i;
2517 if (RealInteg())
2518 {
2519 pmblfr->FormRectangularSystemMatrix(ess_trial_tdof_list, ess_test_tdof_list,
2520 A_r);
2521 }
2522 if (ImagInteg())
2523 {
2524 pmblfi->FormRectangularSystemMatrix(ess_trial_tdof_list, ess_test_tdof_list,
2525 A_i);
2526 }
2527 if (!RealInteg() && !ImagInteg())
2528 {
2529 MFEM_ABORT("Both Real and Imaginary part of the Mixed Sesquilinear form are empty");
2530 }
2531
2532 // A = A_r + i A_i
2533 A.Clear();
2534 if ((!A_r.Ptr() || A_r.Type() == Operator::Hypre_ParCSR) &&
2535 (!A_i.Ptr() || A_i.Type() == Operator::Hypre_ParCSR))
2536 {
2537 ComplexHypreParMatrix * A_hyp =
2539 A_i.As<HypreParMatrix>(),
2540 A_r.OwnsOperator(),
2541 A_i.OwnsOperator(),
2542 conv);
2543 A.Reset<ComplexHypreParMatrix>(A_hyp, true);
2544 }
2545 else
2546 {
2547 ComplexOperator * A_op = new ComplexOperator(A_r.As<Operator>(),
2548 A_i.As<Operator>(),
2549 A_r.OwnsOperator(),
2550 A_i.OwnsOperator(),
2551 conv);
2552 A.Reset<ComplexOperator>(A_op, true);
2553 }
2554 A_r.SetOperatorOwner(false);
2555 A_i.SetOperatorOwner(false);
2556}
2557
2558void
2560{
2561 pmblfr->Update();
2562 pmblfi->Update();
2563}
2564
2565
2566
2567#endif // MFEM_USE_MPI
2568
2569}
Abstract base class BilinearFormIntegrator.
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
void SetDiagonalPolicy(DiagonalPolicy policy)
Sets Operator::DiagonalPolicy used upon construction of the linear system. Policies include:
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
Array< BilinearFormIntegrator * > * GetFBFI()
Access all integrators added with AddInteriorFaceIntegrator().
virtual void Update(FiniteElementSpace *nfes=NULL)
Update the FiniteElementSpace and delete all data associated with the old one.
Array< BilinearFormIntegrator * > * GetDBFI()
Access all the integrators added with AddDomainIntegrator().
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY....
FiniteElementSpace * FESpace()
Return the FE space associated with the BilinearForm.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi)
Adds new Boundary Integrator. Assumes ownership of bfi.
void Assemble(int skip_zeros=1)
Assembles the form i.e. sums over all domain/bdr integrators.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi)
Adds new boundary Face Integrator. Assumes ownership of bfi.
Array< BilinearFormIntegrator * > * GetBBFI()
Access all the integrators added with AddBoundaryIntegrator().
Array< BilinearFormIntegrator * > * GetBFBFI()
Access all integrators added with AddBdrFaceIntegrator().
virtual void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B, int copy_interior=0)
Form the linear system A X = B, corresponding to this bilinear form and the linear form b(....
virtual void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A)
Form the linear system matrix A, see FormLinearSystem() for details.
const SparseMatrix & SpMat() const
Returns a const reference to the sparse matrix: .
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi)
Adds new interior Face Integrator. Assumes ownership of bfi.
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
virtual void ProjectBdrCoefficient(Coefficient &real_coeff, Coefficient &imag_coeff, Array< int > &attr)
virtual void ProjectCoefficient(Coefficient &real_coeff, Coefficient &imag_coeff)
FiniteElementSpace * fes
FiniteElementCollection * fec_owned
Used when the grid function is read from a file. It can also be set explicitly, see MakeOwner().
virtual real_t ComputeLpError(const real_t p, Coefficient &exsolr, Coefficient &exsoli, Coefficient *weight=NULL, const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Returns ||u_ex - u_h||_Lp for complex-valued H1 or L2 elements.
virtual void ProjectBdrCoefficientNormal(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
ComplexGridFunction(FiniteElementSpace *f)
Construct a ComplexGridFunction associated with the FiniteElementSpace *f.
virtual void Save(std::ostream &out) const
Save the ComplexGridFunction to an output stream.
Specialization of the ComplexOperator built from a pair of HypreParMatrices.
ComplexLinearForm(FiniteElementSpace *fes, ComplexOperator::Convention convention=ComplexOperator::HERMITIAN)
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real, LinearFormIntegrator *lfi_imag)
Adds new Boundary Face Integrator. Assumes ownership of lfi.
void AddDomainIntegrator(LinearFormIntegrator *lfi_real, LinearFormIntegrator *lfi_imag)
Adds new Domain Integrator.
std::complex< real_t > operator()(const ComplexGridFunction &gf) const
void Assemble()
Assembles the linear form i.e. sums over all domain/bdr integrators.
void AddBoundaryIntegrator(LinearFormIntegrator *lfi_real, LinearFormIntegrator *lfi_imag)
Adds new Boundary Integrator.
Mimic the action of a complex operator using two real operators.
@ HERMITIAN
Native convention for Hermitian operators.
@ BLOCK_SYMMETRIC
Alternate convention for damping operators.
Specialization of the ComplexOperator built from a pair of Sparse Matrices.
Square Operator for imposing essential boundary conditions using only the action, Mult(),...
real_t Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint....
Definition eltrans.hpp:144
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
void Save(std::ostream &out) const
Save finite element space to output stream out.
Definition fespace.cpp:4409
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition fespace.hpp:827
ElementTransformation * GetElementTransformation(int i) const
Definition fespace.hpp:903
bool Nonconforming() const
Definition fespace.hpp:650
FiniteElementCollection * Load(Mesh *m, std::istream &input)
Read a FiniteElementSpace from a stream. The returned FiniteElementCollection is owned by the caller.
Definition fespace.cpp:4734
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition fespace.cpp:3860
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:852
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:867
const SparseMatrix * GetConformingProlongation() const
Definition fespace.cpp:1422
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:824
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:817
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Definition fespace.cpp:3896
const Operator * GetUpdateOperator()
Get the GridFunction update operator.
Definition fespace.hpp:1552
Abstract class for all finite elements.
Definition fe_base.hpp:294
int GetRangeDim() const
Returns the vector dimension for vector-valued finite elements, which is also the dimension of the in...
Definition fe_base.hpp:387
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:414
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
Definition fe_base.hpp:427
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition fe_base.hpp:407
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
Definition gridfunc.cpp:497
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition gridfunc.cpp:169
virtual void MakeRef(FiniteElementSpace *f, real_t *v)
Make the GridFunction reference external data on a new FiniteElementSpace.
Definition gridfunc.cpp:235
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, const Array< int > &bdr_attr)
Project the tangential components of the given VectorCoefficient on the boundary.
void ProjectBdrCoefficientNormal(Coefficient *coeff, VectorCoefficient *vcoeff, const Array< int > &attr)
virtual void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
void ProjectBdrCoefficient(Coefficient &coeff, const Array< int > &attr)
Project a Coefficient on the GridFunction, modifying only DOFs on the boundary associated with the bo...
Definition gridfunc.hpp:672
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
Wrapper for hypre's parallel vector class.
Definition hypre.hpp:230
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:258
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Abstract base class LinearFormIntegrator.
Definition lininteg.hpp:28
Vector with associated FE space and LinearFormIntegrators.
void AddDomainIntegrator(LinearFormIntegrator *lfi)
Adds new Domain Integrator. Assumes ownership of lfi.
FiniteElementSpace * FESpace()
Read+write access to the associated FiniteElementSpace.
virtual void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset)
Make the LinearForm reference external data on a new FiniteElementSpace.
void AddBoundaryIntegrator(LinearFormIntegrator *lfi)
Adds new Boundary Integrator. Assumes ownership of lfi.
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi)
Adds new Boundary Face Integrator. Assumes ownership of lfi.
void Assemble()
Assembles the linear form i.e. sums over all domain/bdr integrators.
Mesh data type.
Definition mesh.hpp:67
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1317
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition mesh.hpp:318
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi)
Adds a boundary face integrator. Assumes ownership of bfi.
Array< BilinearFormIntegrator * > * GetBFBFI()
Access all integrators added with AddBdrFaceIntegrator().
void Assemble(int skip_zeros=1)
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi)
Adds a boundary integrator. Assumes ownership of bfi.
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi)
Adds an interior face integrator. Assumes ownership of bfi.
virtual void FormRectangularSystemMatrix(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, OperatorHandle &A)
Return in A that is column-constrained.
Array< BilinearFormIntegrator * > * GetTFBFI()
Access all integrators added with AddTraceFaceIntegrator().
Array< BilinearFormIntegrator * > * GetBBFI()
Access all integrators added with AddBoundaryIntegrator().
void AddBdrTraceFaceIntegrator(BilinearFormIntegrator *bfi)
Adds a boundary trace face integrator. Assumes ownership of bfi.
FiniteElementSpace * TestFESpace()
Return the test FE space associated with the BilinearForm.
void Update()
Must be called after making changes to trial_fes or test_fes.
virtual void FormRectangularLinearSystem(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B)
Form the linear system A X = B, corresponding to this mixed bilinear form and the linear form b(....
const SparseMatrix & SpMat() const
Returns a const reference to the sparse matrix: .
FiniteElementSpace * TrialFESpace()
Return the trial FE space associated with the BilinearForm.
Array< BilinearFormIntegrator * > * GetDBFI()
Access all integrators added with AddDomainIntegrator().
void AddTraceFaceIntegrator(BilinearFormIntegrator *bfi)
Add a trace face integrator. Assumes ownership of bfi.
Array< BilinearFormIntegrator * > * GetBTFBFI()
Access all integrators added with AddBdrTraceFaceIntegrator().
Array< BilinearFormIntegrator * > * GetFBFI()
Access all integrators added with AddInteriorFaceIntegrator().
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds a domain integrator. Assumes ownership of bfi.
void AddDomainIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Domain Integrator.
void AddBdrTraceFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds a boundary trace face integrator. Assumes ownership of bfi.
void FormRectangularLinearSystem(const Array< int > &ess_trial_tdof_list, const Array< int > &ess_test_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B)
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new interior Face Integrator. Assumes ownership of bfi.
MixedSesquilinearForm(FiniteElementSpace *trial_fes, FiniteElementSpace *test_fes, ComplexOperator::Convention convention=ComplexOperator::HERMITIAN)
void FormRectangularSystemMatrix(const Array< int > &ess_trial_tdof_list, const Array< int > &ess_test_tdof_list, OperatorHandle &A)
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Boundary Integrator.
virtual void Update()
Updates the internal mixed forms with the new finite element space.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new boundary Face Integrator. Assumes ownership of bfi.
ComplexSparseMatrix * AssembleComplexSparseMatrix()
Return a ComplexSparseMatrix wrapping the local (L-dof) real and imaginary matrices of the form.
void Finalize(int skip_zeros=1)
Finalizes the matrix initialization.
void AddTraceFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Add a trace face integrator. Assumes ownership of bfi.
bool IsLegacyLoaded() const
I/O: Return true if the mesh was loaded from the legacy v1.1 format.
Definition ncmesh.hpp:534
Pointer to an Operator of a specified type.
Definition handle.hpp:34
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
Definition handle.hpp:104
bool OwnsOperator() const
Return true if the OperatorHandle owns the held Operator.
Definition handle.hpp:117
void SetOperatorOwner(bool own=true)
Set the ownership flag for the held Operator.
Definition handle.hpp:120
Operator * Ptr() const
Access the underlying Operator pointer.
Definition handle.hpp:87
void Clear()
Clear the OperatorHandle, deleting the held Operator (if owned), while leaving the type id unchanged.
Definition handle.hpp:124
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
Definition handle.hpp:145
OpType * Is() const
Return the Operator pointer dynamically cast to a specified OpType.
Definition handle.hpp:108
Operator::Type Type() const
Get the currently set operator type id.
Definition handle.hpp:99
Abstract operator.
Definition operator.hpp:27
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
DiagonalPolicy
Defines operator diagonal policy upon elimination of rows and/or columns.
Definition operator.hpp:50
@ DIAG_ZERO
Set the diagonal value to zero.
Definition operator.hpp:51
@ MFEM_SPARSEMAT
ID for class SparseMatrix.
Definition operator.hpp:321
@ Hypre_ParCSR
ID for class HypreParMatrix.
Definition operator.hpp:322
Class for parallel bilinear form.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A) override
Form the linear system matrix A, see FormLinearSystem() for details.
void Update(FiniteElementSpace *nfes=NULL) override
Update the FiniteElementSpace and delete all data associated with the old one.
ParFiniteElementSpace * ParFESpace() const
Return the parallel FE space associated with the ParBilinearForm.
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B, int copy_interior=0) override
Form the linear system A X = B, corresponding to this bilinear form and the linear form b(....
virtual void ProjectBdrCoefficient(Coefficient &real_coeff, Coefficient &imag_coeff, Array< int > &attr)
FiniteElementCollection * fec_owned
Used when the grid function is read from a file. It can also be set explicitly, see MakeOwner().
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
ParComplexGridFunction(ParFiniteElementSpace *pf)
Construct a ParComplexGridFunction associated with the ParFiniteElementSpace *pf.
virtual void ProjectBdrCoefficientNormal(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
ParFiniteElementSpace * pfes
void Distribute(const Vector *tv)
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
virtual void ProjectCoefficient(Coefficient &real_coeff, Coefficient &imag_coeff)
void Save(std::ostream &out) const
Save the local portion of the ParComplexGridFunction.
void Update(ParFiniteElementSpace *pf=NULL)
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real, LinearFormIntegrator *lfi_imag)
Adds new Boundary Face Integrator. Assumes ownership of lfi.
std::complex< real_t > operator()(const ParComplexGridFunction &gf) const
void AddBoundaryIntegrator(LinearFormIntegrator *lfi_real, LinearFormIntegrator *lfi_imag)
Adds new Boundary Integrator.
void Assemble()
Assembles the linear form i.e. sums over all domain/bdr integrators.
HypreParVector * ParallelAssemble()
Returns the vector assembled on the true dofs, i.e. P^t v.
void AddDomainIntegrator(LinearFormIntegrator *lfi_real, LinearFormIntegrator *lfi_imag)
Adds new Domain Integrator.
ParComplexLinearForm(ParFiniteElementSpace *pf, ComplexOperator::Convention convention=ComplexOperator::HERMITIAN)
Abstract parallel finite element space.
Definition pfespace.hpp:31
MPI_Comm GetComm() const
Definition pfespace.hpp:337
HYPRE_BigInt * GetTrueDofOffsets() const
Definition pfespace.hpp:358
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:361
int GetTrueVSize() const override
Return the number of local vector true dofs.
Definition pfespace.hpp:365
const Operator * GetProlongationMatrix() const override
void ApplyDofSigns(real_t *h_data) const
Apply the DOF signs to the given host data h_data which must be of size GetVSize() if HaveDofSigns() ...
Definition pfespace.cpp:575
Class for parallel grid function.
Definition pgridfunc.hpp:50
void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, const Array< int > &attr)
void MakeRef(FiniteElementSpace *f, real_t *v) override
Make the ParGridFunction reference external data on a new FiniteElementSpace.
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
void Update() override
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition pgridfunc.cpp:97
void Distribute(const Vector *tv)
void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, const Array< int > &bdr_attr) override
Project the tangential components of the given VectorCoefficient on the boundary.
Class for parallel linear form.
void ParallelAssemble(Vector &tv)
Assemble the vector on the true dofs, i.e. P^t v.
void Assemble()
Assembles the ParLinearForm i.e. sums over all domain/bdr integrators.
void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset) override
Make the ParLinearForm reference external data on a new FiniteElementSpace.
ParFiniteElementSpace * ParFESpace() const
Class for parallel meshes.
Definition pmesh.hpp:35
Class for parallel bilinear form using different test and trial FE spaces.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void FormRectangularSystemMatrix(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, OperatorHandle &A) override
Return in A a parallel (on truedofs) version of this operator.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P_test^t A P_trial.
void FormRectangularLinearSystem(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B) override
Form the parallel linear system A X = B, corresponding to this mixed bilinear form and the linear for...
ComplexHypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new boundary Face Integrator. Assumes ownership of bfi.
ParMixedSesquilinearForm(ParFiniteElementSpace *trial_fes, ParFiniteElementSpace *test_fes, ComplexOperator::Convention convention=ComplexOperator::HERMITIAN)
void FormRectangularLinearSystem(const Array< int > &ess_trial_tdof_list, const Array< int > &ess_test_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B)
void AddTraceFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Add a trace face integrator. Assumes ownership of bfi.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new interior Face Integrator. Assumes ownership of bfi.
void FormRectangularSystemMatrix(const Array< int > &ess_trial_tdof_list, const Array< int > &ess_test_tdof_list, OperatorHandle &A)
void AddBdrTraceFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds a boundary trace face integrator. Assumes ownership of bfi.
virtual void Update()
Updates the internal mixed forms with the new finite element space.
void Finalize(int skip_zeros=1)
Finalizes the matrix initialization.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Boundary Integrator.
void AddDomainIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Domain Integrator.
virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
ComplexHypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
ParSesquilinearForm(ParFiniteElementSpace *pf, ComplexOperator::Convention convention=ComplexOperator::HERMITIAN)
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A)
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B, int copy_interior=0)
virtual void Update(FiniteElementSpace *nfes=NULL)
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Boundary Integrator.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new boundary Face Integrator. Assumes ownership of bfi.
void Finalize(int skip_zeros=1)
Finalizes the matrix initialization.
void AddDomainIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Domain Integrator.
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new interior Face Integrator. Assumes ownership of bfi.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
ComplexSparseMatrix * AssembleComplexSparseMatrix()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void SetDiagonalPolicy(mfem::Matrix::DiagonalPolicy dpolicy)
Sets diagonal policy used upon construction of the linear system.
void Finalize(int skip_zeros=1)
Finalizes the matrix initialization.
virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
void Assemble(int skip_zeros=1)
Assemble the local matrix.
SesquilinearForm(FiniteElementSpace *fes, ComplexOperator::Convention convention=ComplexOperator::HERMITIAN)
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A)
void AddDomainIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Domain Integrator.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new Boundary Integrator.
virtual void Update(FiniteElementSpace *nfes=NULL)
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, OperatorHandle &A, Vector &X, Vector &B, int copy_interior=0)
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new interior Face Integrator. Assumes ownership of bfi.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, BilinearFormIntegrator *bfi_imag)
Adds new boundary Face Integrator. Assumes ownership of bfi.
Data type sparse matrix.
Definition sparsemat.hpp:51
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
Base class for vector Coefficients that optionally depend on time and space.
Vector data type.
Definition vector.hpp:82
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
Definition vector.hpp:524
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:520
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition vector.cpp:870
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
Definition vector.hpp:275
void SyncMemory(const Vector &v) const
Update the memory location of the vector to match v.
Definition vector.hpp:272
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
Definition vector.cpp:127
virtual bool UseDevice() const
Return the device flag of the Memory object used by the Vector.
Definition vector.hpp:148
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition vector.hpp:145
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
Vector & operator=(const real_t *v)
Copy Size() entries from v.
Definition vector.cpp:197
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
Definition vector.hpp:540
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:528
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition vector.hpp:709
real_t * diag_data
const HYPRE_Int * diag_i
const int * ess_tdof_list
HYPRE_Int HYPRE_BigInt
real_t b
Definition lissajous.cpp:42
real_t weight(const Vector &x)
mfem::real_t real_t
std::ostream & operator<<(std::ostream &os, SparseMatrix const &mat)
MemoryClass GetHypreForallMemoryClass()
Definition forall.hpp:1325
void filter_dos(std::string &line)
Check for, and remove, a trailing '\r' from and std::string.
Definition text.hpp:45
void hypre_forall(int N, lambda &&body)
Definition forall.hpp:1302
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void forall(int N, lambda &&body)
Definition forall.hpp:1134
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
Definition text.hpp:31
constexpr real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:549
STL namespace.
real_t p(const Vector &x, real_t t)
real_t sol(const Vector &x)