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