38 Table face_dof, dof_face;
57 int *I = dof_dof.
GetI();
58 int *J = dof_dof.
GetJ();
113 MFEM_ABORT(
"the assembly level has already been set!");
134 MFEM_ABORT(
"BilinearForm: unknown assembly level");
143 MFEM_WARNING(
"Static condensation not supported for this assembly level");
149 bool symmetric =
false;
150 bool block_diagonal =
false;
167 MFEM_WARNING(
"Hybridization not supported for this assembly level");
198 "invalid matrix A dimensions: "
200 MFEM_ASSERT(A.
Finalized(),
"matrix A must be Finalized");
290 domain_integs[0]->AssembleElementMatrix(fe, *eltrans, elmat);
331 tr = mesh -> GetFaceElementTransformations (i);
335 if (tr->Elem2No >= 0)
359 if (tr->Elem2No >= 0)
373 tr = mesh -> GetBdrFaceTransformations (i);
377 fe1 =
fes -> GetFE (tr -> Elem1No);
477#ifdef MFEM_USE_LEGACY_OPENMP
478 int free_element_matrices = 0;
482 free_element_matrices = 1;
494 "invalid element marker for domain integrator #"
495 << k <<
", counting from zero");
500 MFEM_VERIFY(
fes->
GetNURBSext(),
"Patchwise integration requires a "
501 <<
"NURBS FE space");
507 for (
int i = 0; i <
fes -> GetNE(); i++)
515 elmat_p = &(*element_matrices)(i);
532 if (elmat.
Size() == 0)
542 if (elmat.
Size() == 0)
572 bool vdofsSet =
false;
588 for (
int r=0; r<spmat->
Height(); ++r)
590 spmat->
GetRow(r, cols, srow);
591 for (
int i=0; i<cols.
Size(); ++i)
593 cols[i] =
vdofs[cols[i]];
619 MFEM_ASSERT(bdr_marker.
Size() == bdr_attr_marker.
Size(),
620 "invalid boundary marker for boundary integrator #"
621 << k <<
", counting from zero");
622 for (
int i = 0; i < bdr_attr_marker.
Size(); i++)
624 bdr_attr_marker[i] |= bdr_marker[i];
629 for (
int i = 0; i <
fes -> GetNBE(); i++)
632 if (bdr_attr_marker[bdr_attr-1] == 0) {
continue; }
635 fes -> GetBdrElementVDofs (i,
vdofs, doftrans);
636 eltrans =
fes -> GetBdrElementTransformation (i);
678 for (
int i = 0; i < nfaces; i++)
680 tr = mesh -> GetInteriorFaceTransformations (i);
683 fes -> GetElementVDofs (tr -> Elem1No,
vdofs);
684 fes -> GetElementVDofs (tr -> Elem2No, vdofs2);
689 AssembleFaceMatrix(*
fes->
GetFE(tr->Elem1No),
715 MFEM_ASSERT(bdr_marker.
Size() == bdr_attr_marker.
Size(),
716 "invalid boundary marker for boundary face integrator #"
717 << k <<
", counting from zero");
718 for (
int i = 0; i < bdr_attr_marker.
Size(); i++)
720 bdr_attr_marker[i] |= bdr_marker[i];
724 for (
int i = 0; i <
fes -> GetNBE(); i++)
727 if (bdr_attr_marker[bdr_attr-1] == 0) {
continue; }
729 tr = mesh -> GetBdrFaceTransformations (i);
733 fes -> GetElementVDofs (tr -> Elem1No,
vdofs, doftrans);
734 fe1 =
fes -> GetFE (tr -> Elem1No);
754#ifdef MFEM_USE_LEGACY_OPENMP
755 if (free_element_matrices)
769 MFEM_ASSERT(
mat,
"the BilinearForm is not assembled");
800 "Vector for holding diagonal has wrong size!");
804 MFEM_ASSERT(
mat,
"the BilinearForm is not assembled!");
806 "BilinearForm::ConformingAssemble() is not called!");
813 ext->AssembleDiagonal(diag);
822 ext->AssembleDiagonal(local_diag);
828 Vector &B,
int copy_interior)
838 std::unique_ptr<ConstrainedOperator> A_constrained([&]()
844 MFEM_ASSERT(A_constrained !=
nullptr,
"");
862 A_constrained->EliminateRHS(conf_x, conf_b);
943 const int remove_zeros = 0;
974 const int remove_zeros = 0;
993 ext->RecoverFEMSolution(X,
b, x);
1072#ifdef MFEM_USE_LEGACY_OPENMP
1073 #pragma omp parallel for private(tmp,eltrans)
1075 for (
int i = 0; i < num_elements; i++)
1078 num_dofs_per_el, num_dofs_per_el);
1082 mfem_error(
"BilinearForm::ComputeElementMatrices:"
1083 " all elements must have same number of dofs");
1087 domain_integs[0]->AssembleElementMatrix(fe, eltrans, elmat);
1161 for (
int i = 0; i < vdofs_.
Size(); i++)
1163 int vdof = vdofs_[i];
1166 mat -> EliminateRowCol (vdof,
sol(vdof), rhs, dpolicy);
1170 mat -> EliminateRowCol (-1-vdof,
sol(-1-vdof), rhs, dpolicy);
1184 for (
int i = 0; i < vdofs_.
Size(); i++)
1186 int vdof = vdofs_[i];
1189 mat -> EliminateRowCol (vdof, *
mat_e, dpolicy);
1193 mat -> EliminateRowCol (-1-vdof, *
mat_e, dpolicy);
1202 MFEM_ASSERT(ess_dofs.
Size() ==
height,
"incorrect dof Array size");
1203 MFEM_ASSERT(
sol.Size() ==
height,
"incorrect sol Vector size");
1204 MFEM_ASSERT(rhs.
Size() ==
height,
"incorrect rhs Vector size");
1206 for (
int i = 0; i < ess_dofs.
Size(); i++)
1207 if (ess_dofs[i] < 0)
1209 mat -> EliminateRowCol (i,
sol(i), rhs, dpolicy);
1217 "incorrect dof Array size: " << ess_dofs.
Size() <<
' ' <<
height);
1219 for (
int i = 0; i < ess_dofs.
Size(); i++)
1220 if (ess_dofs[i] < 0)
1222 mat -> EliminateRowCol (i, dpolicy);
1230 "incorrect dof Array size: " << ess_dofs.
Size() <<
' ' <<
height);
1232 for (
int i = 0; i < ess_dofs.
Size(); i++)
1233 if (ess_dofs[i] < 0)
1235 mat -> EliminateRowColDiag (i, value);
1262 ext->AddMult(x, y,
a);
1275 ext->AddMultTranspose(x, y,
a);
1287 ext->MultTranspose(x, y);
1300 if (nfes && nfes !=
fes)
1333 if (
ext) {
ext->Update(); }
1361 :
Matrix(te_fes->GetVSize(), tr_fes->GetVSize())
1375 :
Matrix(te_fes->GetVSize(), tr_fes->GetVSize())
1403 MFEM_ABORT(
"the assembly level has already been set!");
1415 MFEM_ABORT(
"Element assembly not supported yet... stay tuned!");
1422 MFEM_ABORT(
"Matrix-free action not supported yet... stay tuned!");
1426 MFEM_ABORT(
"Unknown assembly level");
1432 return (*
mat)(i, j);
1437 return (*
mat)(i, j);
1451 ext->AddMult(x, y,
a);
1470 ext->AddMultTranspose(x, y,
a);
1482 MFEM_WARNING(
"MixedBilinearForm::Inverse not possible with this "
1504 "MixedBilinearForm::GetBlocks: both trial and test spaces "
1505 "must use Ordering::byNODES!");
1601 "invalid element marker for domain integrator #"
1602 << k <<
", counting from zero");
1607 for (
int i = 0; i <
test_fes -> GetNE(); i++)
1612 eltrans =
test_fes -> GetElementTransformation (i);
1637 bdr_attr_marker = 0;
1642 bdr_attr_marker = 1;
1646 MFEM_ASSERT(bdr_marker.
Size() == bdr_attr_marker.
Size(),
1647 "invalid boundary marker for boundary integrator #"
1648 << k <<
", counting from zero");
1649 for (
int i = 0; i < bdr_attr_marker.
Size(); i++)
1651 bdr_attr_marker[i] |= bdr_marker[i];
1656 for (
int i = 0; i <
test_fes -> GetNBE(); i++)
1659 if (bdr_attr_marker[bdr_attr-1] == 0) {
continue; }
1663 eltrans =
test_fes -> GetBdrElementTransformation (i);
1686 const FiniteElement *trial_fe1, *trial_fe2, *test_fe1, *test_fe2;
1689 for (
int i = 0; i < nfaces; i++)
1712 trial_fe2 = trial_fe1;
1713 test_fe2 = test_fe1;
1730 const FiniteElement *trial_fe1, *trial_fe2, *test_fe1, *test_fe2;
1735 bdr_attr_marker = 0;
1740 bdr_attr_marker = 1;
1744 MFEM_ASSERT(bdr_marker.
Size() == bdr_attr_marker.
Size(),
1745 "invalid boundary marker for boundary face integrator #"
1746 << k <<
", counting from zero");
1747 for (
int i = 0; i < bdr_attr_marker.
Size(); i++)
1749 bdr_attr_marker[i] |= bdr_marker[i];
1754 for (
int i = 0; i <
trial_fes -> GetNBE(); i++)
1757 if (bdr_attr_marker[bdr_attr-1] == 0) {
continue; }
1759 ftr = mesh -> GetBdrFaceTransformations (i);
1769 trial_fe2 = trial_fe1;
1770 test_fe2 = test_fe1;
1793 for (
int i = 0; i < nfaces; i++)
1811 test_fe2 = test_fe1;
1831 bdr_attr_marker = 0;
1836 bdr_attr_marker = 1;
1840 MFEM_ASSERT(bdr_marker.
Size() == bdr_attr_marker.
Size(),
1841 "invalid boundary marker for boundary trace face"
1842 "integrator #" << k <<
", counting from zero");
1843 for (
int i = 0; i < bdr_attr_marker.
Size(); i++)
1845 bdr_attr_marker[i] |= bdr_marker[i];
1849 for (
int i = 0; i <
trial_fes -> GetNBE(); i++)
1852 if (bdr_attr_marker[bdr_attr-1] == 0) {
continue; }
1865 test_fe2 = test_fe1;
1889 "Vector for holding diagonal has wrong size!");
1891 "Vector for holding diagonal has wrong size!");
1897 P_trial->
Mult(D, local_D);
1902 ext->AssembleDiagonal_ADAt(local_D, local_diag);
1907 ext->AssembleDiagonal_ADAt(local_D, diag);
1915 ext->AssembleDiagonal_ADAt(D, local_diag);
1920 ext->AssembleDiagonal_ADAt(D, diag);
1926 MFEM_ABORT(
"Not implemented. Maybe assemble your bilinear form into a "
1927 "matrix and use SparseMatrix functions?");
1935 MFEM_WARNING(
"Conforming assemble not supported for this assembly level!");
1972 domain_integs[0]->AssembleElementMatrix2(trial_fe, test_fe, *eltrans,
1976 domain_integs[k]->AssembleElementMatrix2(trial_fe, test_fe, *eltrans,
1986 elmat.
SetSize(te_dofs, tr_dofs);
1999 boundary_integs[0]->AssembleElementMatrix2(trial_be, test_be, *eltrans,
2003 boundary_integs[k]->AssembleElementMatrix2(trial_be, test_be, *eltrans,
2013 elmat.
SetSize(te_dofs, tr_dofs);
2023 MFEM_ASSERT(ftr,
"No associated face transformations.");
2025 const FiniteElement *trial_fe1, *trial_fe2, *test_fe1, *test_fe2;
2039 trial_fe2 = trial_fe1;
2040 test_fe2 = test_fe1;
2066 elmat.
SetSize(te_dofs, tr_dofs);
2076 MFEM_ASSERT(ftr,
"No associated boundary face.");
2078 const FiniteElement *trial_fe1, *trial_fe2, *test_fe1, *test_fe2;
2085 trial_fe2 = trial_fe1;
2086 test_fe2 = test_fe1;
2106 elmat.
SetSize(te_dofs, tr_dofs);
2116 MFEM_ASSERT(ftr,
"No associated face transformation.");
2131 test_fe2 = test_fe1;
2154 elmat.
SetSize(te_dofs, tr_face_dofs);
2165 MFEM_ASSERT(ftr,
"No associated boundary face.");
2174 test_fe2 = test_fe1;
2194 elmat.
SetSize(te_dofs, tr_face_dofs);
2258 trial_vdofs_marker);
2271 trial_vdofs_marker);
2294 for (i = 0; i <
test_fes -> GetNBE(); i++)
2295 if (bdr_attr_is_ess[
test_fes -> GetBdrAttribute (i)-1])
2297 test_fes -> GetBdrElementVDofs (i, te_vdofs);
2298 for (j = 0; j < te_vdofs.
Size(); j++)
2300 if ( (k = te_vdofs[j]) < 0 )
2304 mat -> EliminateRow (k);
2311 for (
int i=0; i<test_vdofs_.
Size(); ++i)
2325 ext->FormRectangularSystemOperator(trial_tdof_list, test_tdof_list, A);
2334 if (test_P && trial_P)
2368 ext->FormRectangularLinearSystem(trial_tdof_list, test_tdof_list,
2397 if (
ext) {
ext->Update(); }
2425 MFEM_ABORT(
"the assembly level has already been set!");
2435 MFEM_ABORT(
"Element assembly not supported yet... stay tuned!");
2441 MFEM_ABORT(
"Matrix-free action not supported yet... stay tuned!");
2444 MFEM_ABORT(
"Unknown assembly level");
2474 "invalid element marker for domain integrator #"
2475 << k <<
", counting from zero");
2509 for (
int i = 0; i < nfaces; i++)
Dynamic 2D array using row-major layout.
void SetSize(int m, int n)
Set the 2D array size to m x n.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
int Size() const
Return the logical size of the array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Square Operator for imposing essential boundary conditions using only the action, Mult(),...
Data type dense matrix using column-major storage.
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
int Size() const
For backward compatibility define Size to be synonym of Width()
Rank 3 tensor (array of matrices)
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
void SetAssemblyLevel(AssemblyLevel assembly_level)
Set the desired assembly level. The default is AssemblyLevel::FULL.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
const SparseMatrix * GetConformingRestriction() const
The returned SparseMatrix is owned by the FiniteElementSpace.
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th boundary fac...
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
ElementTransformation * GetElementTransformation(int i) const
virtual const SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
static void ListToMarker(const Array< int > &list, int marker_size, Array< int > &marker, int mark_val=-1)
Convert an array of indices (list) to a Boolean marker array where all indices in the list are marked...
const NURBSExtension * GetNURBSext() const
virtual const Operator * GetProlongationMatrix() const
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Ordering::Type GetOrdering() const
Return the ordering method.
ElementTransformation * GetBdrElementTransformation(int i) const
Returns ElementTransformation for the i-th boundary element.
int GetNE() const
Returns number of elements in the mesh.
void GetFaceVDofs(int i, Array< int > &vdofs) const
Returns the indices of the degrees of freedom for the specified face, including the DOFs for the edge...
const FiniteElement * GetFaceElement(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th face in the ...
const SparseMatrix * GetConformingProlongation() const
Mesh * GetMesh() const
Returns the mesh.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
int GetVDim() const
Returns the vector dimension of the finite element space.
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for i'th boundary element. The returned indices are offsets int...
virtual void GetEssentialVDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_vdofs, int component=-1) const
Mark degrees of freedom associated with boundary elements with the specified boundary attributes (mar...
void GetPatchVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom in vdofs for NURBS patch i.
Abstract class for all finite elements.
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Auxiliary class Hybridization, used to implement BilinearForm hybridization.
Abstract data type for matrix inverse.
Abstract data type matrix.
Class used by MFEM to store pointers to host and/or device memory.
virtual FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
int GetAttribute(int i) const
Return the attribute of element i.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
int GetBdrElementFaceIndex(int be_idx) const
Return the local face (codimension-1) index for the given boundary element index.
ElementTransformation * GetFaceTransformation(int FaceNo)
Returns a pointer to the transformation defining the given face element.
FaceElementTransformations * GetBdrFaceTransformations(int BdrElemNo)
Builds the transformation defining the given boundary face.
FaceElementTransformations * GetInteriorFaceTransformations(int FaceNo)
See GetFaceElementTransformations().
Table * GetFaceToElementTable() const
Array< int > attributes
A list of all unique element attributes used by the Mesh.
int GetNP() const
Return the number of patches.
Pointer to an Operator of a specified type.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
int width
Dimension of the input / number of columns in the matrix.
void FormSystemOperator(const Array< int > &ess_tdof_list, Operator *&A)
Return in A a parallel (on truedofs) version of this square operator.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int height
Dimension of the output / number of rows in the matrix.
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.
@ DIAG_ONE
Set the diagonal value to one.
@ DIAG_KEEP
Keep the diagonal value.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
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.
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 ...
Partial assembly extension for DiscreteLinearOperator.
int GetRow(const int row, Array< int > &cols, Vector &srow) const override
Extract all column indices and values from a given row.
void GetDiag(Vector &d) const
Returns the Diagonal of A.
void PartMult(const Array< int > &rows, const Vector &x, Vector &y) const
bool ColumnsAreSorted() const
Returns whether or not the columns are sorted.
void MultTranspose(const Vector &x, Vector &y) const override
Multiply a vector with the transposed matrix. y = At * x.
bool Finalized() const
Returns whether or not CSR format has been finalized.
void SetSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
void AddMultTranspose(const Vector &x, Vector &y, const real_t a=1.0) const override
y += At * x (default) or y += a * At * x
void AddMult(const Vector &x, Vector &y, const real_t a=1.0) const override
y += A * x (default) or y += a * A * x
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
void EliminateRow(int row, const real_t sol, Vector &rhs)
Eliminates a column from the transpose matrix.
void GetBlocks(Array2D< SparseMatrix * > &blocks) const
void AbsMultTranspose(const Vector &x, Vector &y) const override
y = |At| * x, using entry-wise absolute values of the transpose of matrix A
void Finalize(int skip_zeros=1) override
Finalize the matrix initialization, switching the storage format from LIL to CSR.
void EliminateCols(const Array< int > &cols, const Vector *x=NULL, Vector *b=NULL)
Eliminate all columns i for which cols[i] != 0.
int * GetJ()
Return the array J.
void AddRow(const int row, const Array< int > &cols, const Vector &srow)
int * GetI()
Return the array I.
Table stores the connectivity of elements of TYPE I to elements of TYPE II. For example,...
void LoseData()
Releases ownership of and null-ifies the data.
void SortRows()
Sort the column (TYPE II) indices in each row.
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
void SyncMemory(const Vector &v) const
Update the memory location of the vector to match v.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
void SetSubVectorComplement(const Array< int > &dofs, const real_t val)
Set all vector entries NOT in the dofs Array to the given val.
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
const int * ess_tdof_list
void mfem_error(const char *msg)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void TransformDual(const DofTransformation &ran_dof_trans, const DofTransformation &dom_dof_trans, DenseMatrix &elmat)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
AssemblyLevel
Enumeration defining the assembly level for bilinear and nonlinear form classes derived from Operator...
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
bool IsIdentityProlongation(const Operator *P)
void TransformPrimal(const DofTransformation &ran_dof_trans, const DofTransformation &dom_dof_trans, DenseMatrix &elmat)
@ NATIVE
Native ordering as defined by the FiniteElement.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
SparseMatrix * TransposeMult(const SparseMatrix &A, const SparseMatrix &B)
C = A^T B.
real_t p(const Vector &x, real_t t)
real_t sol(const Vector &x)