1
- # HELMHOLTZ SOLVER WITH AUTO-GENERATING PML
2
- #
3
- # Copyright (C) 2022-2023 Antonio Baiano Svizzero, Undabit
4
- # www.undabit.com
5
-
6
1
import numpy as np
7
2
import ufl
8
3
from dolfinx import geometry
9
- from dolfinx .fem import Function , FunctionSpace , assemble_scalar , dirichletbc , locate_dofs_topological , form , Constant , VectorFunctionSpace , TensorFunctionSpace , Expression
4
+ from dolfinx .fem import Function , functionspace , assemble_scalar , form
10
5
from dolfinx .fem .petsc import LinearProblem
11
- from dolfinx .io import XDMFFile , gmshio
12
- from dolfinx .mesh import create_unit_square , meshtags
13
- from ufl import dx , grad , inner , outer , dot , ds , Measure , as_matrix , as_tensor , inv , det , log
6
+ from dolfinx .io import VTXWriter
7
+ from dolfinx .mesh import create_submesh
8
+ from ufl import dx , grad , inner , Measure
14
9
from mpi4py import MPI
15
10
from petsc4py import PETSc
16
11
import time
17
12
from autogen_PML import PML_Functions
18
- from ufl . algorithms . compute_form_data import estimate_total_polynomial_degree
13
+
19
14
20
15
# The code will be executed in frequency-multiprocessing mode:
21
16
# the entire domain will be assigned to one process for every frequency.
22
17
# Set the number of processes to use in parallel:
23
- n_processes = 4
18
+ n_processes = 2
24
19
25
20
#frequency range definition
26
- f_axis = np .arange (100 , 3005 , 100 )
21
+ f_axis = np .arange (100 , 3000 , 100 )
27
22
28
23
#Mic position definition
29
24
mic = np .array ([0.05 , 0.03 , 0.03 ])
44
39
mesh_name_prefix = CAD_name .rpartition ('.' )[0 ]
45
40
46
41
# PML
47
- Num_layers = 8 # number of PML elements layers
48
- d_PML = 0.08 # total thickness of the PML layer
49
- mesh_size_max = 0.008 # the mesh will be created entirely in gmsh. this sets its maximum
42
+ Num_layers = 4 # number of PML elements layers
43
+ d_PML = 0.02 # total thickness of the PML layer
44
+ mesh_size_max = 0.007 # the mesh will be created entirely in gmsh. this sets its maximum
50
45
# size
51
46
# PML_surfaces = [4,6] # vector of tags, identifying the surfaces from which the PML
52
47
# layer gets automatically extruded. Comment this line to extrude
53
48
# all the 2D surfaces of the system
54
49
55
50
56
51
# PML Functions needed for the variational formulation
57
- LAMBDA_PML , detJ , omega , k0 , msh , cell_tags , facet_tags = PML_Functions (CAD_name , mesh_size_max , Num_layers , d_PML )
52
+ LAMBDA_PML , detJ , omega , k0 , msh , cell_tags , facet_tags = PML_Functions (CAD_name , mesh_size_max , Num_layers , d_PML , elem_degree = deg )
58
53
59
54
# Source amplitude
60
55
Q = 0.0001
65
60
Sz = 0.1
66
61
67
62
# Test and trial function space
68
- V = FunctionSpace (msh , ("CG" , deg ))
63
+ V = functionspace (msh , ("CG" , deg ))
69
64
u = ufl .TrialFunction (V )
70
65
v = ufl .TestFunction (V )
71
66
f = Function (V )
72
67
73
68
#Narrow normalized gauss distribution (quasi-monopole)
74
- alfa = mesh_size_max / 6
69
+ alfa = mesh_size_max * 2
75
70
delta_tmp = Function (V )
76
71
delta_tmp .interpolate (lambda x : 1 / (np .abs (alfa )* np .sqrt (np .pi ))* np .exp (- (((x [0 ]- Sx )** 2 + (x [1 ]- Sy )** 2 + (x [2 ]- Sz )** 2 )/ (alfa ** 2 ))))
77
72
int_delta_tmp = assemble_scalar (form (delta_tmp * dx ))
97
92
# creation of the submesh without the PML on which the soultion is projected
98
93
i_INT = cell_tags .indices [(cell_tags .values == 1 )] #
99
94
msh_INT , entity_map , vertex_map , geom_map = create_submesh (msh , msh .topology .dim , i_INT )
100
- V_INT = FunctionSpace (msh_INT , ("CG" , deg ))
95
+ V_INT = functionspace (msh_INT , ("CG" , deg ))
101
96
uh_NOPML = Function (V_INT )
102
97
103
98
# spectrum initialization
@@ -116,27 +111,26 @@ def frequency_loop(nf):
116
111
omega .value = f_axis [nf ]* 2 * np .pi
117
112
k0 .value = 2 * np .pi * f_axis [nf ]/ c0
118
113
problem .solve ()
119
-
114
+
115
+ uh_NOPML .interpolate (uh )
116
+
120
117
# Export field for multiple of 100 Hz frequencies
121
- # uh_NOPML.interpolate(uh)
122
- # if freq%100 == 0:
123
- # with XDMFFile(msh.comm,"Solution_" + str(freq) + "Hz.xdmf", "w") as xdmf:
124
- # xdmf.write_mesh(msh)
125
- # xdmf.write_function(uh)
126
- # with XDMFFile(msh_INT.comm,"Solution_" + str(freq) + "Hz_NOPML.xdmf", "w") as xdmf:
127
- # xdmf.write_mesh(msh_INT)
128
- # xdmf.write_function(uh_NOPML)
118
+ if freq % 100 == 0 :
119
+ with VTXWriter (msh .comm , "fields/pressure_" + str (np .round (f_axis [nf ])) + ".bp" , [uh ]) as vtx :
120
+ vtx .write (0.0 )
121
+ with VTXWriter (msh .comm , "fields/pressure_" + str (np .round (f_axis [nf ])) + "_NOPML.bp" , [uh_NOPML ]) as vtx :
122
+ vtx .write (0.0 )
129
123
130
124
# Microphone pressure at specified point evaluation
131
125
points = np .zeros ((3 ,1 ))
132
126
points [0 ][0 ] = mic [0 ]
133
127
points [1 ][0 ] = mic [1 ]
134
128
points [2 ][0 ] = mic [2 ]
135
- bb_tree = geometry .BoundingBoxTree (msh , msh .topology .dim )
129
+ bb_tree_ = geometry .bb_tree (msh , msh .topology .dim ) #bb_tree è una funzione, non usarla come nome.
136
130
cells = []
137
131
points_on_proc = []
138
132
# Find cells whose bounding-box collide with the the points
139
- cell_candidates = geometry .compute_collisions ( bb_tree , points .T )
133
+ cell_candidates = geometry .compute_collisions_points ( bb_tree_ , points .T )
140
134
# Choose one of the cells that contains the point
141
135
colliding_cells = geometry .compute_colliding_cells (msh , cell_candidates , points .T )
142
136
for i , point in enumerate (points .T ):
0 commit comments