MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
pml.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#ifndef MFEM_DPG_PML
13#define MFEM_DPG_PML
14
15#include "pml.hpp"
16
17namespace mfem
18{
19
21 : mesh(mesh_), length(length_)
22{
23 dim = mesh->Dimension();
24 SetBoundaries();
25}
26
27void CartesianPML::SetBoundaries()
28{
29 comp_dom_bdr.SetSize(dim, 2);
30 dom_bdr.SetSize(dim, 2);
31 // initialize
32 for (int i = 0; i < dim; i++)
33 {
34 dom_bdr(i, 0) = infinity();
35 dom_bdr(i, 1) = -infinity();
36 }
37
38 for (int i = 0; i < mesh->GetNBE(); i++)
39 {
40 Array<int> bdr_vertices;
41 mesh->GetBdrElementVertices(i, bdr_vertices);
42 for (int j = 0; j < bdr_vertices.Size(); j++)
43 {
44 for (int k = 0; k < dim; k++)
45 {
46 dom_bdr(k, 0) = std::min(dom_bdr(k, 0), mesh->GetVertex(bdr_vertices[j])[k]);
47 dom_bdr(k, 1) = std::max(dom_bdr(k, 1), mesh->GetVertex(bdr_vertices[j])[k]);
48 }
49 }
50 }
51
52#ifdef MFEM_USE_MPI
53 ParMesh * pmesh = dynamic_cast<ParMesh *>(mesh);
54 if (pmesh)
55 {
56 for (int d=0; d<dim; d++)
57 {
58 MPI_Allreduce(MPI_IN_PLACE, &dom_bdr(d,0), 1,
59 MPITypeMap<real_t>::mpi_type, MPI_MIN,pmesh->GetComm());
60 MPI_Allreduce(MPI_IN_PLACE, &dom_bdr(d,1), 1,
61 MPITypeMap<real_t>::mpi_type, MPI_MAX, pmesh->GetComm());
62 }
63 }
64#endif
65
66 for (int i = 0; i < dim; i++)
67 {
68 comp_dom_bdr(i, 0) = dom_bdr(i, 0) + length(i, 0);
69 comp_dom_bdr(i, 1) = dom_bdr(i, 1) - length(i, 1);
70 }
71}
72
74 Array<int> * attrPML)
75{
76 int nrelem = mesh_->GetNE();
77 elems.SetSize(nrelem);
78
79 for (int i = 0; i < nrelem; ++i)
80 {
81 elems[i] = 1;
82 bool in_pml = false;
83 Element *el = mesh_->GetElement(i);
84 Array<int> vertices;
85 // Initialize Attribute
86 el->SetAttribute(1);
87 el->GetVertices(vertices);
88 int nrvert = vertices.Size();
89 // Check if any vertex is in the pml
90 for (int iv = 0; iv < nrvert; ++iv)
91 {
92 int vert_idx = vertices[iv];
93 real_t *coords = mesh_->GetVertex(vert_idx);
94 for (int comp = 0; comp < dim; ++comp)
95 {
96 if (coords[comp] > comp_dom_bdr(comp, 1) ||
97 coords[comp] < comp_dom_bdr(comp, 0))
98 {
99 in_pml = true;
100 break;
101 }
102 }
103 }
104 if (in_pml)
105 {
106 elems[i] = 0;
107 el->SetAttribute(2);
108 }
109 }
110 mesh_->SetAttributes();
111
112 if (mesh_->attributes.Size())
113 {
114 if (attrNonPML)
115 {
116 attrNonPML->SetSize(mesh_->attributes.Max());
117 *attrNonPML = 0; (*attrNonPML)[0] = 1;
118
119 }
120 if (attrPML)
121 {
122 attrPML->SetSize(mesh_->attributes.Max());
123 *attrPML = 0;
124 if (mesh_->attributes.Max()>1)
125 {
126 (*attrPML)[1]=1;
127 }
128 }
129 }
130
131}
132
134 std::vector<std::complex<real_t>> &dxs)
135{
136 std::complex<real_t> zi = std::complex<real_t>(0., 1.);
137
138 real_t n = 2.0;
139 real_t c = 5.0;
140 real_t coeff;
141 real_t k = omega * sqrt(epsilon * mu);
142 // Stretch in each direction independently
143 for (int i = 0; i < dim; ++i)
144 {
145 dxs[i] = 1.0;
146 if (x(i) >= comp_dom_bdr(i, 1))
147 {
148 coeff = n * c / k / pow(length(i, 1), n);
149 dxs[i] = real_t(1.0) + zi * real_t(coeff * std::abs(pow(x(i) - comp_dom_bdr(i,
150 1), n - 1.0)));
151 }
152 if (x(i) <= comp_dom_bdr(i, 0))
153 {
154 coeff = n * c / k / pow(length(i, 0), n);
155 dxs[i] = real_t(1.0) + zi * real_t(coeff * std::abs(pow(x(i) - comp_dom_bdr(i,
156 0), n - 1.0)));
157 }
158 }
159}
160
161// acoustics UW PML coefficients functions
162// |J|
164{
165 int dim = pml->dim;
166 std::vector<std::complex<real_t>> dxs(dim);
167 std::complex<real_t> det(1.0,0.0);
168 pml->StretchFunction(x, dxs);
169 for (int i=0; i<dim; ++i) { det *= dxs[i]; }
170 return det.real();
171}
172
174{
175 int dim = pml->dim;
176 std::vector<std::complex<real_t>> dxs(dim);
177 std::complex<real_t> det(1.0,0.0);
178 pml->StretchFunction(x, dxs);
179 for (int i=0; i<dim; ++i) { det *= dxs[i]; }
180 return det.imag();
181}
182
184{
185 int dim = pml->dim;
186 std::vector<std::complex<real_t>> dxs(dim);
187 std::complex<real_t> det(1.0,0.0);
188 pml->StretchFunction(x, dxs);
189 for (int i=0; i<dim; ++i) { det *= dxs[i]; }
190 return det.imag()*det.imag() + det.real()*det.real();
191}
192
193// J^T J / |J|
195 DenseMatrix & M)
196{
197 int dim = pml->dim;
198 std::vector<std::complex<real_t>> dxs(dim);
199 std::complex<real_t> det(1.0,0.0);
200 pml->StretchFunction(x, dxs);
201 for (int i = 0; i<dim; ++i) { det *= dxs[i]; }
202
203 M=0.0;
204 for (int i = 0; i<dim; ++i)
205 {
206 M(i,i) = (pow(dxs[i], real_t(2))/det).real();
207 }
208}
209
211 DenseMatrix & M)
212{
213 int dim = pml->dim;
214 std::vector<std::complex<real_t>> dxs(dim);
215 std::complex<real_t> det = 1.0;
216 pml->StretchFunction(x, dxs);
217 for (int i = 0; i<dim; ++i) { det *= dxs[i]; }
218
219 M=0.0;
220 for (int i = 0; i<dim; ++i)
221 {
222 M(i,i) = (pow(dxs[i], real_t(2))/det).imag();
223 }
224}
225
227 DenseMatrix & M)
228{
229 int dim = pml->dim;
230 std::vector<std::complex<real_t>> dxs(dim);
231 std::complex<real_t> det = 1.0;
232 pml->StretchFunction(x, dxs);
233 for (int i = 0; i<dim; ++i) { det *= dxs[i]; }
234
235 M=0.0;
236 for (int i = 0; i<dim; ++i)
237 {
238 std::complex<real_t> a = pow(dxs[i], real_t(2))/det;
239 M(i,i) = a.imag() * a.imag() + a.real() * a.real();
240 }
241}
242
243
244// Maxwell PML coefficients
246 DenseMatrix &M)
247{
248 int dim = pml->dim;
249 std::vector<std::complex<real_t>> dxs(dim);
250 std::complex<real_t> det(1.0, 0.0);
251 pml->StretchFunction(x, dxs);
252
253 for (int i = 0; i < dim; ++i) { det *= dxs[i]; }
254
255 M = 0.0;
256 for (int i = 0; i < dim; ++i)
257 {
258 M(i, i) = (det / pow(dxs[i], real_t(2))).real();
259 }
260}
261
263 DenseMatrix &M)
264{
265 int dim = pml->dim;
266 std::vector<std::complex<real_t>> dxs(dim);
267 std::complex<real_t> det = 1.0;
268 pml->StretchFunction(x, dxs);
269
270 for (int i = 0; i < dim; ++i) { det *= dxs[i]; }
271
272 M = 0.0;
273 for (int i = 0; i < dim; ++i)
274 {
275 M(i, i) = (det / pow(dxs[i], real_t(2))).imag();
276 }
277}
278
280 DenseMatrix &M)
281{
282 int dim = pml->dim;
283 std::vector<std::complex<real_t>> dxs(dim);
284 std::complex<real_t> det = 1.0;
285 pml->StretchFunction(x, dxs);
286
287 for (int i = 0; i < dim; ++i) { det *= dxs[i]; }
288
289 M = 0.0;
290 for (int i = 0; i < dim; ++i)
291 {
292 std::complex<real_t> a = det / pow(dxs[i], real_t(2));
293 M(i, i) = a.real()*a.real() + a.imag()*a.imag();
294 }
295}
296
297} // namespace mfem
298
299#endif // MFEM_DPG_PML
Dynamic 2D array using row-major layout.
Definition array.hpp:459
void SetSize(int m, int n)
Set the 2D array size to m x n.
Definition array.hpp:474
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:869
int Size() const
Return the logical size of the array.
Definition array.hpp:192
Class for setting up a simple Cartesian PML region.
Definition pml.hpp:19
void SetAttributes(Mesh *mesh_, Array< int > *attrNonPML=nullptr, Array< int > *attrPML=nullptr)
Mark element in the PML region.
Definition pml.cpp:73
void StretchFunction(const Vector &x, std::vector< std::complex< real_t > > &dxs)
PML complex stretching function.
Definition pml.cpp:133
CartesianPML(Mesh *mesh_, const Array2D< real_t > &length_)
Definition pml.cpp:20
real_t epsilon
Definition pml.hpp:49
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
Abstract data type element.
Definition element.hpp:29
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
void SetAttribute(const int attr)
Set element's attribute.
Definition element.hpp:61
Mesh data type.
Definition mesh.hpp:67
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
Definition mesh.hpp:1626
const Element * GetElement(int i) const
Return pointer to the i'th element object.
Definition mesh.hpp:1447
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
virtual void SetAttributes(bool elem_attrs_changed=true, bool bdr_face_attrs_changed=true)
Determine the sets of unique attribute values in domain if elem_attrs_changed and boundary elements i...
Definition mesh.cpp:2016
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1393
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:307
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Definition mesh.hpp:1429
Vector data type.
Definition vector.hpp:82
int dim
Definition ex24.cpp:53
real_t a
Definition lissajous.cpp:41
real_t detJ_r_function(const Vector &x, CartesianPML *pml)
PML stretching functions: See https://doi.org/10.1006/jcph.1994.1159.
Definition pml.cpp:163
void Jt_J_detJinv_r_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:194
void abs_Jt_J_detJinv_2_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:226
void detJ_Jt_J_inv_r_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:245
void Jt_J_detJinv_i_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:210
float real_t
Definition config.hpp:46
real_t abs_detJ_2_function(const Vector &x, CartesianPML *pml)
Definition pml.cpp:183
real_t detJ_i_function(const Vector &x, CartesianPML *pml)
Definition pml.cpp:173
void abs_detJ_Jt_J_inv_2_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:279
constexpr real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
void detJ_Jt_J_inv_i_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:262