1 // Copyright (c) 2010-2021, 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 #ifndef MFEM_COMPLEX_FEM 13 #define MFEM_COMPLEX_FEM 14 15 #include "../linalg/complex_operator.hpp" 16 #include "gridfunc.hpp" 17 #include "linearform.hpp" 18 #include "bilinearform.hpp" 19 #ifdef MFEM_USE_MPI 20 #include "pgridfunc.hpp" 21 #include "plinearform.hpp" 22 #include "pbilinearform.hpp" 23 #endif 24 #include <complex> 25 26 namespace mfem 27 { 28 29 /// Class for complex-valued grid function - real + imaginary part Vector with 30 /// associated FE space. 31 class ComplexGridFunction : public Vector 32 { 33 private: 34 GridFunction * gfr; 35 GridFunction * gfi; 36 37 protected: Destroy()38 void Destroy() { delete gfr; delete gfi; } 39 40 public: 41 /** @brief Construct a ComplexGridFunction associated with the 42 FiniteElementSpace @a *f. */ 43 ComplexGridFunction(FiniteElementSpace *f); 44 45 void Update(); 46 47 /// Assign constant values to the ComplexGridFunction data. operator =(const std::complex<double> & value)48 ComplexGridFunction &operator=(const std::complex<double> & value) 49 { *gfr = value.real(); *gfi = value.imag(); return *this; } 50 51 virtual void ProjectCoefficient(Coefficient &real_coeff, 52 Coefficient &imag_coeff); 53 virtual void ProjectCoefficient(VectorCoefficient &real_vcoeff, 54 VectorCoefficient &imag_vcoeff); 55 56 virtual void ProjectBdrCoefficient(Coefficient &real_coeff, 57 Coefficient &imag_coeff, 58 Array<int> &attr); 59 virtual void ProjectBdrCoefficientNormal(VectorCoefficient &real_coeff, 60 VectorCoefficient &imag_coeff, 61 Array<int> &attr); 62 virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, 63 VectorCoefficient &imag_coeff, 64 Array<int> &attr); 65 FESpace()66 FiniteElementSpace *FESpace() { return gfr->FESpace(); } FESpace() const67 const FiniteElementSpace *FESpace() const { return gfr->FESpace(); } 68 real()69 GridFunction & real() { return *gfr; } imag()70 GridFunction & imag() { return *gfi; } real() const71 const GridFunction & real() const { return *gfr; } imag() const72 const GridFunction & imag() const { return *gfi; } 73 74 /// Update the memory location of the real and imaginary GridFunction @a gfr 75 /// and @a gfi to match the ComplexGridFunction. Sync()76 void Sync() { gfr->SyncMemory(*this); gfi->SyncMemory(*this); } 77 78 /// Update the alias memory location of the real and imaginary GridFunction 79 /// @a gfr and @a gfi to match the ComplexGridFunction. SyncAlias()80 void SyncAlias() { gfr->SyncAliasMemory(*this); gfi->SyncAliasMemory(*this); } 81 82 /// Destroys the grid function. ~ComplexGridFunction()83 virtual ~ComplexGridFunction() { Destroy(); } 84 85 }; 86 87 /** Class for a complex-valued linear form 88 89 The @a convention argument in the class's constructor is documented in the 90 mfem::ComplexOperator class found in linalg/complex_operator.hpp. 91 92 When supplying integrators to the ComplexLinearForm either the real or 93 imaginary integrator can be NULL. This indicates that the corresponding 94 portion of the complex-valued field is equal to zero. 95 */ 96 class ComplexLinearForm : public Vector 97 { 98 private: 99 ComplexOperator::Convention conv; 100 101 protected: 102 LinearForm * lfr; 103 LinearForm * lfi; 104 105 public: 106 ComplexLinearForm(FiniteElementSpace *fes, 107 ComplexOperator::Convention 108 convention = ComplexOperator::HERMITIAN); 109 110 /** @brief Create a ComplexLinearForm on the FiniteElementSpace @a fes, using 111 the same integrators as the LinearForms @a lf_r (real) and @a lf_i (imag). 112 113 The pointer @a fes is not owned by the newly constructed object. 114 115 The integrators are copied as pointers and they are not owned by the 116 newly constructed ComplexLinearForm. */ 117 ComplexLinearForm(FiniteElementSpace *fes, LinearForm *lf_r, LinearForm *lf_i, 118 ComplexOperator::Convention 119 convention = ComplexOperator::HERMITIAN); 120 121 virtual ~ComplexLinearForm(); 122 GetConvention() const123 ComplexOperator::Convention GetConvention() const { return conv; } SetConvention(const ComplexOperator::Convention & convention)124 void SetConvention(const ComplexOperator::Convention & 125 convention) { conv = convention; } 126 127 /// Adds new Domain Integrator. 128 void AddDomainIntegrator(LinearFormIntegrator *lfi_real, 129 LinearFormIntegrator *lfi_imag); 130 131 /// Adds new Boundary Integrator. 132 void AddBoundaryIntegrator(LinearFormIntegrator *lfi_real, 133 LinearFormIntegrator *lfi_imag); 134 135 /** @brief Add new Boundary Integrator, restricted to the given boundary 136 attributes. 137 138 Assumes ownership of @a lfi_real and @a lfi_imag. 139 140 The array @a bdr_attr_marker is stored internally as a pointer to the 141 given Array<int> object. */ 142 void AddBoundaryIntegrator(LinearFormIntegrator *lfi_real, 143 LinearFormIntegrator *lfi_imag, 144 Array<int> &bdr_attr_marker); 145 146 /// Adds new Boundary Face Integrator. Assumes ownership of @a lfi. 147 void AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real, 148 LinearFormIntegrator *lfi_imag); 149 150 /** @brief Add new Boundary Face Integrator, restricted to the given boundary 151 attributes. 152 153 Assumes ownership of @a lfi_real and @a lfi_imag. 154 155 The array @a bdr_attr_marker is stored internally as a pointer to the 156 given Array<int> object. */ 157 void AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real, 158 LinearFormIntegrator *lfi_imag, 159 Array<int> &bdr_attr_marker); 160 FESpace() const161 FiniteElementSpace *FESpace() const { return lfr->FESpace(); } 162 real()163 LinearForm & real() { return *lfr; } imag()164 LinearForm & imag() { return *lfi; } real() const165 const LinearForm & real() const { return *lfr; } imag() const166 const LinearForm & imag() const { return *lfi; } 167 168 /// Update the memory location of the real and imaginary LinearForm @a lfr 169 /// and @a lfi to match the ComplexLinearForm. Sync()170 void Sync() { lfr->SyncMemory(*this); lfi->SyncMemory(*this); } 171 172 /// Update the alias memory location of the real and imaginary LinearForm @a 173 /// lfr and @a lfi to match the ComplexLinearForm. SyncAlias()174 void SyncAlias() { lfr->SyncAliasMemory(*this); lfi->SyncAliasMemory(*this); } 175 176 void Update(); 177 void Update(FiniteElementSpace *f); 178 179 /// Assembles the linear form i.e. sums over all domain/bdr integrators. 180 void Assemble(); 181 182 std::complex<double> operator()(const ComplexGridFunction &gf) const; 183 }; 184 185 186 /** Class for sesquilinear form 187 188 A sesquilinear form is a generalization of a bilinear form to complex-valued 189 fields. Sesquilinear forms are linear in the second argument but the first 190 argument involves a complex conjugate in the sense that: 191 192 a(alpha u, beta v) = conj(alpha) beta a(u, v) 193 194 The @a convention argument in the class's constructor is documented in the 195 mfem::ComplexOperator class found in linalg/complex_operator.hpp. 196 197 When supplying integrators to the SesquilinearForm either the real or 198 imaginary integrator can be NULL. This indicates that the corresponding 199 portion of the complex-valued material coefficient is equal to zero. 200 */ 201 class SesquilinearForm 202 { 203 private: 204 ComplexOperator::Convention conv; 205 206 /** This data member allows one to specify what should be done to the 207 diagonal matrix entries and corresponding RHS values upon elimination of 208 the constrained DoFs. */ 209 mfem::Matrix::DiagonalPolicy diag_policy = mfem::Matrix::DIAG_ONE; 210 211 BilinearForm *blfr; 212 BilinearForm *blfi; 213 214 /* These methods check if the real/imag parts of the sesquilinear form are 215 not empty */ 216 bool RealInteg(); 217 bool ImagInteg(); 218 219 public: 220 SesquilinearForm(FiniteElementSpace *fes, 221 ComplexOperator::Convention 222 convention = ComplexOperator::HERMITIAN); 223 /** @brief Create a SesquilinearForm on the FiniteElementSpace @a fes, using 224 the same integrators as the BilinearForms @a bfr and @a bfi . 225 226 The pointer @a fes is not owned by the newly constructed object. 227 228 The integrators are copied as pointers and they are not owned by the 229 newly constructed SesquilinearForm. */ 230 SesquilinearForm(FiniteElementSpace *fes, BilinearForm *bfr, BilinearForm *bfi, 231 ComplexOperator::Convention 232 convention = ComplexOperator::HERMITIAN); 233 GetConvention() const234 ComplexOperator::Convention GetConvention() const { return conv; } SetConvention(const ComplexOperator::Convention & convention)235 void SetConvention(const ComplexOperator::Convention & 236 convention) { conv = convention; } 237 238 /// Set the desired assembly level. 239 /** Valid choices are: 240 241 - AssemblyLevel::LEGACY (default) 242 - AssemblyLevel::FULL 243 - AssemblyLevel::PARTIAL 244 - AssemblyLevel::ELEMENT 245 - AssemblyLevel::NONE 246 247 This method must be called before assembly. */ SetAssemblyLevel(AssemblyLevel assembly_level)248 void SetAssemblyLevel(AssemblyLevel assembly_level) 249 { 250 blfr->SetAssemblyLevel(assembly_level); 251 blfi->SetAssemblyLevel(assembly_level); 252 } 253 real()254 BilinearForm & real() { return *blfr; } imag()255 BilinearForm & imag() { return *blfi; } real() const256 const BilinearForm & real() const { return *blfr; } imag() const257 const BilinearForm & imag() const { return *blfi; } 258 259 /// Adds new Domain Integrator. 260 void AddDomainIntegrator(BilinearFormIntegrator *bfi_real, 261 BilinearFormIntegrator *bfi_imag); 262 263 /// Adds new Boundary Integrator. 264 void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, 265 BilinearFormIntegrator *bfi_imag); 266 267 /// Adds new Boundary Integrator, restricted to specific boundary attributes. 268 void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, 269 BilinearFormIntegrator *bfi_imag, 270 Array<int> &bdr_marker); 271 272 /// Adds new interior Face Integrator. Assumes ownership of @a bfi. 273 void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi_real, 274 BilinearFormIntegrator *bfi_imag); 275 276 /// Adds new boundary Face Integrator. Assumes ownership of @a bfi. 277 void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, 278 BilinearFormIntegrator *bfi_imag); 279 280 /** @brief Adds new boundary Face Integrator, restricted to specific boundary 281 attributes. 282 283 Assumes ownership of @a bfi. 284 285 The array @a bdr_marker is stored internally as a pointer to the given 286 Array<int> object. */ 287 void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, 288 BilinearFormIntegrator *bfi_imag, 289 Array<int> &bdr_marker); 290 291 /// Assemble the local matrix 292 void Assemble(int skip_zeros = 1); 293 294 /// Finalizes the matrix initialization. 295 void Finalize(int skip_zeros = 1); 296 297 /// Returns the matrix assembled on the true dofs, i.e. P^t A P. 298 /** The returned matrix has to be deleted by the caller. */ 299 ComplexSparseMatrix *AssembleComplexSparseMatrix(); 300 301 /// Return the parallel FE space associated with the ParBilinearForm. FESpace() const302 FiniteElementSpace *FESpace() const { return blfr->FESpace(); } 303 304 void FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b, 305 OperatorHandle &A, Vector &X, Vector &B, 306 int copy_interior = 0); 307 308 void FormSystemMatrix(const Array<int> &ess_tdof_list, 309 OperatorHandle &A); 310 311 /** Call this method after solving a linear system constructed using the 312 FormLinearSystem method to recover the solution as a ParGridFunction-size 313 vector in x. Use the same arguments as in the FormLinearSystem call. */ 314 virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x); 315 316 virtual void Update(FiniteElementSpace *nfes = NULL); 317 318 /// Sets diagonal policy used upon construction of the linear system 319 void SetDiagonalPolicy(mfem::Matrix::DiagonalPolicy dpolicy); 320 321 /// Returns the diagonal policy of the sesquilinear form GetDiagonalPolicy() const322 Matrix::DiagonalPolicy GetDiagonalPolicy() const {return diag_policy;} 323 324 virtual ~SesquilinearForm(); 325 }; 326 327 #ifdef MFEM_USE_MPI 328 329 /// Class for parallel complex-valued grid function - real + imaginary part 330 /// Vector with associated parallel FE space. 331 class ParComplexGridFunction : public Vector 332 { 333 private: 334 335 ParGridFunction * pgfr; 336 ParGridFunction * pgfi; 337 338 protected: Destroy()339 void Destroy() { delete pgfr; delete pgfi; } 340 341 public: 342 343 /** @brief Construct a ParComplexGridFunction associated with the 344 ParFiniteElementSpace @a *pf. */ 345 ParComplexGridFunction(ParFiniteElementSpace *pf); 346 347 void Update(); 348 349 /// Assign constant values to the ParComplexGridFunction data. operator =(const std::complex<double> & value)350 ParComplexGridFunction &operator=(const std::complex<double> & value) 351 { *pgfr = value.real(); *pgfi = value.imag(); return *this; } 352 353 virtual void ProjectCoefficient(Coefficient &real_coeff, 354 Coefficient &imag_coeff); 355 virtual void ProjectCoefficient(VectorCoefficient &real_vcoeff, 356 VectorCoefficient &imag_vcoeff); 357 358 virtual void ProjectBdrCoefficient(Coefficient &real_coeff, 359 Coefficient &imag_coeff, 360 Array<int> &attr); 361 virtual void ProjectBdrCoefficientNormal(VectorCoefficient &real_coeff, 362 VectorCoefficient &imag_coeff, 363 Array<int> &attr); 364 virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, 365 VectorCoefficient &imag_coeff, 366 Array<int> &attr); 367 368 void Distribute(const Vector *tv); Distribute(const Vector & tv)369 void Distribute(const Vector &tv) { Distribute(&tv); } 370 371 /// Returns the vector restricted to the true dofs. 372 void ParallelProject(Vector &tv) const; 373 FESpace()374 FiniteElementSpace *FESpace() { return pgfr->FESpace(); } FESpace() const375 const FiniteElementSpace *FESpace() const { return pgfr->FESpace(); } 376 ParFESpace()377 ParFiniteElementSpace *ParFESpace() { return pgfr->ParFESpace(); } ParFESpace() const378 const ParFiniteElementSpace *ParFESpace() const { return pgfr->ParFESpace(); } 379 real()380 ParGridFunction & real() { return *pgfr; } imag()381 ParGridFunction & imag() { return *pgfi; } real() const382 const ParGridFunction & real() const { return *pgfr; } imag() const383 const ParGridFunction & imag() const { return *pgfi; } 384 385 /// Update the memory location of the real and imaginary ParGridFunction @a 386 /// pgfr and @a pgfi to match the ParComplexGridFunction. Sync()387 void Sync() { pgfr->SyncMemory(*this); pgfi->SyncMemory(*this); } 388 389 /// Update the alias memory location of the real and imaginary 390 /// ParGridFunction @a pgfr and @a pgfi to match the ParComplexGridFunction. SyncAlias()391 void SyncAlias() { pgfr->SyncAliasMemory(*this); pgfi->SyncAliasMemory(*this); } 392 393 ComputeL2Error(Coefficient & exsolr,Coefficient & exsoli,const IntegrationRule * irs[]=NULL) const394 virtual double ComputeL2Error(Coefficient &exsolr, Coefficient &exsoli, 395 const IntegrationRule *irs[] = NULL) const 396 { 397 double err_r = pgfr->ComputeL2Error(exsolr, irs); 398 double err_i = pgfi->ComputeL2Error(exsoli, irs); 399 return sqrt(err_r * err_r + err_i * err_i); 400 } 401 ComputeL2Error(VectorCoefficient & exsolr,VectorCoefficient & exsoli,const IntegrationRule * irs[]=NULL,Array<int> * elems=NULL) const402 virtual double ComputeL2Error(VectorCoefficient &exsolr, 403 VectorCoefficient &exsoli, 404 const IntegrationRule *irs[] = NULL, 405 Array<int> *elems = NULL) const 406 { 407 double err_r = pgfr->ComputeL2Error(exsolr, irs, elems); 408 double err_i = pgfi->ComputeL2Error(exsoli, irs, elems); 409 return sqrt(err_r * err_r + err_i * err_i); 410 } 411 412 413 /// Destroys grid function. ~ParComplexGridFunction()414 virtual ~ParComplexGridFunction() { Destroy(); } 415 416 }; 417 418 /** Class for a complex-valued, parallel linear form 419 420 The @a convention argument in the class's constructor is documented in the 421 mfem::ComplexOperator class found in linalg/complex_operator.hpp. 422 423 When supplying integrators to the ParComplexLinearForm either the real or 424 imaginary integrator can be NULL. This indicates that the corresponding 425 portion of the complex-valued field is equal to zero. 426 */ 427 class ParComplexLinearForm : public Vector 428 { 429 private: 430 ComplexOperator::Convention conv; 431 432 protected: 433 ParLinearForm * plfr; 434 ParLinearForm * plfi; 435 436 HYPRE_BigInt * tdof_offsets; 437 438 public: 439 440 ParComplexLinearForm(ParFiniteElementSpace *pf, 441 ComplexOperator::Convention 442 convention = ComplexOperator::HERMITIAN); 443 444 /** @brief Create a ParComplexLinearForm on the ParFiniteElementSpace @a pf, 445 using the same integrators as the LinearForms @a plf_r (real) and 446 @a plf_i (imag). 447 448 The pointer @a fes is not owned by the newly constructed object. 449 450 The integrators are copied as pointers and they are not owned by the newly 451 constructed ParComplexLinearForm. */ 452 ParComplexLinearForm(ParFiniteElementSpace *pf, ParLinearForm *plf_r, 453 ParLinearForm *plf_i, 454 ComplexOperator::Convention 455 convention = ComplexOperator::HERMITIAN); 456 457 virtual ~ParComplexLinearForm(); 458 GetConvention() const459 ComplexOperator::Convention GetConvention() const { return conv; } SetConvention(const ComplexOperator::Convention & convention)460 void SetConvention(const ComplexOperator::Convention & 461 convention) { conv = convention; } 462 463 /// Adds new Domain Integrator. 464 void AddDomainIntegrator(LinearFormIntegrator *lfi_real, 465 LinearFormIntegrator *lfi_imag); 466 467 /// Adds new Boundary Integrator. 468 void AddBoundaryIntegrator(LinearFormIntegrator *lfi_real, 469 LinearFormIntegrator *lfi_imag); 470 471 /** @brief Add new Boundary Integrator, restricted to the given boundary 472 attributes. 473 474 Assumes ownership of @a lfi_real and @a lfi_imag. 475 476 The array @a bdr_attr_marker is stored internally as a pointer to the 477 given Array<int> object. */ 478 void AddBoundaryIntegrator(LinearFormIntegrator *lfi_real, 479 LinearFormIntegrator *lfi_imag, 480 Array<int> &bdr_attr_marker); 481 482 /// Adds new Boundary Face Integrator. Assumes ownership of @a lfi. 483 void AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real, 484 LinearFormIntegrator *lfi_imag); 485 486 /** @brief Add new Boundary Face Integrator, restricted to the given boundary 487 attributes. 488 489 Assumes ownership of @a lfi_real and @a lfi_imag. 490 491 The array @a bdr_attr_marker is stored internally as a pointer to the 492 given Array<int> object. */ 493 void AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real, 494 LinearFormIntegrator *lfi_imag, 495 Array<int> &bdr_attr_marker); 496 ParFESpace() const497 ParFiniteElementSpace *ParFESpace() const { return plfr->ParFESpace(); } 498 real()499 ParLinearForm & real() { return *plfr; } imag()500 ParLinearForm & imag() { return *plfi; } real() const501 const ParLinearForm & real() const { return *plfr; } imag() const502 const ParLinearForm & imag() const { return *plfi; } 503 504 /// Update the memory location of the real and imaginary ParLinearForm @a lfr 505 /// and @a lfi to match the ParComplexLinearForm. Sync()506 void Sync() { plfr->SyncMemory(*this); plfi->SyncMemory(*this); } 507 508 /// Update the alias memory location of the real and imaginary ParLinearForm 509 /// @a plfr and @a plfi to match the ParComplexLinearForm. SyncAlias()510 void SyncAlias() { plfr->SyncAliasMemory(*this); plfi->SyncAliasMemory(*this); } 511 512 void Update(ParFiniteElementSpace *pf = NULL); 513 514 /// Assembles the linear form i.e. sums over all domain/bdr integrators. 515 void Assemble(); 516 517 /// Assemble the vector on the true dofs, i.e. P^t v. 518 void ParallelAssemble(Vector &tv); 519 520 /// Returns the vector assembled on the true dofs, i.e. P^t v. 521 HypreParVector *ParallelAssemble(); 522 523 std::complex<double> operator()(const ParComplexGridFunction &gf) const; 524 525 }; 526 527 /** Class for a parallel sesquilinear form 528 529 A sesquilinear form is a generalization of a bilinear form to complex-valued 530 fields. Sesquilinear forms are linear in the second argument but the 531 first argument involves a complex conjugate in the sense that: 532 533 a(alpha u, beta v) = conj(alpha) beta a(u, v) 534 535 The @a convention argument in the class's constructor is documented in the 536 mfem::ComplexOperator class found in linalg/complex_operator.hpp. 537 538 When supplying integrators to the ParSesquilinearForm either the real or 539 imaginary integrator can be NULL. This indicates that the corresponding 540 portion of the complex-valued material coefficient is equal to zero. 541 */ 542 class ParSesquilinearForm 543 { 544 private: 545 ComplexOperator::Convention conv; 546 547 ParBilinearForm *pblfr; 548 ParBilinearForm *pblfi; 549 550 /* These methods check if the real/imag parts of the sesqulinear form are not 551 empty */ 552 bool RealInteg(); 553 bool ImagInteg(); 554 555 public: 556 ParSesquilinearForm(ParFiniteElementSpace *pf, 557 ComplexOperator::Convention 558 convention = ComplexOperator::HERMITIAN); 559 560 /** @brief Create a ParSesquilinearForm on the ParFiniteElementSpace @a pf, 561 using the same integrators as the ParBilinearForms @a pbfr and @a pbfi . 562 563 The pointer @a pf is not owned by the newly constructed object. 564 565 The integrators are copied as pointers and they are not owned by the 566 newly constructed ParSesquilinearForm. */ 567 ParSesquilinearForm(ParFiniteElementSpace *pf, ParBilinearForm *pbfr, 568 ParBilinearForm *pbfi, 569 ComplexOperator::Convention 570 convention = ComplexOperator::HERMITIAN); 571 GetConvention() const572 ComplexOperator::Convention GetConvention() const { return conv; } SetConvention(const ComplexOperator::Convention & convention)573 void SetConvention(const ComplexOperator::Convention & 574 convention) { conv = convention; } 575 576 /// Set the desired assembly level. 577 /** Valid choices are: 578 579 - AssemblyLevel::LEGACY (default) 580 - AssemblyLevel::FULL 581 - AssemblyLevel::PARTIAL 582 - AssemblyLevel::ELEMENT 583 - AssemblyLevel::NONE 584 585 This method must be called before assembly. */ SetAssemblyLevel(AssemblyLevel assembly_level)586 void SetAssemblyLevel(AssemblyLevel assembly_level) 587 { 588 pblfr->SetAssemblyLevel(assembly_level); 589 pblfi->SetAssemblyLevel(assembly_level); 590 } 591 real()592 ParBilinearForm & real() { return *pblfr; } imag()593 ParBilinearForm & imag() { return *pblfi; } real() const594 const ParBilinearForm & real() const { return *pblfr; } imag() const595 const ParBilinearForm & imag() const { return *pblfi; } 596 597 /// Adds new Domain Integrator. 598 void AddDomainIntegrator(BilinearFormIntegrator *bfi_real, 599 BilinearFormIntegrator *bfi_imag); 600 601 /// Adds new Boundary Integrator. 602 void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, 603 BilinearFormIntegrator *bfi_imag); 604 605 /** @brief Adds new boundary Integrator, restricted to specific boundary 606 attributes. 607 608 Assumes ownership of @a bfi. 609 610 The array @a bdr_marker is stored internally as a pointer to the given 611 Array<int> object. */ 612 void AddBoundaryIntegrator(BilinearFormIntegrator *bfi_real, 613 BilinearFormIntegrator *bfi_imag, 614 Array<int> &bdr_marker); 615 616 /// Adds new interior Face Integrator. Assumes ownership of @a bfi. 617 void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi_real, 618 BilinearFormIntegrator *bfi_imag); 619 620 /// Adds new boundary Face Integrator. Assumes ownership of @a bfi. 621 void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, 622 BilinearFormIntegrator *bfi_imag); 623 624 /** @brief Adds new boundary Face Integrator, restricted to specific boundary 625 attributes. 626 627 Assumes ownership of @a bfi. 628 629 The array @a bdr_marker is stored internally as a pointer to the given 630 Array<int> object. */ 631 void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi_real, 632 BilinearFormIntegrator *bfi_imag, 633 Array<int> &bdr_marker); 634 635 /// Assemble the local matrix 636 void Assemble(int skip_zeros = 1); 637 638 /// Finalizes the matrix initialization. 639 void Finalize(int skip_zeros = 1); 640 641 /// Returns the matrix assembled on the true dofs, i.e. P^t A P. 642 /** The returned matrix has to be deleted by the caller. */ 643 ComplexHypreParMatrix *ParallelAssemble(); 644 645 /// Return the parallel FE space associated with the ParBilinearForm. ParFESpace() const646 ParFiniteElementSpace *ParFESpace() const { return pblfr->ParFESpace(); } 647 648 void FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b, 649 OperatorHandle &A, Vector &X, Vector &B, 650 int copy_interior = 0); 651 652 void FormSystemMatrix(const Array<int> &ess_tdof_list, 653 OperatorHandle &A); 654 655 /** Call this method after solving a linear system constructed using the 656 FormLinearSystem method to recover the solution as a ParGridFunction-size 657 vector in x. Use the same arguments as in the FormLinearSystem call. */ 658 virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x); 659 660 virtual void Update(FiniteElementSpace *nfes = NULL); 661 662 virtual ~ParSesquilinearForm(); 663 }; 664 665 #endif // MFEM_USE_MPI 666 667 } 668 669 #endif // MFEM_COMPLEX_FEM 670