SciFEM_Schratter/ex6/adaptivity_schemes.py
2026-01-04 20:15:55 +01:00

83 lines
No EOL
2.2 KiB
Python

import numpy as np
def flux_jumps(mesh, u):
N = len(mesh) - 1 # number of elements
jumps = np.zeros(N + 1) # N-1 edges
for i in range(1, N):
upper = (u[i + 1] - u[i])/(mesh[i + 1] - mesh[i])
lower = (u[i] - u[i - 1])/(mesh[i] - mesh[i - 1])
jumps[i] = upper - lower
return jumps
def residual_errors(mesh, u):
N = len(mesh) - 1 # number of elements
errors = np.zeros(N)
jumps = flux_jumps(mesh, u)
for i in range(N):
errors[i] = np.sqrt((jumps[i]**2 + jumps[i + 1]**2)/2) # Braess (8.10)
#print("errors:\n", errors)
return errors
def adapt_h(mesh, u, alpha):
N = len(mesh) - 1 # number of elements
errors = residual_errors(mesh, u)
threshhold = alpha * abs(max(errors))
# refine mesh
refined_mesh = [mesh[0]]
for i in range(N):
if abs(errors[i]) <= threshhold:
refined_mesh.append(mesh[i + 1])
else:
refined_mesh.append(mesh[i] + (mesh[i + 1] - mesh[i])/2)
refined_mesh.append(mesh[i + 1])
#print("refined mesh:\n", refined_mesh)
return refined_mesh
def adapt_r(mesh, u):
N = len(mesh) - 1 # number of elements
rho = np.abs(flux_jumps(mesh, u)) # rho ... mesh density function
p = np.zeros(N) # piecewise constant function on the mesh elements
for i in range(N):
p[i] = (rho[i] + rho[i + 1])/2
P = np.zeros(N + 1) # \int_0^{x_j} p(x) dx for j = 1,...,N
for j in range(1, N + 1):
h_j = mesh[j] - mesh[j - 1]
P[j] = P[j - 1] + h_j*p[j - 1] # add integral over j-th interval
moved_mesh = np.zeros(N + 1)
moved_mesh[0] = mesh[0]
moved_mesh[-1] = mesh[-1]
for j in range(1, N): # calculate the new nodes with De Boor's algorithm
xi_j = j/N
k = np.searchsorted(P, xi_j*P[-1], side="left") # searches for index k, such that xi_j*P[-1] > P[k]
assert(P[k - 1] < xi_j*P[-1])
assert(xi_j*P[-1] <= P[k])
moved_mesh[j] = mesh[k - 1] + (xi_j*P[-1] - P[k - 1])/p[k - 1]
print("orign_mesh[j] =", mesh[j])
print("moved_mesh[j] =", moved_mesh[j])
print("done\n")
#print("moved mesh:\n", moved_mesh)
return moved_mesh