1
2 """Operators modeling diffusive phenomena."""
3
4 from __future__ import division
5
6 __copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
7
8 __license__ = """
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see U{http://www.gnu.org/licenses/}.
21 """
22
23
24
25 import numpy
26 import numpy.linalg as la
27
28 import hedge.data
29 from hedge.models import TimeDependentOperator
30
31
32
33
39 self.dimensions = dimensions
40 assert isinstance(dimensions, int)
41
42 self.coeff = coeff
43 self.ldg = ldg
44
45 self.dirichlet_bc = dirichlet_bc
46 self.dirichlet_tag = dirichlet_tag
47 self.neumann_bc = neumann_bc
48 self.neumann_tag = neumann_tag
49
50
52 class FluxSet: pass
53 fs = FluxSet()
54
55 from hedge.flux import FluxVectorPlaceholder, make_normal
56
57
58
59
60
61
62
63
64
65 dim = self.dimensions
66 vec = FluxVectorPlaceholder(1+dim)
67 fs.u = u = vec[0]
68 fs.v = v = vec[1:]
69 normal = fs.normal = make_normal(dim)
70
71
72 fs.flux_u = u.avg*normal
73 fs.flux_v = numpy.dot(v.avg, normal)
74
75
76
77 fs.flux_u_dbdry = fs.flux_u
78 fs.flux_u_nbdry = fs.flux_u
79
80 fs.flux_v_dbdry = fs.flux_v
81 fs.flux_v_nbdry = fs.flux_v
82
83 if ldg:
84 ldg_beta = numpy.ones((dim,))
85
86 fs.flux_u = fs.flux_u - (u.int-u.ext)*0.5*ldg_beta
87 fs.flux_v = fs.flux_v + numpy.dot((v.int-v.ext)*0.5, ldg_beta)
88
89 return fs
90
106
107
109 from hedge.optemplate import Field, pair_with_boundary, \
110 InverseMassOperator, make_stiffness, get_flux_operator
111
112 stiff = make_stiffness(self.dimensions)
113
114 u = Field("u")
115 sqrt_coeff_u = Field("sqrt_coeff_u")
116 dir_bc_u = Field("dir_bc_u")
117 neu_bc_u = Field("neu_bc_u")
118
119 fs = self.get_strong_flux_set(self.ldg)
120 flux_u = get_flux_operator(fs.flux_u)
121 flux_u_dbdry = get_flux_operator(fs.flux_u_dbdry)
122 flux_u_nbdry = get_flux_operator(fs.flux_u_nbdry)
123
124 return InverseMassOperator() * (
125 stiff * u
126 - flux_u*sqrt_coeff_u
127 - flux_u_dbdry*pair_with_boundary(sqrt_coeff_u, dir_bc_u, self.dirichlet_tag)
128 - flux_u_nbdry*pair_with_boundary(sqrt_coeff_u, neu_bc_u, self.neumann_tag)
129 )
130
132 from hedge.optemplate import make_vector_field, pair_with_boundary, \
133 InverseMassOperator, get_flux_operator, make_stiffness
134
135 stiff = make_stiffness(self.dimensions)
136
137 d = self.dimensions
138 w = make_vector_field("w", 1+d)
139 v = w[1:]
140
141 dir_bc_w = make_vector_field("dir_bc_w", 1+d)
142 neu_bc_w = make_vector_field("neu_bc_w", 1+d)
143
144 fs = self.get_strong_flux_set(self.ldg)
145 flux_v = get_flux_operator(fs.flux_v)
146 flux_v_dbdry = get_flux_operator(fs.flux_v_dbdry)
147 flux_v_nbdry = get_flux_operator(fs.flux_v_nbdry)
148
149 return InverseMassOperator() * (
150 numpy.dot(stiff, v)
151 - flux_v * w
152 - flux_v_dbdry * pair_with_boundary(w, dir_bc_w, self.dirichlet_tag)
153 - flux_v_nbdry * pair_with_boundary(w, neu_bc_w, self.neumann_tag)
154 )
155
156
157 - def bind(self, discr):
158 from hedge.mesh import check_bc_coverage
159 check_bc_coverage(discr.mesh, [self.dirichlet_tag, self.neumann_tag])
160
161 return self.BoundHeatOperator(self, discr)
162
179
181 hop = self.heat_op
182
183 return (
184 -self.discr.boundarize_volume_field(sqrt_coeff_u, hop.dirichlet_tag)
185 +2*self.dir_sqrt_coeff*hop.dirichlet_bc.boundary_interpolant(
186 t, self.discr, hop.dirichlet_tag)
187 )
188
193
198
209
211 from hedge.tools import join_fields
212
213 hop = self.heat_op
214
215 dtag = hop.dirichlet_tag
216 ntag = hop.neumann_tag
217
218 sqrt_coeff_u = self.sqrt_coeff * u
219
220 dir_bc_u = self.dirichlet_bc_u(t, sqrt_coeff_u)
221 neu_bc_u = self.neumann_bc_u(t, sqrt_coeff_u)
222
223 v = self.grad_c(
224 u=u, sqrt_coeff_u=sqrt_coeff_u,
225 dir_bc_u=dir_bc_u, neu_bc_u=neu_bc_u)
226
227 from hedge.tools import ptwise_mul
228 sqrt_coeff_v = ptwise_mul(self.sqrt_coeff, v)
229
230 dir_bc_v = self.dirichlet_bc_v(t, sqrt_coeff_v)
231 neu_bc_v = self.neumann_bc_v(t, sqrt_coeff_v)
232
233 w = join_fields(sqrt_coeff_u, sqrt_coeff_v)
234 dir_bc_w = join_fields(dir_bc_u, dir_bc_v)
235 neu_bc_w = join_fields(neu_bc_u, neu_bc_v)
236
237 return self.div_c(w=w, dir_bc_w=dir_bc_w, neu_bc_w=neu_bc_w)
238