Hello,
I would like to perform a geometric affine transformation of a Function u0, like a translation along the x-axis by a specific value b.
The FunctionSpace and the mesh are fixed, only the function (with unknown expression) would “translate on the FunctionSpace”. It would also be great if the part of the shifted function that lies outside the range of the mesh, could be mapped/“looped” at the beginning of the mesh:
Ideally, I would like to avoid solving a PDE as I plan on integrating this into an optimization with a large number of iterations.
Do some of you have any suggestions?
I tried something but don’t manage to make it work as desired… I’ve tried to map the coordinates of the translated Degrees Of Freedom (DOF) to the ones of the initial FunctionSpace.
from dolfin import *
from dolfin_adjoint import *
import numpy as np
import matplotlib.pyplot as plt
# Mesh information
n_elem = 16
xmin, xmax = -0.5, 0.5
ymin, ymax = -0.25, 0.25
lx, ly = xmax-xmin , ymax-ymin
mesh = RectangleMesh(Point(xmin,ymin),Point(xmax,ymax),n_elem,n_elem)
V = FunctionSpace(mesh, "CG", 2)
# Initial Function (expression not known in practice)
expr_init = Expression("sin(pi*x[0])*cos(pi*x[1])",degree=3)
u_0 = interpolate(expr_init, V)
n = V.dim()
d = mesh.geometry().dim()
dof_V_coordinates = V.tabulate_dof_coordinates()
dof_V_coordinates.resize((n, d))
dof_V_x = dof_V_coordinates[:, 0]
dof_V_y = dof_V_coordinates[:, 1]
# Shift spatially along x the dofs
b = lx/4.0 #shift along x-axis
shifted_dofs = dof_V_x + b
idx_outside = np.where(shifted_dofs>xmax)[0]
shifted_dofs[idx_outside] -= lx # The dofs that are outside the bounds of the mesh are "looped" to its begining (xmax --> xmin)
# Build the map of the dof from the inital field to the shifted one
dof_map_0to1 = np.array([])
idx_shifted_dofs = list(range(len(shifted_dofs)))
for idx in idx_shifted_dofs:
idx_shiftedInMain = np.argmin(np.linalg.norm(dof_V_x - shifted_dofs[idx])) # Find the closest initial dof to the current shifted one
dof_map_0to1 = np.append(dof_map_0to1, idx_shiftedInMain)
u_1 = Function(V)
u_1.vector()[:] = u_0.vector()[dof_map_0to1]
# Plot the functions for comparison
pl, ax = plt.subplots(); fig = plt.gcf(); fig.set_size_inches(16, 4)
plt.subplot(1, 2, 1); p = plot(u_0,title='Initial Distribution',mode='color',vmin=-1.0,vmax=1.0); cbar = plt.colorbar(p);
plt.subplot(1, 2, 2); p = plot(u_1,title='Shifted Distribution',mode='color',vmin=-1.0,vmax=1.0); cbar = plt.colorbar(p);
This is what I obtained (which is obviously wrong):
And this is what I would like to achieve:
Thank you for your time.