-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathnonuniform.py
143 lines (93 loc) · 3.09 KB
/
nonuniform.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
"""
Example of using a nonuniform grid for selectively resolving portions
of the computational domain
Distribute n grid points on the interval [0,1] so that the density of nodes
is higher at a set of m locations xi[0],...,xi[m-1]
Test the grid clustering method on the boundary value problem
-(p(x)u')' = 1, u(0)=u(1)=0
where p(x) = 1.001+cos(4*pi*x)
so that u varies rapidly in neighborhoods of the points where p(x) is small
"""
import numpy as np
import matplotlib.pyplot as plt
import dolfin as df
def update(q,y,xj,g):
nj = len(xi)
# Nonnormalized mapping function
phi_hat = lambda q: sum([0.5+np.arctan((q-xj[j])/g[j])/np.pi
for j in range(nj)])
# Scaling for normalization
scale = 1/(phi_hat(1)-phi_hat(0))
# Normalized mapping function
phi = scale*(phi_hat(q)-phi_hat(0))
# Derivative of normalized mapping function
phi_x = scale*sum([g[j]/(np.pi*((q-xj[j])**2+g[j]**2))
for j in range(nj)])
# Newton update
dx = (y-phi)/phi_x
return dx
def compute_grid(n,xi,g,nsteps,csteps):
# Uniform grid points
xu = np.linspace(0,1,n)
# Clustered grid points (initial guess)
x = np.linspace(0,1,n)
t = [float(i+1)/csteps for i in range(csteps)]
g0 = np.ones(len(xi))
for l in range(csteps):
gt = t[l]*g + (1-t[l])*g0
for k in range(nsteps):
dx = update(x,xu,xi,gt)
x[1:-1] += dx[1:-1]
return x
# Boundaries
class BoundaryPoint(df.SubDomain):
def __init__(self,bpt):
df.SubDomain.__init__(self)
self.bpt = bpt
def inside(self,x,on_boundary):
return df.near(x[0],self.bpt)
if __name__ == '__main__':
# Number of grid points
n = 200
# Create FEniCS mesh
mesh = df.IntervalMesh(n-1,0,1)
# Clustering locations
xi = np.array((0.25,0.75))
# Number of junctions
ni = len(xi)
# Set node clustering factors (smaller means more clustering)
g = np.array((0.02,0.02))
# Compute clustered grid
x = compute_grid(n,xi,g,3,100)
# Modify mesh to use clustered grid
mesh.coordinates()[:] = np.reshape(x,(n,1))
# Set up function space
V = df.FunctionSpace(mesh,"CG",1)
u = df.TrialFunction(V)
v = df.TestFunction(V)
ux = u.dx(0)
vx = v.dx(0)
# Set up homogeneous Dirichlet boundary conditions
left = BoundaryPoint(0)
right = BoundaryPoint(1)
boundaries = df.FacetFunction("size_t",mesh)
left.mark(boundaries,0)
right.mark(boundaries,1)
bc = [df.DirichletBC(V,df.Constant(0.0),left),
df.DirichletBC(V,df.Constant(0.0),right)]
# Variable coefficient
p = df.Expression('1.001+cos(4*pi*x[0])')
# Forms
a = (vx*p*ux)*df.dx
L = v*df.dx
u = df.Function(V)
df.solve(a==L,u,bc)
# Extract nodal values
ug = u.compute_vertex_values()
fig = plt.figure(1,(10,4))
ax = fig.add_subplot(111)
ax.plot(x,ug,'.')
ylim = ax.get_ylim()
ax.vlines(xi,ylim[0],ylim[1],linestyle='--')
ax.set_xlim(0,1)
plt.show()