MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
operator.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 "vector.hpp"
13#include "operator.hpp"
14#include "../general/forall.hpp"
15
16#include <iostream>
17#include <iomanip>
18
19namespace mfem
20{
21
22void Operator::InitTVectors(const Operator *Po, const Operator *Ri,
23 const Operator *Pi,
24 Vector &x, Vector &b,
25 Vector &X, Vector &B) const
26{
28 {
29 // Variational restriction with Po
30 B.SetSize(Po->Width(), b);
31 Po->MultTranspose(b, B);
32 }
33 else
34 {
35 // B points to same data as b
36 B.MakeRef(b, 0, b.Size());
37 }
39 {
40 // Variational restriction with Ri
41 X.SetSize(Ri->Height(), x);
42 Ri->Mult(x, X);
43 }
44 else
45 {
46 // X points to same data as x
47 X.MakeRef(x, 0, x.Size());
48 }
49}
50
51void Operator::AddMult(const Vector &x, Vector &y, const real_t a) const
52{
53 mfem::Vector z(y.Size());
54 Mult(x, z);
55 y.Add(a, z);
56}
57
59 const real_t a) const
60{
61 mfem::Vector z(y.Size());
62 MultTranspose(x, z);
63 y.Add(a, z);
64}
65
67 Array<Vector *> &Y) const
68{
69 MFEM_ASSERT(X.Size() == Y.Size(),
70 "Number of columns mismatch in Operator::Mult!");
71 for (int i = 0; i < X.Size(); i++)
72 {
73 MFEM_ASSERT(X[i] && Y[i], "Missing Vector in Operator::Mult!");
74 Mult(*X[i], *Y[i]);
75 }
76}
77
79 Array<Vector *> &Y) const
80{
81 MFEM_ASSERT(X.Size() == Y.Size(),
82 "Number of columns mismatch in Operator::MultTranspose!");
83 for (int i = 0; i < X.Size(); i++)
84 {
85 MFEM_ASSERT(X[i] && Y[i], "Missing Vector in Operator::MultTranspose!");
86 MultTranspose(*X[i], *Y[i]);
87 }
88}
89
91 const real_t a) const
92{
93 MFEM_ASSERT(X.Size() == Y.Size(),
94 "Number of columns mismatch in Operator::AddMult!");
95 for (int i = 0; i < X.Size(); i++)
96 {
97 MFEM_ASSERT(X[i] && Y[i], "Missing Vector in Operator::AddMult!");
98 AddMult(*X[i], *Y[i], a);
99 }
100}
101
103 Array<Vector *> &Y, const real_t a) const
104{
105 MFEM_ASSERT(X.Size() == Y.Size(),
106 "Number of columns mismatch in Operator::AddMultTranspose!");
107 for (int i = 0; i < X.Size(); i++)
108 {
109 MFEM_ASSERT(X[i] && Y[i], "Missing Vector in Operator::AddMultTranspose!");
110 AddMultTranspose(*X[i], *Y[i], a);
112}
113
115{
116 MFEM_ABORT("this method is not overridden for this class!");
117}
118
120{
121 MFEM_ABORT("this method is not overridden for this class!");
122}
123
125{
126 MFEM_ABORT("this method is not overridden for this class!");
127}
128
130 Vector &x, Vector &b,
131 Operator* &Aout, Vector &X, Vector &B,
132 int copy_interior)
133{
134 const Operator *P = this->GetProlongation();
135 const Operator *R = this->GetRestriction();
136 InitTVectors(P, R, P, x, b, X, B);
137
138 if (!copy_interior) { X.SetSubVectorComplement(ess_tdof_list, 0.0); }
139
140 ConstrainedOperator *constrainedA;
142 constrainedA->EliminateRHS(X, B);
143 Aout = constrainedA;
144}
145
147 const Array<int> &trial_tdof_list,
148 const Array<int> &test_tdof_list, Vector &x, Vector &b,
149 Operator* &Aout, Vector &X, Vector &B)
150{
151 const Operator *Pi = this->GetProlongation();
152 const Operator *Po = this->GetOutputProlongation();
153 const Operator *Ri = this->GetRestriction();
154 InitTVectors(Po, Ri, Pi, x, b, X, B);
155
156 RectangularConstrainedOperator *constrainedA;
157 FormRectangularConstrainedSystemOperator(trial_tdof_list, test_tdof_list,
158 constrainedA);
159 constrainedA->EliminateRHS(X, B);
160 Aout = constrainedA;
161}
162
164{
165 // Same for Rectangular and Square operators
166 const Operator *P = this->GetProlongation();
168 {
169 // Apply conforming prolongation
170 x.SetSize(P->Height());
171 P->Mult(X, x);
172 }
173 else
174 {
175 // X and x point to the same data
176
177 // If the validity flags of X's Memory were changed (e.g. if it was moved
178 // to device memory) then we need to tell x about that.
179 x.SyncMemory(X);
180 }
181}
182
184{
185 Operator *rap;
186 if (!IsIdentityProlongation(Pi))
187 {
188 if (!IsIdentityProlongation(Po))
189 {
190 rap = new RAPOperator(*Po, *this, *Pi);
191 }
192 else
193 {
194 rap = new ProductOperator(this, Pi, false,false);
195 }
196 }
197 else
198 {
199 if (!IsIdentityProlongation(Po))
200 {
201 TransposeOperator * PoT = new TransposeOperator(Po);
202 rap = new ProductOperator(PoT, this, true,false);
203 }
204 else
205 {
206 rap = this;
207 }
208 }
209 return rap;
210}
211
214{
215 const Operator *P = this->GetProlongation();
216 Operator *rap = SetupRAP(P, P);
217
218 // Impose the boundary conditions through a ConstrainedOperator, which owns
219 // the rap operator when P and R are non-trivial
221 rap != this);
222 Aout = A;
223}
224
226 const Array<int> &trial_tdof_list, const Array<int> &test_tdof_list,
228{
229 const Operator *Pi = this->GetProlongation();
230 const Operator *Po = this->GetOutputProlongation();
231 Operator *rap = SetupRAP(Pi, Po);
232
233 // Impose the boundary conditions through a RectangularConstrainedOperator,
234 // which owns the rap operator when P and R are non-trivial
237 trial_tdof_list, test_tdof_list,
238 rap != this);
239 Aout = A;
240}
241
249
251 const Array<int> &test_tdof_list,
252 Operator* &Aout)
253{
255 FormRectangularConstrainedSystemOperator(trial_tdof_list, test_tdof_list, A);
256 Aout = A;
257}
258
260{
261 const Operator *Pin = this->GetProlongation();
262 const Operator *Rout = this->GetOutputRestriction();
263 Aout = new TripleProductOperator(Rout, this, Pin,false, false, false);
264}
265
266void Operator::PrintMatlab(std::ostream & os, int n, int m) const
267{
268 using namespace std;
269 if (n == 0) { n = width; }
270 if (m == 0) { m = height; }
271
272 Vector x(n), y(m);
273 x = 0.0;
274
275 os << setiosflags(ios::scientific | ios::showpos);
276 for (int i = 0; i < n; i++)
277 {
278 x(i) = 1.0;
279 Mult(x, y);
280 for (int j = 0; j < m; j++)
281 {
282 if (y(j) != 0)
283 {
284 os << j+1 << " " << i+1 << " " << y(j) << '\n';
285 }
286 }
287 x(i) = 0.0;
288 }
289}
290
291void Operator::PrintMatlab(std::ostream &os) const
292{
294}
295
296
298{
299 mfem_error("TimeDependentOperator::ExplicitMult() is not overridden!");
300}
301
303 Vector &) const
304{
305 mfem_error("TimeDependentOperator::ImplicitMult() is not overridden!");
306}
307
309{
310 mfem_error("TimeDependentOperator::Mult() is not overridden!");
311}
312
314 Vector &)
315{
316 mfem_error("TimeDependentOperator::ImplicitSolve() is not overridden!");
317}
318
320 const Vector &, const Vector &, real_t) const
321{
322 mfem_error("TimeDependentOperator::GetImplicitGradient() is "
323 "not overridden!");
324 return const_cast<Operator &>(dynamic_cast<const Operator &>(*this));
325}
326
328{
329 mfem_error("TimeDependentOperator::GetExplicitGradient() is "
330 "not overridden!");
331 return const_cast<Operator &>(dynamic_cast<const Operator &>(*this));
332}
333
335 const Vector &,
336 int, int *, real_t)
337{
338 mfem_error("TimeDependentOperator::SUNImplicitSetup() is not overridden!");
339 return (-1);
340}
341
343{
344 mfem_error("TimeDependentOperator::SUNImplicitSolve() is not overridden!");
345 return (-1);
346}
347
349{
350 mfem_error("TimeDependentOperator::SUNMassSetup() is not overridden!");
351 return (-1);
352}
353
355{
356 mfem_error("TimeDependentOperator::SUNMassSolve() is not overridden!");
357 return (-1);
358}
359
361{
362 mfem_error("TimeDependentOperator::SUNMassMult() is not overridden!");
363 return (-1);
364}
365
366
368 const Vector &dxdt,
369 Vector &y) const
370{
371 mfem_error("SecondOrderTimeDependentOperator::Mult() is not overridden!");
372}
373
375 const real_t dt1,
376 const Vector &x,
377 const Vector &dxdt,
378 Vector &k)
379{
380 mfem_error("SecondOrderTimeDependentOperator::ImplicitSolve() is not overridden!");
381}
382
384 const Operator *B, const real_t beta,
385 bool ownA, bool ownB)
386 : Operator(A->Height(), A->Width()),
387 A(A), B(B), alpha(alpha), beta(beta), ownA(ownA), ownB(ownB),
388 z(A->Height())
389{
390 MFEM_VERIFY(A->Width() == B->Width(),
391 "incompatible Operators: different widths\n"
392 << "A->Width() = " << A->Width()
393 << ", B->Width() = " << B->Width() );
394 MFEM_VERIFY(A->Height() == B->Height(),
395 "incompatible Operators: different heights\n"
396 << "A->Height() = " << A->Height()
397 << ", B->Height() = " << B->Height() );
398
399 {
400 const Solver* SolverA = dynamic_cast<const Solver*>(A);
401 const Solver* SolverB = dynamic_cast<const Solver*>(B);
402 if (SolverA)
403 {
404 MFEM_VERIFY(!(SolverA->iterative_mode),
405 "Operator A of a SumOperator should not be in iterative mode");
406 }
407 if (SolverB)
408 {
409 MFEM_VERIFY(!(SolverB->iterative_mode),
410 "Operator B of a SumOperator should not be in iterative mode");
411 }
412 }
413
414}
415
417{
418 if (ownA) { delete A; }
419 if (ownB) { delete B; }
420}
421
423 bool ownA, bool ownB)
424 : Operator(A->Height(), B->Width()),
425 A(A), B(B), ownA(ownA), ownB(ownB), z(A->Width())
426{
427 MFEM_VERIFY(A->Width() == B->Height(),
428 "incompatible Operators: A->Width() = " << A->Width()
429 << ", B->Height() = " << B->Height());
430
431 {
432 const Solver* SolverB = dynamic_cast<const Solver*>(B);
433 if (SolverB)
434 {
435 MFEM_VERIFY(!(SolverB->iterative_mode),
436 "Operator B of a ProductOperator should not be in iterative mode");
437 }
438 }
439}
440
442{
443 if (ownA) { delete A; }
444 if (ownB) { delete B; }
445}
446
447
449 const Operator &P_)
450 : Operator(Rt_.Width(), P_.Width()), Rt(Rt_), A(A_), P(P_)
451{
452 MFEM_VERIFY(Rt.Height() == A.Height(),
453 "incompatible Operators: Rt.Height() = " << Rt.Height()
454 << ", A.Height() = " << A.Height());
455 MFEM_VERIFY(A.Width() == P.Height(),
456 "incompatible Operators: A.Width() = " << A.Width()
457 << ", P.Height() = " << P.Height());
458
459 {
460 const Solver* SolverA = dynamic_cast<const Solver*>(&A);
461 if (SolverA)
462 {
463 MFEM_VERIFY(!(SolverA->iterative_mode),
464 "Operator A of an RAPOperator should not be in iterative mode");
465 }
466
467 const Solver* SolverP = dynamic_cast<const Solver*>(&P);
468 if (SolverP)
469 {
470 MFEM_VERIFY(!(SolverP->iterative_mode),
471 "Operator P of an RAPOperator should not be in iterative mode");
472 }
473 }
474
475 mem_class = Rt.GetMemoryClass()*P.GetMemoryClass();
476 MemoryType mem_type = GetMemoryType(A.GetMemoryClass()*mem_class);
477 Px.SetSize(P.Height(), mem_type);
478 APx.SetSize(A.Height(), mem_type);
479}
480
481
483 const Operator *A, const Operator *B, const Operator *C,
484 bool ownA, bool ownB, bool ownC)
485 : Operator(A->Height(), C->Width())
486 , A(A), B(B), C(C)
487 , ownA(ownA), ownB(ownB), ownC(ownC)
488{
489 MFEM_VERIFY(A->Width() == B->Height(),
490 "incompatible Operators: A->Width() = " << A->Width()
491 << ", B->Height() = " << B->Height());
492 MFEM_VERIFY(B->Width() == C->Height(),
493 "incompatible Operators: B->Width() = " << B->Width()
494 << ", C->Height() = " << C->Height());
495
496 {
497 const Solver* SolverB = dynamic_cast<const Solver*>(B);
498 if (SolverB)
499 {
500 MFEM_VERIFY(!(SolverB->iterative_mode),
501 "Operator B of a TripleProductOperator should not be in iterative mode");
502 }
503
504 const Solver* SolverC = dynamic_cast<const Solver*>(C);
505 if (SolverC)
506 {
507 MFEM_VERIFY(!(SolverC->iterative_mode),
508 "Operator C of a TripleProductOperator should not be in iterative mode");
509 }
510 }
511
512 mem_class = A->GetMemoryClass()*C->GetMemoryClass();
513 MemoryType mem_type = GetMemoryType(mem_class*B->GetMemoryClass());
514 t1.SetSize(C->Height(), mem_type);
515 t2.SetSize(B->Height(), mem_type);
516}
517
519{
520 if (ownA) { delete A; }
521 if (ownB) { delete B; }
522 if (ownC) { delete C; }
523}
524
525
527 bool own_A_,
528 DiagonalPolicy diag_policy_)
529 : Operator(A->Height(), A->Width()), A(A), own_A(own_A_),
530 diag_policy(diag_policy_)
531{
532 // 'mem_class' should work with A->Mult() and mfem::forall():
535 list.Read(); // TODO: just ensure 'list' is registered, no need to copy it
537 // typically z and w are large vectors, so use the device (GPU) to perform
538 // operations on them
539 z.SetSize(height, mem_type); z.UseDevice(true);
540 w.SetSize(height, mem_type); w.UseDevice(true);
541}
542
544{
545 A->AssembleDiagonal(diag);
546
547 if (diag_policy == DIAG_KEEP) { return; }
548
549 const int csz = constraint_list.Size();
550 auto d_diag = diag.ReadWrite();
551 auto idx = constraint_list.Read();
552 switch (diag_policy)
553 {
554 case DIAG_ONE:
555 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
556 {
557 const int id = idx[i];
558 d_diag[id] = 1.0;
559 });
560 break;
561 case DIAG_ZERO:
562 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
563 {
564 const int id = idx[i];
565 d_diag[id] = 0.0;
566 });
567 break;
568 default:
569 MFEM_ABORT("unknown diagonal policy");
570 break;
571 }
572}
573
575{
576 w = 0.0;
577 const int csz = constraint_list.Size();
578 auto idx = constraint_list.Read();
579 auto d_x = x.Read();
580 // Use read+write access - we are modifying sub-vector of w
581 auto d_w = w.ReadWrite();
582 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
583 {
584 const int id = idx[i];
585 d_w[id] = d_x[id];
586 });
587
588 // A.AddMult(w, b, -1.0); // if available to all Operators
589 A->Mult(w, z);
590 b -= z;
591
592 // Use read+write access - we are modifying sub-vector of b
593 auto d_b = b.ReadWrite();
594 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
595 {
596 const int id = idx[i];
597 d_b[id] = d_x[id];
598 });
599}
600
602 const bool transpose) const
603{
604 const int csz = constraint_list.Size();
605 if (csz == 0)
606 {
607 if (transpose)
608 {
609 A->MultTranspose(x, y);
610 }
611 else
612 {
613 A->Mult(x, y);
614 }
615 return;
616 }
617
618 z = x;
619
620 auto idx = constraint_list.Read();
621 // Use read+write access - we are modifying sub-vector of z
622 auto d_z = z.ReadWrite();
623 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i) { d_z[idx[i]] = 0.0; });
624
625 if (transpose)
626 {
627 A->MultTranspose(z, y);
628 }
629 else
630 {
631 A->Mult(z, y);
632 }
633
634 auto d_x = x.Read();
635 // Use read+write access - we are modifying sub-vector of y
636 auto d_y = y.ReadWrite();
637 switch (diag_policy)
638 {
639 case DIAG_ONE:
640 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
641 {
642 const int id = idx[i];
643 d_y[id] = d_x[id];
644 });
645 break;
646 case DIAG_ZERO:
647 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
648 {
649 const int id = idx[i];
650 d_y[id] = 0.0;
651 });
652 break;
653 case DIAG_KEEP:
654 // Needs action of the operator diagonal on vector
655 mfem_error("ConstrainedOperator::Mult #1");
656 break;
657 default:
658 mfem_error("ConstrainedOperator::Mult #2");
659 break;
660 }
661}
662
664 const bool transpose) const
665{
666 const int csz = constraint_list.Size();
667 if (csz == 0)
668 {
669 if (transpose)
670 {
671 A->AbsMultTranspose(x, y);
672 }
673 else
674 {
675 A->AbsMult(x, y);
676 }
677 return;
678 }
679
680 z = x;
681
682 auto idx = constraint_list.Read();
683 // Use read+write access - we are modifying sub-vector of z
684 auto d_z = z.ReadWrite();
685 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i) { d_z[idx[i]] = 0.0; });
686
687 if (transpose)
688 {
689 A->AbsMultTranspose(z, y);
690 }
691 else
692 {
693 A->AbsMult(z, y);
694 }
695
696 auto d_x = x.Read();
697 // Use read+write access - we are modifying sub-vector of y
698 auto d_y = y.ReadWrite();
699 switch (diag_policy)
700 {
701 case DIAG_ONE:
702 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
703 {
704 const int id = idx[i];
705 d_y[id] = d_x[id];
706 });
707 break;
708 case DIAG_ZERO:
709 mfem::forall(csz, [=] MFEM_HOST_DEVICE (int i)
710 {
711 const int id = idx[i];
712 d_y[id] = 0.0;
713 });
714 break;
715 case DIAG_KEEP:
716 // Needs action of the operator diagonal on vector
717 mfem_error("ConstrainedOperator::AbsMult #1");
718 break;
719 default:
720 mfem_error("ConstrainedOperator::AbsMult #2");
721 break;
722 }
723}
724
726{
727 constexpr bool transpose = false;
728 ConstrainedMult(x, y, transpose);
729}
730
732{
733 constexpr bool transpose = false;
734 ConstrainedAbsMult(x, y, transpose);
735}
736
738{
739 constexpr bool transpose = true;
740 ConstrainedMult(x, y, transpose);
741}
742
744{
745 constexpr bool transpose = true;
746 ConstrainedAbsMult(x, y, transpose);
747}
748
750 const real_t a) const
751{
752 Mult(x, w);
753 y.Add(a, w);
754}
755
757 Operator *A,
758 const Array<int> &trial_list,
759 const Array<int> &test_list,
760 bool own_A_)
761 : Operator(A->Height(), A->Width()), A(A), own_A(own_A_)
762{
763 // 'mem_class' should work with A->Mult() and mfem::forall():
766 trial_list.Read(); // TODO: just ensure 'list' is registered, no need to copy it
767 test_list.Read(); // TODO: just ensure 'list' is registered, no need to copy it
768 trial_constraints.MakeRef(trial_list);
769 test_constraints.MakeRef(test_list);
770 // typically z and w are large vectors, so store them on the device
771 z.SetSize(height, mem_type); z.UseDevice(true);
772 w.SetSize(width, mem_type); w.UseDevice(true);
773}
774
776 Vector &b) const
777{
778 w = 0.0;
779 const int trial_csz = trial_constraints.Size();
780 auto trial_idx = trial_constraints.Read();
781 auto d_x = x.Read();
782 // Use read+write access - we are modifying sub-vector of w
783 auto d_w = w.ReadWrite();
784 mfem::forall(trial_csz, [=] MFEM_HOST_DEVICE (int i)
785 {
786 const int id = trial_idx[i];
787 d_w[id] = d_x[id];
788 });
789
790 A->AddMult(w, b, -1.0);
791
792 const int test_csz = test_constraints.Size();
793 auto test_idx = test_constraints.Read();
794 auto d_b = b.ReadWrite();
795 mfem::forall(test_csz, [=] MFEM_HOST_DEVICE (int i)
796 {
797 d_b[test_idx[i]] = 0.0;
798 });
799}
800
802{
803 const int trial_csz = trial_constraints.Size();
804 const int test_csz = test_constraints.Size();
805 if (trial_csz == 0)
806 {
807 A->Mult(x, y);
808 }
809 else
810 {
811 w = x;
812
813 auto idx = trial_constraints.Read();
814 // Use read+write access - we are modifying sub-vector of w
815 auto d_w = w.ReadWrite();
816 mfem::forall(trial_csz, [=] MFEM_HOST_DEVICE (int i)
817 {
818 d_w[idx[i]] = 0.0;
819 });
820
821 A->Mult(w, y);
822 }
823
824 if (test_csz != 0)
825 {
826 auto idx = test_constraints.Read();
827 auto d_y = y.ReadWrite();
828 mfem::forall(test_csz, [=] MFEM_HOST_DEVICE (int i)
829 {
830 d_y[idx[i]] = 0.0;
831 });
832 }
833}
834
836 Vector &y) const
837{
838 const int trial_csz = trial_constraints.Size();
839 const int test_csz = test_constraints.Size();
840 if (test_csz == 0)
841 {
842 A->MultTranspose(x, y);
843 }
844 else
845 {
846 z = x;
847
848 auto idx = test_constraints.Read();
849 // Use read+write access - we are modifying sub-vector of z
850 auto d_z = z.ReadWrite();
851 mfem::forall(test_csz, [=] MFEM_HOST_DEVICE (int i)
852 {
853 d_z[idx[i]] = 0.0;
854 });
855
856 A->MultTranspose(z, y);
857 }
858
859 if (trial_csz != 0)
860 {
861 auto idx = trial_constraints.Read();
862 auto d_y = y.ReadWrite();
863 mfem::forall(trial_csz, [=] MFEM_HOST_DEVICE (int i)
864 {
865 d_y[idx[i]] = 0.0;
866 });
867 }
868}
869
871{
872#ifndef MFEM_USE_MPI
873 return (x * y);
874#else
875 if (dot_prod_type == 0)
876 {
877 return (x * y);
878 }
879 else
880 {
881 return InnerProduct(comm, x, y);
882 }
883#endif
884}
885
887 int numSteps, real_t tolerance,
888 int seed)
889{
890 v1.SetSize(v0.Size());
891 if (seed != 0)
892 {
893 v0.Randomize(seed);
894 }
895
896 real_t eigenvalue = 1.0;
897
898 for (int iter = 0; iter < numSteps; ++iter)
899 {
900 real_t normV0;
901
902#ifdef MFEM_USE_MPI
903 if (comm != MPI_COMM_NULL)
904 {
905 normV0 = InnerProduct(comm, v0, v0);
906 }
907 else
908 {
909 normV0 = InnerProduct(v0, v0);
910 }
911#else
912 normV0 = InnerProduct(v0, v0);
913#endif
914
915 v0 /= sqrt(normV0);
916 opr.Mult(v0, v1);
917
918 real_t eigenvalueNew;
919#ifdef MFEM_USE_MPI
920 if (comm != MPI_COMM_NULL)
921 {
922 eigenvalueNew = InnerProduct(comm, v0, v1);
923 }
924 else
925 {
926 eigenvalueNew = InnerProduct(v0, v1);
927 }
928#else
929 eigenvalueNew = InnerProduct(v0, v1);
930#endif
931 real_t diff = std::abs((eigenvalueNew - eigenvalue) / eigenvalue);
932
933 eigenvalue = eigenvalueNew;
934 std::swap(v0, v1);
935
936 if (diff < tolerance)
937 {
938 break;
939 }
940 }
941
942 return eigenvalue;
943}
944
945}
int Size() const
Return the logical size of the array.
Definition array.hpp:192
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
Definition array.hpp:1082
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:410
Square Operator for imposing essential boundary conditions using only the action, Mult(),...
Array< int > constraint_list
List of constrained indices/dofs.
void Mult(const Vector &x, Vector &y) const override
Constrained operator action.
Definition operator.cpp:725
Operator * A
The unconstrained Operator.
void EliminateRHS(const Vector &x, Vector &b) const
Eliminate "essential boundary condition" values specified in x from the given right-hand side b.
Definition operator.cpp:574
void ConstrainedAbsMult(const Vector &x, Vector &y, const bool transpose) const
Implementation of AbsMult or AbsMultTranspose. TODO - Generalize to allow constraining rows and colum...
Definition operator.cpp:663
ConstrainedOperator(Operator *A, const Array< int > &list, bool own_A=false, DiagonalPolicy diag_policy=DIAG_ONE)
Constructor from a general Operator and a list of essential indices/dofs.
Definition operator.cpp:526
void AbsMultTranspose(const Vector &x, Vector &y) const override
Action of the transpose absolute-value operator: y=|A|^t(x). The default behavior in class Operator i...
Definition operator.cpp:743
void AddMult(const Vector &x, Vector &y, const real_t a=1.0) const override
Operator application: y+=A(x) (default) or y+=a*A(x).
Definition operator.cpp:749
void AssembleDiagonal(Vector &diag) const override
Diagonal of A, modified according to the used DiagonalPolicy.
Definition operator.cpp:543
DiagonalPolicy diag_policy
Diagonal policy for constrained dofs.
void ConstrainedMult(const Vector &x, Vector &y, const bool transpose) const
Implementation of Mult or MultTranspose. TODO - Generalize to allow constraining rows and columns dif...
Definition operator.cpp:601
Vector w
Auxiliary vectors.
void AbsMult(const Vector &x, Vector &y) const override
Action of the absolute-value operator: y=|A|(x). The default behavior in class Operator is to generat...
Definition operator.cpp:731
void MultTranspose(const Vector &x, Vector &y) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition operator.cpp:737
static MemoryClass GetMemoryClass()
(DEPRECATED) Equivalent to GetDeviceMemoryClass().
Definition device.hpp:310
static MemoryClass GetDeviceMemoryClass()
Get the current Device MemoryClass. This is the MemoryClass used by most MFEM device kernels to acces...
Definition device.hpp:306
virtual real_t Dot(const Vector &x, const Vector &y) const
Standard global/local inner product.
Definition operator.cpp:870
Class representing an array of Vectors with generally different sizes.
Abstract operator.
Definition operator.hpp:27
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:146
virtual MemoryClass GetMemoryClass() const
Return the MemoryClass preferred by the Operator.
Definition operator.hpp:88
void FormConstrainedSystemOperator(const Array< int > &ess_tdof_list, ConstrainedOperator *&Aout)
see FormSystemOperator()
Definition operator.cpp:212
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:129
int width
Dimension of the input / number of columns in the matrix.
Definition operator.hpp:30
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:242
void FormDiscreteOperator(Operator *&A)
Return in A a parallel (on truedofs) version of this rectangular operator.
Definition operator.cpp:259
virtual void ArrayMultTranspose(const Array< const Vector * > &X, Array< Vector * > &Y) const
Action of the transpose operator on a matrix: Y=A^t(X).
Definition operator.cpp:78
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
int height
Dimension of the output / number of rows in the matrix.
Definition operator.hpp:29
virtual void ArrayAddMult(const Array< const Vector * > &X, Array< Vector * > &Y, const real_t a=1.0) const
Operator application on a matrix: Y+=A(X) (default) or Y+=a*A(X).
Definition operator.cpp:90
virtual const Operator * GetRestriction() const
Restriction operator from input vectors for the operator to linear algebra (linear system) vectors....
Definition operator.hpp:178
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_ONE
Set the diagonal value to one.
Definition operator.hpp:52
@ DIAG_KEEP
Keep the diagonal value.
Definition operator.hpp:53
@ DIAG_ZERO
Set the diagonal value to zero.
Definition operator.hpp:51
virtual const Operator * GetOutputRestriction() const
Restriction operator from output vectors for the operator to linear algebra (linear system) vectors....
Definition operator.hpp:195
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
virtual const Operator * GetOutputProlongation() const
Prolongation operator from linear algebra (linear system) vectors, to output vectors for the operator...
Definition operator.hpp:182
virtual void ArrayAddMultTranspose(const Array< const Vector * > &X, Array< Vector * > &Y, const real_t a=1.0) const
Operator transpose application on a matrix: Y+=A^t(X) (default) or Y+=a*A^t(X).
Definition operator.cpp:102
virtual void ArrayMult(const Array< const Vector * > &X, Array< Vector * > &Y) const
Operator application on a matrix: Y=A(X).
Definition operator.cpp:66
virtual const Operator * GetProlongation() const
Prolongation operator from linear algebra (linear system) vectors, to input vectors for the operator....
Definition operator.hpp:174
virtual void MultMV(const MultiVector &x, MultiVector &y) const
Operator application, y = A(x), where the input x and the output y are MultiVector objects,...
Definition operator.cpp:114
virtual Operator & GetGradientMV(const MultiVector &x) const
Evaluate the gradient operator at the point x. The input x is provided as a MultiVector,...
Definition operator.cpp:124
virtual void MultTransposeMV(const MultiVector &x, MultiVector &y) const
Action of the transpose operator, y = A^t(x), where the input x and the output y are MultiVector obje...
Definition operator.cpp:119
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:250
Operator * SetupRAP(const Operator *Pi, const Operator *Po)
Returns RAP Operator of this, using input/output Prolongation matrices Pi corresponds to "P",...
Definition operator.cpp:183
virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
Reconstruct a solution vector x (e.g. a GridFunction) from the solution X of a constrained linear sys...
Definition operator.cpp:163
virtual void AbsMultTranspose(const Vector &x, Vector &y) const
Action of the transpose absolute-value operator: y=|A|^t(x). The default behavior in class Operator i...
Definition operator.hpp:107
virtual void AssembleDiagonal(Vector &diag) const
Computes the diagonal entries into diag. Typically, this operation only makes sense for linear Operat...
Definition operator.hpp:166
void InitTVectors(const Operator *Po, const Operator *Ri, const Operator *Pi, Vector &x, Vector &b, Vector &X, Vector &B) const
Initializes memory for true vectors of linear system.
Definition operator.cpp:22
virtual void AddMultTranspose(const Vector &x, Vector &y, const real_t a=1.0) const
Operator transpose application: y+=A^t(x) (default) or y+=a*A^t(x).
Definition operator.cpp:58
void FormRectangularConstrainedSystemOperator(const Array< int > &trial_tdof_list, const Array< int > &test_tdof_list, RectangularConstrainedOperator *&Aout)
see FormRectangularSystemOperator()
Definition operator.cpp:225
virtual void AbsMult(const Vector &x, Vector &y) const
Action of the absolute-value operator: y=|A|(x). The default behavior in class Operator is to generat...
Definition operator.hpp:97
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:102
void PrintMatlab(std::ostream &out, int n, int m=0) const
Prints operator with input size n and output size m in Matlab format.
Definition operator.cpp:266
virtual void AddMult(const Vector &x, Vector &y, const real_t a=1.0) const
Operator application: y+=A(x) (default) or y+=a*A(x).
Definition operator.cpp:51
real_t EstimateLargestEigenvalue(Operator &opr, Vector &v0, int numSteps=10, real_t tolerance=1e-8, int seed=12345)
Returns an estimate of the largest eigenvalue of the operator opr using the iterative power method.
Definition operator.cpp:886
General product operator: x -> (A*B)(x) = A(B(x)).
Definition operator.hpp:969
ProductOperator(const Operator *A, const Operator *B, bool ownA, bool ownB)
Definition operator.cpp:422
virtual ~ProductOperator()
Definition operator.cpp:441
The operator x -> R*A*P*x constructed through the actions of R^T, A and P.
Definition operator.hpp:989
RAPOperator(const Operator &Rt_, const Operator &A_, const Operator &P_)
Construct the RAP operator given R^T, A and P.
Definition operator.cpp:448
Rectangular Operator for imposing essential boundary conditions on the input space using only the act...
RectangularConstrainedOperator(Operator *A, const Array< int > &trial_list, const Array< int > &test_list, bool own_A=false)
Constructor from a general Operator and a list of essential indices/dofs.
Definition operator.cpp:756
void EliminateRHS(const Vector &x, Vector &b) const
Eliminate columns corresponding to "essential boundary condition" values specified in x from the give...
Definition operator.cpp:775
void Mult(const Vector &x, Vector &y) const override
Rectangular-constrained operator action.
Definition operator.cpp:801
void MultTranspose(const Vector &x, Vector &y) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition operator.cpp:835
virtual void Mult(const Vector &x, const Vector &dxdt, Vector &y) const
Perform the action of the operator: y = k = f(x,@ dxdt, t), where k solves the algebraic equation F(x...
Definition operator.cpp:367
virtual void ImplicitSolve(const real_t fac0, const real_t fac1, const Vector &x, const Vector &dxdt, Vector &k)
Solve the equation: k = f(x + fac0 k, dxdt + fac1 k, t), for the unknown k at the current time t.
Definition operator.cpp:374
Base class for solvers.
Definition operator.hpp:855
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
Definition operator.hpp:858
virtual ~SumOperator()
Definition operator.cpp:416
SumOperator(const Operator *A, const real_t alpha, const Operator *B, const real_t beta, bool ownA, bool ownB)
Definition operator.cpp:383
virtual void ImplicitSolve(const real_t gamma, const Vector &u, Vector &k)
Solve for the unknown k, at the current time t, the following equation:
Definition operator.cpp:313
virtual int SUNImplicitSolve(const Vector &r, Vector &dk, real_t tol)
Solve the ODE linear system A dk = r , where A and r are defined by the method SUNImplicitSetup().
Definition operator.cpp:342
virtual int SUNMassMult(const Vector &x, Vector &v)
Compute the mass matrix-vector product v = M x, where M is defined by the method SUNMassSetup().
Definition operator.cpp:360
virtual Operator & GetExplicitGradient(const Vector &u) const
Return an Operator representing dG/du at the given point u and the currently set time.
Definition operator.cpp:327
virtual int SUNMassSetup()
Setup the mass matrix in the ODE system .
Definition operator.cpp:348
void Mult(const Vector &u, Vector &k) const override
Perform the action of the operator (u,t) -> k(u,t) where t is the current time set by SetTime() and k...
Definition operator.cpp:308
virtual int SUNMassSolve(const Vector &b, Vector &x, real_t tol)
Solve the mass matrix linear system M x = b, where M is defined by the method SUNMassSetup().
Definition operator.cpp:354
virtual void ExplicitMult(const Vector &u, Vector &v) const
Perform the action of the explicit part of the operator, G: v = G(u, t) where t is the current time.
Definition operator.cpp:297
virtual Operator & GetImplicitGradient(const Vector &u, const Vector &k, real_t shift) const
Return an Operator representing (dF/dk shift + dF/du) at the given u, k, and the currently set time.
Definition operator.cpp:319
virtual void ImplicitMult(const Vector &u, const Vector &k, Vector &v) const
Perform the action of the implicit part of the operator, F: v = F(u, k, t) where t is the current tim...
Definition operator.cpp:302
virtual int SUNImplicitSetup(const Vector &y, const Vector &v, int jok, int *jcur, real_t gamma)
Setup a linear system as needed by some SUNDIALS ODE solvers to perform a similar action to ImplicitS...
Definition operator.cpp:334
The transpose of a given operator. Switches the roles of the methods Mult() and MultTranspose().
Definition operator.hpp:922
General triple product operator x -> A*B*C*x, with ownership of the factors.
TripleProductOperator(const Operator *A, const Operator *B, const Operator *C, bool ownA, bool ownB, bool ownC)
Definition operator.cpp:482
Vector data type.
Definition vector.hpp:82
void Randomize(int seed=0)
Set random values in the vector.
Definition vector.cpp:955
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:520
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:536
void SyncMemory(const Vector &v) const
Update the memory location of the vector to match v.
Definition vector.hpp:272
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
void SetSubVectorComplement(const Array< int > &dofs, const real_t val)
Set all vector entries NOT in the dofs Array to the given val.
Definition vector.cpp:854
Vector & Add(const real_t a, const Vector &Va)
(*this) += a * Va
Definition vector.cpp:326
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
const int * ess_tdof_list
const real_t alpha
Definition ex15.cpp:369
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
void mfem_error(const char *msg)
Definition error.cpp:154
real_t InnerProduct(HypreParVector *x, HypreParVector *y)
Definition hypre.cpp:471
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
bool IsIdentityProlongation(const Operator *P)
Definition operator.hpp:892
float real_t
Definition config.hpp:46
MemoryType
Memory types supported by MFEM.
void forall(int N, lambda &&body)
Definition forall.hpp:1134
STL namespace.