-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpyop2_adv_diff.py
183 lines (138 loc) · 5.24 KB
/
pyop2_adv_diff.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
"""
This demo solves an advection-diffusion equation on a domain read in from a
triangle file. It requires the pyop2 branch of ffc, which can be obtained
with:
bzr branch lp:~mapdes/ffc/pyop2
This may also depend on development trunk versions of other FEniCS programs.
"""
import numpy as np
from benchrun import clock
from pyop2 import op2, utils
from pyop2.profiling import tic, toc, summary, reset
from pyop2.ffc_interface import compile_form
from triangle_reader import read_triangle
from ufl import *
def run(diffusivity, current_time, dt, endtime, **kwargs):
op2.init(**kwargs)
# Set up finite element problem
T = FiniteElement("Lagrange", "triangle", 1)
V = VectorElement("Lagrange", "triangle", 1)
p=TrialFunction(T)
q=TestFunction(T)
t=Coefficient(T)
u=Coefficient(V)
diffusivity = 0.1
M=p*q*dx
adv_rhs = (q*t+dt*dot(grad(q),u)*t)*dx
d=-dt*diffusivity*dot(grad(q),grad(p))*dx
diff_matrix=M-0.5*d
diff_rhs=action(M+0.5*d,t)
# Generate code for mass and rhs assembly.
mass = compile_form(M, "mass")[0]
adv_rhs = compile_form(adv_rhs, "adv_rhs")[0]
diff_matrix = compile_form(diff_matrix, "diff_matrix")[0]
diff_rhs = compile_form(diff_rhs, "diff_rhs")[0]
# Set up simulation data structures
valuetype=np.float64
nodes, coords, elements, elem_node = read_triangle(kwargs['mesh'])
num_nodes = nodes.size
sparsity = op2.Sparsity((elem_node, elem_node), 1, "sparsity")
mat = op2.Mat(sparsity, valuetype, "mat")
tracer_vals = np.asarray([0.0]*num_nodes, dtype=valuetype)
tracer = op2.Dat(nodes, 1, tracer_vals, valuetype, "tracer")
b_vals = np.asarray([0.0]*num_nodes, dtype=valuetype)
b = op2.Dat(nodes, 1, b_vals, valuetype, "b")
velocity_vals = np.asarray([1.0, 0.0]*num_nodes, dtype=valuetype)
velocity = op2.Dat(nodes, 2, velocity_vals, valuetype, "velocity")
# Set initial condition
i_cond_code="""
void i_cond(double *c, double *t)
{
double i_t = 0.01; // Initial time
double A = 0.1; // Normalisation
double D = 0.1; // Diffusivity
double pi = 3.141459265358979;
double x = c[0]-0.5;
double y = c[1]-0.5;
double r = sqrt(x*x+y*y);
if (r<0.25)
*t = A*(exp((-(r*r))/(4*D*i_t))/(4*pi*D*i_t));
else
*t = 0.0;
}
"""
i_cond = op2.Kernel(i_cond_code, "i_cond")
op2.par_loop(i_cond, nodes,
coords(op2.IdentityMap, op2.READ),
tracer(op2.IdentityMap, op2.WRITE))
zero_dat_code="""
void zero_dat(double *dat)
{
*dat = 0.0;
}
"""
zero_dat = op2.Kernel(zero_dat_code, "zero_dat")
# Assemble and solve
have_advection = True
have_diffusion = True
def timestep_iteration():
# Advection
if have_advection:
tic('advection')
tic('assembly')
mat.zero()
op2.par_loop(mass, elements(3,3),
mat((elem_node[op2.i[0]], elem_node[op2.i[1]]), op2.INC),
coords(elem_node, op2.READ))
op2.par_loop(zero_dat, nodes,
b(op2.IdentityMap, op2.WRITE))
op2.par_loop(adv_rhs, elements(3),
b(elem_node[op2.i[0]], op2.INC),
coords(elem_node, op2.READ),
tracer(elem_node, op2.READ),
velocity(elem_node, op2.READ))
toc('assembly')
tic('solve')
op2.solve(mat, tracer, b)
toc('solve')
toc('advection')
# Diffusion
if have_diffusion:
tic('diffusion')
tic('assembly')
mat.zero()
op2.par_loop(diff_matrix, elements(3,3),
mat((elem_node[op2.i[0]], elem_node[op2.i[1]]), op2.INC),
coords(elem_node, op2.READ))
op2.par_loop(zero_dat, nodes,
b(op2.IdentityMap, op2.WRITE))
op2.par_loop(diff_rhs, elements(3),
b(elem_node[op2.i[0]], op2.INC),
coords(elem_node, op2.READ),
tracer(elem_node, op2.READ))
toc('assembly')
tic('solve')
op2.solve(mat, tracer, b)
toc('solve')
toc('diffusion')
# Perform 1 iteration to warm up plan cache then reset initial condition
timestep_iteration()
op2.par_loop(i_cond, nodes,
coords(op2.IdentityMap, op2.READ),
tracer(op2.IdentityMap, op2.WRITE))
reset()
# Timed iteration
t1 = clock()
while current_time < endtime:
timestep_iteration()
current_time += dt
runtime = clock() - t1
print "/fluidity :: %f" % runtime
summary('profile_pyop2_%s_%s.csv' % (opt['mesh'].split('/')[-1], opt['backend']))
if __name__ == '__main__':
from parameters import *
parser = utils.parser(group=True, description="PyOP2 P1 advection-diffusion demo")
parser.add_argument('-m', '--mesh',
help='Base name of triangle mesh (excluding the .ele or .node extension)')
opt = vars(parser.parse_args())
run(diffusivity, current_time, dt, endtime, **opt)