MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
linearform_ext.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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_face_attributes->Size();
97 const auto attr = bdr_face_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] =
103 attr[e] > 0 ? (attr_markers[attr[e] - 1] == 1) : false;
104 });
105 }
106
107 // Assemble the linear form
108 bdr_b = 0.0;
109 boundary_integs[k]->AssembleDevice(fes, bdr_markers, bdr_b);
110 bdr_restrict_lex->AddMultTranspose(bdr_b, *lf);
111 }
112}
113
115{
116 const FiniteElementSpace &fes = *lf->FESpace();
117 const Mesh &mesh = *fes.GetMesh();
119
120 MFEM_VERIFY(lf->Size() == fes.GetVSize(), "");
121
122 if (lf->domain_integs.Size() > 0)
123 {
124 const int NE = fes.GetNE();
125 markers.SetSize(NE);
126 //markers.UseDevice(true);
127
128 // Gather the attributes on the host from all the elements
129 attributes = &mesh.GetElementAttributes();
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 bdr_face_attributes = &mesh.GetBdrFaceAttributes();
140
141 const int nf_bdr = bdr_face_attributes->Size();
142 bdr_markers.SetSize(nf_bdr);
143 // bdr_markers.UseDevice(true);
144
145 bdr_restrict_lex =
146 dynamic_cast<const FaceRestriction*>(
149 MFEM_VERIFY(bdr_restrict_lex, "Face restriction not available");
150 bdr_b.SetSize(bdr_restrict_lex->Height(), Device::GetMemoryType());
151 bdr_b.UseDevice(true);
152 }
153}
154
155} // namespace mfem
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:69
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:840
int Size() const
Return the logical size of the array.
Definition array.hpp:166
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:389
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:381
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
Definition array.hpp:401
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:281
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.
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:208
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:869
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition fespace.cpp:1480
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:644
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:826
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:1513
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:65
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:304
const Array< int > & GetElementAttributes() const
Returns the attributes for all elements in this mesh. The i'th entry of the array is the attribute of...
Definition mesh.cpp:965
const Array< int > & GetBdrFaceAttributes() const
Returns the attributes for all boundary elements in this mesh.
Definition mesh.cpp:925
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:302
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:100
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:584
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
Definition fespace.hpp:47
void forall(int N, lambda &&body)
Definition forall.hpp:839