I am working in dolfinx with the 3D Reissner-Mindlin shell implementation here: GitHub - RuruX/shell_analysis_fenicsx
I am applying loads as independent point forces at a collection of vertices (I realize there are probably other options here, but it is important for me to stick with this approach presently). So far, it has proved simplest to directly insert the point forces into the force vector of my linear problem, i.e.:
A = assemble_matrix(form(a), bcs)
A.assemble()
b = assemble_vector(form(L)) #just used to initialize with proper sizing
b.setArray(f_node.vector.getArray()) #insert point forces here!
In order to construct f_node
I of course must map my forces (which are vertex-based) to the corresponding degree of freedom. My current approach for this–which I would like to improve–is to do a brute force search between the mesh coordinates and the DOF coordinates to build a vtx_to_dof
index map, i.e.:
# map vertex values to DOFs
w0_coll, submap = W.sub(0).collapse()
dof_coords = w0_coll.tabulate_dof_coordinates()
msh_coords = mesh.geometry.x
submap = np.reshape(submap, (-1,3))
vtx_to_dof = np.zeros(np.shape(msh_coords))
for ii in range(np.shape(msh_coords)[0]):
d = scipy.spatial.distance.cdist([msh_coords[ii,:]], dof_coords)
assert(np.min(d) < 1.0e-6)
idx = np.argmin(d)
vtx_to_dof[ii,:] = submap[idx,:]
vtx_to_dof = np.reshape(vtx_to_dof, (-1,1))
This yields the desired result but, as you can imagine, is not particularly efficient. For the typical problems I work with this procedure is consuming nearly half the total computation time, and for larger problems it scales very poorly.
I suspect there is a cleaner and more efficient way either of applying the forces or, more likely, of constructing/retrieving this vtx_to_dof
map. Can anybody point me in the right direction? I have seen various references to the vertex_to_dof_map
(e.g. here) but from what I can tell this doesn’t seem to be implemented the same way in dolfinx (happy to be corrected if that isn’t the case though!).