Hello again.
I’m a little bit confused at making the MWE from a module made by someone else, but i found a small example in the Fenics tutorial that probably could capture what i intend to do in a simple manner. I got it from here and below is the modified code (i only changed the u_D variable from the original example and add a random time_series list):
from fenics import *
import numpy as np
T = 2.0 # final time
num_steps = 10 # number of time steps
dt = T / num_steps # time step size
alpha = 3 # parameter alpha
beta = 1.2 # parameter beta
# Create mesh and define function space
nx = ny = 8
mesh = UnitSquareMesh(nx, ny)
V = FunctionSpace(mesh, 'P', 1)
# Random timeseries data
time_series = [0.1, 0.4, 0.5, -0.2, -0.6, 0.3, 0.7, 0, -0.1, -0.8]
# Define boundary condition
u_D = Expression("t", t=time_series[0], degree=1)
def boundary(x, on_boundary):
return on_boundary
bc = DirichletBC(V, u_D, boundary)
# Define initial value
u_n = interpolate(u_D, V)
#u_n = project(u_D, V)
# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Constant(beta - 2 - 2*alpha)
F = u*v*dx + dt*dot(grad(u), grad(v))*dx - (u_n + dt*f)*v*dx
a, L = lhs(F), rhs(F)
# Time-stepping
u = Function(V)
t = 0
for n in range(num_steps):
# Update current time
t += dt
u_D.t = t
# Compute solution
solve(a == L, u, bc)
# Plot solution
plot(u)
# Compute error at vertices
u_e = interpolate(u_D, V)
error = np.abs(u_e.vector().array() - u.vector().array()).max()
print('t = %.2f: error = %.3g' % (t, error))
# Update previous solution
u_n.assign(u)
This works (i don’t know how to print Expression values in given time to check if it’s updating, but it shows result until the end). But in OpenTidalFarm it has a different time-updating class in boundary condition definition (fully here, but i just want to highlight this part from the full class) :
def update_time(self, t, only_type=None, exclude_type=None):
''' Update the time attribute for all boundary conditions '''
if exclude_type is None:
exclude_type = []
for bc in self:
if only_type is not None and bc[-1] not in only_type:
continue
if bc[-1] in exclude_type:
continue
if hasattr(bc[1], "t"):
bc[1].t = t
So it only updates when the Expression() has attribute “t” in it. I tried using a similar Expression like u_D above (named top_expr) for boundary condition :
top_expr = Expression("t", t=time_series[0], degree=1)
But this is what i get :
TypeError: in method 'Expression_097464b5e61d068b0849dc47522abe90cd94dd9a_t_set', argument 2 of type 'double'
Probably due to “t” here refers to the variable time_series[0] being a double
So what do i actually want?
I want to make an Expression() that :
- could be detected to have attribute “t”
- will update time variable and can access index based on the time update (e.g. with dt=3600, at t=0 the Expression would give time_series[0/dt] as the value; at t=3600 the Expression would give times_series[3600/dt] as the value)
Is that possible to do? Sorry for the long post, i just hope i could make it clear. Any help is appreciated!