def metric_to_Christoffel_2nd(expr):
 ch_1st = metric_to_Christoffel_1st(expr)
 coord_sys = expr.atoms(CoordSystem).pop()
 indices = list(range(coord_sys.dim))
 matrix = twoform_to_matrix(expr)
 s_fields = set()
 for e in matrix:
  s_fields.update(e.atoms(BaseScalarField))
 s_fields = list(s_fields)
 dums = coord_sys._dummies
 matrix = matrix.subs(list(zip(s_fields, dums))).inv().subs(list(zip(dums, s_fields)))
 christoffel = [[[Add(*[(matrix[(i, l)] * ch_1st[(l, j, k)]) for l in indices]) for k in indices] for j in indices] for i in indices]
 return ImmutableDenseNDimArray(christoffel)

def metric_to_Christoffel_2nd ( expr ) : ch_1st = metric_to_Christoffel_1st ( expr ) coord_sys = expr . atoms ( CoordSystem ) . pop ( ) indices = list ( range ( coord_sys . dim ) ) matrix = twoform_to_matrix ( expr ) s_fields = set ( ) for e in matrix : s_fields . update ( e . atoms ( BaseScalarField ) ) s_fields = list ( s_fields ) dums = coord_sys . _dummies matrix = matrix . subs ( list ( zip ( s_fields , dums ) ) ) . inv ( ) . subs ( list ( zip ( dums , s_fields ) ) ) christoffel = [ [ [ Add ( * [ ( matrix [ ( i , l ) ] * ch_1st [ ( l , j , k ) ] ) for l in indices ] ) for k in indices ] for j in indices ] for i in indices ] return ImmutableDenseNDimArray ( christoffel )
return the nested list of christoffel symbols for the given metric .