Hi Jean-Paul,
Thanks for the response. I realize I should have specified that the values of the inhomogeneities that I would like to use are the differences in the two points that are being glued together. This means that when I set the inhomogeneity for a degree of freedom, I actually need access to all the degrees of freedom with non-zero weights in the line of the constraint involved. In the end, it seemed that the set_periodicity_constraints and make_periodicity_constraints functions are mostly about going through and figuring out which DOFs are being linked, so it seemed easier to modify those functions than to add the inhomogeneities after calling them.
I implemented the modifications for when the faces are at the same level of refinement, but am now having trouble with the solver not converging. My problem of bending a bar around to glue the faces together to form a ring does not satisfy the assumption of infinitesimal strain, so I have included the nonlinear strain term to use the Saint Venant–Kirchhoff model of elasticity, and am using Newton's method to solve the problem. I was able to solve the same problem by setting the boundary conditions directly, although I had to solve the problem in stages in which I updated the boundary to move along a spiral path to achieve convergence. With the inhomogeneous periodic constraints, I also try solving the problem in stages in which I slowly move from a homogeneous problem (the solution of which is no deformation) to the final inhomogeneous problem, although with a more direct path. However, with even the smallest inhomogeneity, after a few Newton iterations, the residual from the CG solver suddenly becomes nan.
I am wondering whether I have setup the constraints properly, particularly whether I have called the functions to condense and distribute the problem correctly. In the "Constraints on degrees of freedom" module, step 1 of the second approach under "Treatment of inhomogeneous constraints" involves calling distribute_local_to_global() during assembly. In my case, because I will calculate the right hand side again with the updated solution to calculate the residual, I have to call this on two occaions. However, in calculating the residual, I only need to assemble the right hand side, so I first tried using the second variant of distribute_local_to_global(), which takes only the local matrix (in addition of course to the local and global RHS vector) as an argument. In the description of the function, it says it is used for situations involving inhomogeneous constraints where the global matrix does not need to be assembled again, which seems to apply here. However, the assembly in the next Newton iteration, which uses the same solution vector (with the step size alpha=1), produces a different result (where it calls variant 9 of the function). Have I misunderstood the difference between these two functions?
In step two of the second approach under "Constraints on degrees of freedom", it states "Set the concerning components of the solution to the inhomogeneous constrained values (for example using AffineConstraints::distribute())". However, in the step-22 example cited for use of inhomogeneous constraints, the distribute method on the constraints object is only called after running the linear solver (which I understand needs to be done as well), not before. In my own tests, it seemed to make no difference whether I called before solving or not. Are the solution components being set in some other function then?
I also wonder if I am using the wrong solver, preconditioner, and/or sparsity pattern for my problem. However before I can address that it seems I need to check I have set the constraints up properly. I have for now stuck with the choices made in the early tutorial steps of SolverCG, PreconditionSSOR, and copying from a DynamicSparsityPattern object to SparsityPattern.
I have attached an example program for solving my problem, as well as the file with the modifications to the periodic boundary conditions functions. The main modifications to the periodic boundary conditions functions are on lines 310-314, where I calculate the difference between the position of the support points the DOFs are associated with and set the inhomogeneity for the current DOF. I did print out the values of the component being used, and this part at least appears to be correct.
Any further thoughts would be much appreciated.
Best,
Alex