scf_celebic/ex6/code/adapt.py
dino.celebic 89326dd329 ex6
2025-12-23 22:34:09 +01:00

83 lines
2.7 KiB
Python

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
# Basis functions
# ---- TODO: order p? ----
def phi(k, mesh, x):
if x > mesh[k-1] and x < mesh[k]:
return (x-mesh[k-1]) / (mesh[k] - mesh[k-1])
elif x > mesh[k] and x < mesh[k+1]:
return (mesh[k+1]-x) / (mesh[k+1] - mesh[k])
elif x == mesh[k]:
return 1
else:
return 0
def phi_prime(k, mesh, x):
if x > mesh[k-1] and x < mesh[k]:
return 1 / (mesh[k] - mesh[k-1])
elif x > mesh[k] and x < mesh[k+1]:
return -1 / (mesh[k+1] - mesh[k])
elif x == mesh[k]:
return print("oh no")
else:
return 0
# vertex flux jump between elements
def flux_jumps(mesh, u):
m = len(mesh)
r = (u[2:]-u[1:-1]) / (mesh[2:]-mesh[1:-1])
l = (u[1:-1]-u[:-2]) / (mesh[1:-1]-mesh[:-2])
jumps = np.zeros(m) # 0 jump at bnd?
jumps[1:-1] = r - l
jumps[0] = jumps[1] # or same jump at bnd?
jumps[-1] = jumps[-2] # or same jump at bnd?
return jumps
# h-adaptivity (refine neighboring elments, if flux jump over certain threshold)
def adapt_h(mesh, jumps):
new_mesh = [mesh[0]]
jumps = jumps[1:-1] # only interior jumps (excluding bnd nodes needed for De Boor)
# define threshold
threshold = 0.5 * np.max(np.abs(jumps))
# mark elements
marked_nodes = np.abs(jumps) > threshold
marked_el = np.zeros(len(mesh)-1, dtype=bool)
for i, refine in enumerate(marked_nodes):
if refine:
marked_el[i] = True
marked_el[i+1] = True
# make new mesh
for k, refine in enumerate(marked_el):
l = mesh[k]
r = mesh[k+1]
if refine:
new_mesh.extend(np.linspace(l, r, 3)[1:])
else:
new_mesh.append(r)
return np.asarray(new_mesh, dtype=float)
# r-adaptivity (one iteration of De Boor's algorithm, moving mesh nodes for equidistributing mesh)
def adapt_r(mesh, rho):
m = len(mesh)
p = 0.5 * (rho[:-1] + rho[1:]) # piecewise constant function on elements
P = np.zeros(m)
for i in range(1,m):
P[i] = P[i-1] + (mesh[i]-mesh[i-1])*p[i-1] # approx integral of p, from node 0 to node i
Pb = P[-1] # integral of p, over whole mesh
new_mesh = mesh.copy()
for j in range(1, m-1):
xi_j = (j)/(m-1)
k = np.searchsorted(P, xi_j*Pb) # search k s.t.: P[node k-1] < xi_j*Pb < P[node k]
k = max(k,1) # if k=0
new_mesh[j] = mesh[k-1] + 2*(xi_j*Pb - P[k-1]) / (rho[k-1]+rho[k]) # new node j
return new_mesh