# 4-node tetrahedron

This is a following question to this one: Filter bad finite elements

I focus only on 4-node tetrahedral element for now.

# Re-implementing FORTRAN in Golang

I studied some files of the source code like these:

`ccx_2.20/src/e_c3d.f`

`ccx_2.20/src/gauss.f`

`ccx_2.20/src/shape4tet.f`

.

I re-implemented this error in Golang:

nonpositive jacobian determinant

My first function is this:

```
import (
v3 "github.com/deadsy/sdfx/vec/v3"
)
func isBadTet4(coords [4]v3.Vec) (bool, float64) {
// xi, et, and ze are the coordinates of the Gauss point
// in the integration scheme for the 4-node tetrahedral element.
// For this element type, there is typically only 1 Gauss point used,
// which is located at the centroid of the tetrahedron.
// The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4).
// Reference:
// ccx_2.20/src/gauss.f
var xi float64 = 0.25
var et float64 = 0.25
var ze float64 = 0.25
return isBadGaussTet4(coords, xi, et, ze)
}
```

And this is my second function that is called by the first function:

```
// Reference:
// CCX source code:
// ccx_2.20/src/shape4tet.f
func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) {
// Coordinates of the nodes.
var xl [3][4]float64
for i := 0; i < 4; i++ {
xl[0][i] = coords[i].X
xl[1][i] = coords[i].Y
xl[2][i] = coords[i].Z
}
// Shape functions.
var shp [4][4]float64
shp[3][0] = 1.0 - xi - et - ze
shp[3][1] = xi
shp[3][2] = et
shp[3][3] = ze
// local derivatives of the shape functions: xi-derivative
shp[0][0] = -1.0
shp[0][1] = 1.0
shp[0][2] = 0.0
shp[0][3] = 0.0
// local derivatives of the shape functions: eta-derivative
shp[1][0] = -1.0
shp[1][1] = 0.0
shp[1][2] = 1.0
shp[1][3] = 0.0
// local derivatives of the shape functions: zeta-derivative
shp[2][0] = -1.0
shp[2][1] = 0.0
shp[2][2] = 0.0
shp[2][3] = 1.0
// computation of the local derivative of the global coordinates (xs)
xs := [3][3]float64{}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
xs[i][j] = 0.0
for k := 0; k < 4; k++ {
xs[i][j] += xl[i][k] * shp[j][k]
}
}
}
// computation of the jacobian determinant
xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) -
xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) +
xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0])
// According to CCX source code to detect nonpositive jacobian determinant in element
//
// Fortran threshold for non-positive Jacobian determinant is 1e-20.
return xsj < 1e-20, xsj
}
```

# Input

When the 4 nodes of a tetrahedron are like this:

```
import (
"github.com/deadsy/sdfx/vec/v3"
)
coords := [4]v3.Vec{
{-3.2205676734447444, -0.01609302163123899, 6.644957738369699},
{-3.4127413321494826, -0.01609302163123899, 6.644957738369699},
{-3.2205676734447444, -0.235796231031416, 6.7280195367106765},
{-3.2205676734447444, -0.01609302163123899, 6.732770196393929},
}
```

My Golang code doesn’t detect it as a bad element. But, CCX solver throws this error for it:

*ERROR in e_c3d: nonpositive jacobian

determinant in element

# Investigating bad element

Investigations show that the bad tetrahedron has actually a fine shape. I visualized the bad element with OpenSCAD, it is just fine:

But the bad element is very small with a volume of `0.000617924113573828`

.

# Question

Despite the fact that I have exactly followed the CCX source code to filter bad elements, I’m seeing CCX solver throwing errors of *nonpositive jacobian determinant*. I’m just looking for some hints and pointers to continue my investigations. Thanks.

# Test code

I have shared the Go code by this playground so that you can run and test it: