Hi Fluvio,
Your code for the residual seems correct. You can delete the line that includes double p = m_s.m_p; since it is not needed here.
Also (and this was my mistake when I said the rest of the code should remain the same), according to eq.(7) in the notes you need to subtract this element force vector from the global residual, so
Regarding the stiffness matrix, your code can be simpler than the one in FEVolumeConstraint. Whereas FEVolumeConstraint::StiffnessMatrix declares kab as a vec3d object, you need to evaluate a general 2nd-order tensor Kab (so declare it as mat3d Kab) inside the double loop.
To evaluate Kab inside the double loop, you first need to evaluate a few things outside that loop (i.e., all the quantities in equation (15) which don't have a subscript a or b). For example, the dyadic product of the unit vector n with itself can be evaluated as N, using
Note that da is the magnitude of the vector cross-product of dxr and dxs, which you will need when you evaluate Kab in the loop.
You can also evaluate the dyadic product of n and u (which produces a non-symmetric tensor) along with the remaining terms containing that expression in equation (15) as
Note here that mat3dd(1) produces a diagonal tensor with 1 along its diagonal, i.e., the identity tensor.
Finally, inside the double loop, you need to evaluate the antisymmetric tensor A (which appears in (15) and (16)) as
FEBio defines the class mat3da for antisymmetric tensors, and the above initialization accepts the dual vector as its argument.
Now you have everything you need to calculate Kab inside the double loop, according to equation (15). You should replace the existing code for evaluating the element stiffness matrix ke with
Since Kab is not symmetric (based on the formulation), you will need to solve problems that use this constraint by setting the flag <symmetric_stiffness>0</symmetric_stiffness> in the <Control> section. If you use a quasi-Newton method, you should use Broyden instead of BFGS (<qnmethod>1</qnmethod>).
As usual, I am available to answer any questions.
Best,
Gerard
Your code for the residual seems correct. You can delete the line that includes double p = m_s.m_p; since it is not needed here.
Also (and this was my mistake when I said the rest of the code should remain the same), according to eq.(7) in the notes you need to subtract this element force vector from the global residual, so
Code:
fe[3 * j ] -= H[j] * v.x; fe[3 * j+1] -= H[j] * v.y; fe[3 * j+2] -= H[j] * v.z;
To evaluate Kab inside the double loop, you first need to evaluate a few things outside that loop (i.e., all the quantities in equation (15) which don't have a subscript a or b). For example, the dyadic product of the unit vector n with itself can be evaluated as N, using
Code:
vec3d nu = dxr ^ dxs; double da = nu.unit(); mat3ds N = dyad(nu);
You can also evaluate the dyadic product of n and u (which produces a non-symmetric tensor) along with the remaining terms containing that expression in equation (15) as
Code:
mat3ds ImN = mat3dd(1) - N; mat3d U = (mat3dd(1)*(u*nu) + (nu & u))*ImN;
Finally, inside the double loop, you need to evaluate the antisymmetric tensor A (which appears in (15) and (16)) as
Code:
mat3da A(dxr*Gs[j] - dxs*Gr[j]);
Now you have everything you need to calculate Kab inside the double loop, according to equation (15). You should replace the existing code for evaluating the element stiffness matrix ke with
Code:
ke[3*i ][3*j ] += Kab(0,0); ke[3*i ][3*j+1] += Kab(0,1); ke[3*i ][3*j+2] += Kab(0,2); ke[3*i+1][3*j ] += Kab(1,0); ke[3*i+1][3*j+1] += Kab(1,1); ke[3*i+1][3*j+2] += Kab(1,2); ke[3*i+2][3*j ] += Kab(2,0); ke[3*i+2][3*j+1] += Kab(2,1); ke[3*i+2][3*j+2] += Kab(2,2);
As usual, I am available to answer any questions.
Best,
Gerard
Comment