MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
linearform_ext.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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 "linearform.hpp"
13#include "../general/forall.hpp"
14
15namespace mfem
16{
17
19
21{
22 const FiniteElementSpace &fes = *lf->FESpace();
23 MFEM_VERIFY(lf->SupportsDevice(), "Not supported.");
24 MFEM_VERIFY(lf->Size() == fes.GetVSize(), "LinearForm size does not "
25 "match the number of vector dofs!");
26
27 const Array<Array<int>*> &domain_integs_marker = *lf->GetDLFI_Marker();
28 const int mesh_attributes_max = fes.GetMesh()->attributes.Size() ?
29 fes.GetMesh()->attributes.Max() : 0;
30 const Array<LinearFormIntegrator*> &domain_integs = *lf->GetDLFI();
31
32 for (int k = 0; k < domain_integs.Size(); ++k)
33 {
34 // Get the markers for this integrator
35 const Array<int> *domain_integs_marker_k = domain_integs_marker[k];
36
37 // check if there are markers for this integrator
38 const bool has_markers_k = domain_integs_marker_k != nullptr;
39
40 if (has_markers_k)
41 {
42 // Element attribute marker should be of length mesh->attributes
43 MFEM_VERIFY(mesh_attributes_max == domain_integs_marker_k->Size(),
44 "invalid element marker for domain linear form "
45 "integrator #" << k << ", counting from zero");
46 }
47
48 // if there are no markers, just use the whole linear form (1)
49 if (!has_markers_k) { markers.HostReadWrite(); markers = 1; }
50 else
51 {
52 // scan the attributes to set the markers to 0 or 1
53 const int NE = fes.GetNE();
54 const auto attr = attributes.Read();
55 const auto dimk = domain_integs_marker_k->Read();
56 auto markers_w = markers.Write();
57 mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
58 {
59 markers_w[e] = dimk[attr[e]-1] == 1;
60 });
61 }
62
63 // Assemble the linear form
64 b = 0.0;
65 domain_integs[k]->AssembleDevice(fes, markers, b);
66 if (k == 0) { elem_restrict_lex->MultTranspose(b, *lf); }
67 else { elem_restrict_lex->AddMultTranspose(b, *lf); }
68 }
69
70 const Array<Array<int>*> &boundary_integs_marker = lf->boundary_integs_marker;
71 const int bdr_attributes_max = fes.GetMesh()->bdr_attributes.Size() ?
72 fes.GetMesh()->bdr_attributes.Max() : 0;
73 const Array<LinearFormIntegrator*> &boundary_integs = lf->boundary_integs;
74
75 for (int k = 0; k < boundary_integs.Size(); ++k)
76 {
77 // Get the markers for this integrator
78 const Array<int> *boundary_integs_marker_k = boundary_integs_marker[k];
79
80 // check if there are markers for this integrator
81 const bool has_markers_k = boundary_integs_marker_k != nullptr;
82
83 if (has_markers_k)
84 {
85 // Element attribute marker should be of length mesh->attributes
86 MFEM_VERIFY(bdr_attributes_max == boundary_integs_marker_k->Size(),
87 "invalid boundary marker for boundary linear form "
88 "integrator #" << k << ", counting from zero");
89 }
90
91 // if there are no markers, just use the whole linear form (1)
92 if (!has_markers_k) { bdr_markers.HostReadWrite(); bdr_markers = 1; }
93 else
94 {
95 // scan the attributes to set the markers to 0 or 1
96 const int NBE = bdr_attributes.Size();
97 const auto attr = bdr_attributes.Read();
98 const auto attr_markers = boundary_integs_marker_k->Read();
99 auto markers_w = bdr_markers.Write();
100 mfem::forall(NBE, [=] MFEM_HOST_DEVICE (int e)
101 {
102 markers_w[e] = attr_markers[attr[e]-1] == 1;
103 });
104 }
105
106 // Assemble the linear form
107 bdr_b = 0.0;
108 boundary_integs[k]->AssembleDevice(fes, bdr_markers, bdr_b);
109 bdr_restrict_lex->AddMultTranspose(bdr_b, *lf);
110 }
111}
112
114{
115 const FiniteElementSpace &fes = *lf->FESpace();
116 const Mesh &mesh = *fes.GetMesh();
118
119 MFEM_VERIFY(lf->Size() == fes.GetVSize(), "");
120
121 if (lf->domain_integs.Size() > 0)
122 {
123 const int NE = fes.GetNE();
124 markers.SetSize(NE);
125 //markers.UseDevice(true);
126
127 // Gather the attributes on the host from all the elements
128 attributes.SetSize(NE);
129 for (int i = 0; i < NE; ++i) { attributes[i] = mesh.GetAttribute(i); }
130
131 elem_restrict_lex = fes.GetElementRestriction(ordering);
132 MFEM_VERIFY(elem_restrict_lex, "Element restriction not available");
133 b.SetSize(elem_restrict_lex->Height(), Device::GetMemoryType());
134 b.UseDevice(true);
135 }
136
137 if (lf->boundary_integs.Size() > 0)
138 {
139 const int nf_bdr = fes.GetNFbyType(FaceType::Boundary);
140 bdr_markers.SetSize(nf_bdr);
141 // bdr_markers.UseDevice(true);
142
143 // The face restriction will give us "face E-vectors" on the boundary that
144 // are numbered in the order of the faces of mesh. This numbering will be
145 // different than the numbering of the boundary elements. We compute
146 // mappings so that the array `bdr_attributes[i]` gives the boundary
147 // attribute of the `i`th boundary face in the mesh face order.
148 std::unordered_map<int,int> f_to_be;
149 for (int i = 0; i < mesh.GetNBE(); ++i)
150 {
151 const int f = mesh.GetBdrElementFaceIndex(i);
152 f_to_be[f] = i;
153 }
154 MFEM_VERIFY(size_t(nf_bdr) == f_to_be.size(), "Incompatible sizes");
155 bdr_attributes.SetSize(nf_bdr);
156 int f_ind = 0;
157 for (int f = 0; f < mesh.GetNumFaces(); ++f)
158 {
159 if (f_to_be.find(f) != f_to_be.end())
160 {
161 const int be = f_to_be[f];
162 bdr_attributes[f_ind] = mesh.GetBdrAttribute(be);
163 ++f_ind;
164 }
165 }
166
167 bdr_restrict_lex =
168 dynamic_cast<const FaceRestriction*>(
171 MFEM_VERIFY(bdr_restrict_lex, "Face restriction not available");
172 bdr_b.SetSize(bdr_restrict_lex->Height(), Device::GetMemoryType());
173 bdr_b.UseDevice(true);
174 }
175}
176
177} // namespace mfem
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:697
int Size() const
Return the logical size of the array.
Definition array.hpp:144
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:325
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:317
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
Definition array.hpp:337
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:278
void AddMultTranspose(const Vector &x, Vector &y, const real_t a=1.0) const override=0
Add the E-vector degrees of freedom x to the L-vector degrees of freedom y.
Base class for operators that extracts Face degrees of freedom.
virtual void AddMultTranspose(const Vector &x, Vector &y, const real_t a=1.0) const override=0
Add the face degrees of freedom x to the element degrees of freedom y.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:220
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:740
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition fespace.cpp:1336
int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type.
Definition fespace.hpp:757
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:559
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:713
virtual const FaceRestriction * GetFaceRestriction(ElementDofOrdering f_ordering, FaceType, L2FaceValues mul=L2FaceValues::DoubleValued) const
Return an Operator that converts L-vectors to E-vectors on each face.
Definition fespace.cpp:1369
void Update()
Update the linear form extension.
LinearFormExtension(LinearForm *lf)
Create a LinearForm extension of lf.
Vector with associated FE space and LinearFormIntegrators.
FiniteElementSpace * FESpace()
Read+write access to the associated FiniteElementSpace.
virtual bool SupportsDevice() const
Return true if assembly on device is supported, false otherwise.
Array< Array< int > * > boundary_integs_marker
Entries are not owned.
Array< LinearFormIntegrator * > domain_integs
Set of Domain Integrators to be applied.
Array< LinearFormIntegrator * > * GetDLFI()
Access all integrators added with AddDomainIntegrator() which are not DeltaLFIntegrators or they are ...
Array< Array< int > * > * GetDLFI_Marker()
Access all domain markers added with AddDomainIntegrator(). If no marker was specified when the integ...
Array< LinearFormIntegrator * > boundary_integs
Set of Boundary Integrators to be applied.
Mesh data type.
Definition mesh.hpp:56
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:282
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition mesh.cpp:6250
int GetAttribute(int i) const
Return the attribute of element i.
Definition mesh.hpp:1333
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
Definition mesh.hpp:1339
int GetBdrElementFaceIndex(int be_idx) const
Return the local face (codimension-1) index for the given boundary element index.
Definition mesh.hpp:1518
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1229
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:280
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:66
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:93
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition vector.hpp:136
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:538
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
Definition fespace.hpp:75
@ LEXICOGRAPHIC
Lexicographic ordering for tensor-product FiniteElements.
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:754