Files
astaroth/acc/stdlib/stdderiv.h

233 lines
6.7 KiB
C

#ifndef STENCIL_ORDER
#define STENCIL_ORDER (6)
#endif
Scalar
first_derivative(Scalar pencil[], Scalar inv_ds)
{
#if STENCIL_ORDER == 2
Scalar coefficients[] = {0, 1.0 / 2.0};
#elif STENCIL_ORDER == 4
Scalar coefficients[] = {0, 2.0 / 3.0, -1.0 / 12.0};
#elif STENCIL_ORDER == 6
Scalar coefficients[] = {0, 3.0 / 4.0, -3.0 / 20.0, 1.0 / 60.0};
#elif STENCIL_ORDER == 8
Scalar coefficients[] = {0, 4.0 / 5.0, -1.0 / 5.0, 4.0 / 105.0, -1.0 / 280.0};
#endif
#define MID (STENCIL_ORDER / 2)
Scalar res = 0;
for (int i = 1; i <= MID; ++i) {
res = res + coefficients[i] * (pencil[MID + i] - pencil[MID - i]);
}
return res * inv_ds;
}
Scalar
second_derivative(Scalar pencil[], Scalar inv_ds)
{
#if STENCIL_ORDER == 2
Scalar coefficients[] = {-2.0, 1.0};
#elif STENCIL_ORDER == 4
Scalar coefficients[] = {-5.0 / 2.0, 4.0 / 3.0, -1.0 / 12.0};
#elif STENCIL_ORDER == 6
Scalar coefficients[] = {-49.0 / 18.0, 3.0 / 2.0, -3.0 / 20.0, 1.0 / 90.0};
#elif STENCIL_ORDER == 8
Scalar coefficients[] = {-205.0 / 72.0, 8.0 / 5.0, -1.0 / 5.0, 8.0 / 315.0, -1.0 / 560.0};
#endif
#define MID (STENCIL_ORDER / 2)
Scalar res = coefficients[0] * pencil[MID];
for (int i = 1; i <= MID; ++i) {
res = res + coefficients[i] * (pencil[MID + i] + pencil[MID - i]);
}
return res * inv_ds * inv_ds;
}
Scalar
cross_derivative(Scalar pencil_a[], Scalar pencil_b[], Scalar inv_ds_a, Scalar inv_ds_b)
{
#if STENCIL_ORDER == 2
Scalar coefficients[] = {0, 1.0 / 4.0};
#elif STENCIL_ORDER == 4
Scalar coefficients[] = {0, 1.0 / 32.0,
1.0 / 64.0}; // TODO correct coefficients, these are just placeholders
#elif STENCIL_ORDER == 6
Scalar fac = 1.0 / 720.0;
Scalar coefficients[] = {0.0 * fac, 270.0 * fac, -27.0 * fac, 2.0 * fac};
#elif STENCIL_ORDER == 8
Scalar fac = (1.0 / 20160.0);
Scalar coefficients[] = {0.0 * fac, 8064.0 * fac, -1008.0 * fac, 128.0 * fac, -9.0 * fac};
#endif
#define MID (STENCIL_ORDER / 2)
Scalar res = 0.0;
for (int i = 1; i <= MID; ++i) {
res = res + coefficients[i] * (pencil_a[MID + i] + pencil_a[MID - i] - pencil_b[MID + i] -
pencil_b[MID - i]);
}
return res * inv_ds_a * inv_ds_b;
}
Scalar
derx(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil[offset] = arr[vertexIdx.x + offset - STENCIL_ORDER / 2, vertexIdx.y, vertexIdx.z];
}
return first_derivative(pencil, AC_inv_dsx);
}
Scalar
derxx(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil[offset] = arr[vertexIdx.x + offset - STENCIL_ORDER / 2, vertexIdx.y, vertexIdx.z];
}
return second_derivative(pencil, AC_inv_dsx);
}
Scalar
derxy(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil_a[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil_a[offset] = arr[vertexIdx.x + offset - STENCIL_ORDER / 2,
vertexIdx.y + offset - STENCIL_ORDER / 2, vertexIdx.z];
}
Scalar pencil_b[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil_b[offset] = arr[vertexIdx.x + offset - STENCIL_ORDER / 2,
vertexIdx.y + STENCIL_ORDER / 2 - offset, vertexIdx.z];
}
return cross_derivative(pencil_a, pencil_b, AC_inv_dsx, AC_inv_dsy);
}
Scalar
derxz(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil_a[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil_a[offset] = arr[vertexIdx.x + offset - STENCIL_ORDER / 2, vertexIdx.y,
vertexIdx.z + offset - STENCIL_ORDER / 2];
}
Scalar pencil_b[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil_b[offset] = arr[vertexIdx.x + offset - STENCIL_ORDER / 2, vertexIdx.y,
vertexIdx.z + STENCIL_ORDER / 2 - offset];
}
return cross_derivative(pencil_a, pencil_b, AC_inv_dsx, AC_inv_dsz);
}
Scalar
dery(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil[offset] = arr[vertexIdx.x, vertexIdx.y + offset - STENCIL_ORDER / 2, vertexIdx.z];
}
return first_derivative(pencil, AC_inv_dsy);
}
Scalar
deryy(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil[offset] = arr[vertexIdx.x, vertexIdx.y + offset - STENCIL_ORDER / 2, vertexIdx.z];
}
return second_derivative(pencil, AC_inv_dsy);
}
Scalar
deryz(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil_a[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil_a[offset] = arr[vertexIdx.x, vertexIdx.y + offset - STENCIL_ORDER / 2,
vertexIdx.z + offset - STENCIL_ORDER / 2];
}
Scalar pencil_b[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil_b[offset] = arr[vertexIdx.x, vertexIdx.y + offset - STENCIL_ORDER / 2,
vertexIdx.z + STENCIL_ORDER / 2 - offset];
}
return cross_derivative(pencil_a, pencil_b, AC_inv_dsy, AC_inv_dsz);
}
Scalar
derz(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil[offset] = arr[vertexIdx.x, vertexIdx.y, vertexIdx.z + offset - STENCIL_ORDER / 2];
}
return first_derivative(pencil, AC_inv_dsz);
}
Scalar
derzz(int3 vertexIdx, in ScalarField arr)
{
Scalar pencil[STENCIL_ORDER + 1];
for (int offset = 0; offset < STENCIL_ORDER + 1; ++offset) {
pencil[offset] = arr[vertexIdx.x, vertexIdx.y, vertexIdx.z + offset - STENCIL_ORDER / 2];
}
return second_derivative(pencil, AC_inv_dsz);
}
Preprocessed Scalar
value(in ScalarField vertex)
{
return vertex[vertexIdx];
}
Preprocessed Vector
gradient(in ScalarField vertex)
{
return (Vector){derx(vertexIdx, vertex), dery(vertexIdx, vertex), derz(vertexIdx, vertex)};
}
Preprocessed Matrix
hessian(in ScalarField vertex)
{
Matrix hessian;
hessian.row[0] = (Vector){derxx(vertexIdx, vertex), derxy(vertexIdx, vertex),
derxz(vertexIdx, vertex)};
hessian.row[1] = (Vector){hessian.row[0].y, deryy(vertexIdx, vertex), deryz(vertexIdx, vertex)};
hessian.row[2] = (Vector){hessian.row[0].z, hessian.row[1].z, derzz(vertexIdx, vertex)};
return hessian;
}