Files
David Galiffi 0403aaa97f Use clang-format-18 for source formatting (#256)
* Updating clang-format to v18

- Updates the pre-commit-config
- Formats source files according to the utility

Signed-off-by: David Galiffi <David.Galiffi@amd.com>

* Update format source workflow

Signed-off-by: David Galiffi <David.Galiffi@amd.com>

* Update CONTRIBUTING

* Update comment in .clang-format

* Update CONTRIBUTING.md

* Update helper script

---------

Signed-off-by: David Galiffi <David.Galiffi@amd.com>

[ROCm/rocprofiler-systems commit: 1e13b590e7]
2025-06-22 08:48:08 -04:00

2309 خطوط
78 KiB
C++

#include <climits>
#include <ctype.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <vector>
#include "lulesh.h"
#include "causal.hpp"
static Kokkos::View<Real_t*> buffer;
static size_t buffer_size;
static size_t buffer_offset;
static int do_atomic;
void
ResizeBuffer(const size_t size)
{
buffer_offset = 0;
if(size / sizeof(Real_t) + 1 > buffer_size)
{
buffer_size = size / sizeof(Real_t) + 1;
buffer = Kokkos::View<Real_t*>("Buffer", buffer_size);
}
}
template <class Type>
Type*
AllocateFromBuffer(const Index_t& count)
{
const Index_t offset = (count * sizeof(Type) + sizeof(Real_t) - 1) / sizeof(Real_t);
Real_t* ptr = buffer.data() + buffer_offset;
buffer_offset += ((offset + 511) / 512) * 512;
return static_cast<Type*>(ptr);
}
static inline void
TimeIncrement(Domain& domain)
{
Real_t targetdt = domain.stoptime() - domain.time();
if((domain.dtfixed() <= Real_t(0.0)) && (domain.cycle() != Int_t(0)))
{
// CAUSAL_BEGIN("TimeIncrement_Iteration")
Real_t ratio;
Real_t olddt = domain.deltatime();
Real_t gnewdt = Real_t(1.0e+20);
Real_t newdt;
if(domain.dtcourant() < gnewdt)
{
gnewdt = domain.dtcourant() / Real_t(2.0);
}
if(domain.dthydro() < gnewdt)
{
gnewdt = domain.dthydro() * Real_t(2.0) / Real_t(3.0);
}
#if USE_MPI
MPI_Allreduce(&gnewdt, &newdt, 1,
((sizeof(Real_t) == 4) ? MPI_FLOAT : MPI_DOUBLE), MPI_MIN,
MPI_COMM_WORLD);
#else
newdt = gnewdt;
#endif
ratio = newdt / olddt;
if(ratio >= Real_t(1.0))
{
if(ratio < domain.deltatimemultlb())
{
newdt = olddt;
}
else if(ratio > domain.deltatimemultub())
{
newdt = olddt * domain.deltatimemultub();
}
}
if(newdt > domain.dtmax())
{
newdt = domain.dtmax();
}
domain.deltatime() = newdt;
CAUSAL_PROGRESS_NAMED("TimeIncrement_Iteration");
// CAUSAL_END("TimeIncrement_Iteration")
}
if((targetdt > domain.deltatime()) &&
(targetdt < (Real_t(4.0) * domain.deltatime() / Real_t(3.0))))
{
targetdt = Real_t(2.0) * domain.deltatime() / Real_t(3.0);
}
if(targetdt < domain.deltatime())
{
domain.deltatime() = targetdt;
}
domain.time() += domain.deltatime();
++domain.cycle();
}
KOKKOS_INLINE_FUNCTION void
CollectDomainNodesToElemNodes(const Domain& domain, const Index_t* elemToNode,
Real_t elemX[8], Real_t elemY[8], Real_t elemZ[8])
{
Index_t nd0i = elemToNode[0];
Index_t nd1i = elemToNode[1];
Index_t nd2i = elemToNode[2];
Index_t nd3i = elemToNode[3];
Index_t nd4i = elemToNode[4];
Index_t nd5i = elemToNode[5];
Index_t nd6i = elemToNode[6];
Index_t nd7i = elemToNode[7];
elemX[0] = domain.c_x(nd0i);
elemX[1] = domain.c_x(nd1i);
elemX[2] = domain.c_x(nd2i);
elemX[3] = domain.c_x(nd3i);
elemX[4] = domain.c_x(nd4i);
elemX[5] = domain.c_x(nd5i);
elemX[6] = domain.c_x(nd6i);
elemX[7] = domain.c_x(nd7i);
elemY[0] = domain.c_y(nd0i);
elemY[1] = domain.c_y(nd1i);
elemY[2] = domain.c_y(nd2i);
elemY[3] = domain.c_y(nd3i);
elemY[4] = domain.c_y(nd4i);
elemY[5] = domain.c_y(nd5i);
elemY[6] = domain.c_y(nd6i);
elemY[7] = domain.c_y(nd7i);
elemZ[0] = domain.c_z(nd0i);
elemZ[1] = domain.c_z(nd1i);
elemZ[2] = domain.c_z(nd2i);
elemZ[3] = domain.c_z(nd3i);
elemZ[4] = domain.c_z(nd4i);
elemZ[5] = domain.c_z(nd5i);
elemZ[6] = domain.c_z(nd6i);
elemZ[7] = domain.c_z(nd7i);
}
static inline void
InitStressTermsForElems(Domain& domain, Real_t* sigxx, Real_t* sigyy, Real_t* sigzz,
Index_t numElem)
{
Kokkos::parallel_for(
"InitStressTermsForElems", numElem, KOKKOS_LAMBDA(const Index_t& i) {
sigxx[i] = sigyy[i] = sigzz[i] = -domain.p(i) - domain.q(i);
});
}
KOKKOS_INLINE_FUNCTION void
CalcElemShapeFunctionDerivatives(Real_t const x[], Real_t const y[], Real_t const z[],
Real_t b[][8], Real_t* const volume)
{
const Real_t x0 = x[0];
const Real_t x1 = x[1];
const Real_t x2 = x[2];
const Real_t x3 = x[3];
const Real_t x4 = x[4];
const Real_t x5 = x[5];
const Real_t x6 = x[6];
const Real_t x7 = x[7];
const Real_t y0 = y[0];
const Real_t y1 = y[1];
const Real_t y2 = y[2];
const Real_t y3 = y[3];
const Real_t y4 = y[4];
const Real_t y5 = y[5];
const Real_t y6 = y[6];
const Real_t y7 = y[7];
const Real_t z0 = z[0];
const Real_t z1 = z[1];
const Real_t z2 = z[2];
const Real_t z3 = z[3];
const Real_t z4 = z[4];
const Real_t z5 = z[5];
const Real_t z6 = z[6];
const Real_t z7 = z[7];
Real_t fjxxi, fjxet, fjxze;
Real_t fjyxi, fjyet, fjyze;
Real_t fjzxi, fjzet, fjzze;
Real_t cjxxi, cjxet, cjxze;
Real_t cjyxi, cjyet, cjyze;
Real_t cjzxi, cjzet, cjzze;
fjxxi = Real_t(.125) * ((x6 - x0) + (x5 - x3) - (x7 - x1) - (x4 - x2));
fjxet = Real_t(.125) * ((x6 - x0) - (x5 - x3) + (x7 - x1) - (x4 - x2));
fjxze = Real_t(.125) * ((x6 - x0) + (x5 - x3) + (x7 - x1) + (x4 - x2));
fjyxi = Real_t(.125) * ((y6 - y0) + (y5 - y3) - (y7 - y1) - (y4 - y2));
fjyet = Real_t(.125) * ((y6 - y0) - (y5 - y3) + (y7 - y1) - (y4 - y2));
fjyze = Real_t(.125) * ((y6 - y0) + (y5 - y3) + (y7 - y1) + (y4 - y2));
fjzxi = Real_t(.125) * ((z6 - z0) + (z5 - z3) - (z7 - z1) - (z4 - z2));
fjzet = Real_t(.125) * ((z6 - z0) - (z5 - z3) + (z7 - z1) - (z4 - z2));
fjzze = Real_t(.125) * ((z6 - z0) + (z5 - z3) + (z7 - z1) + (z4 - z2));
cjxxi = (fjyet * fjzze) - (fjzet * fjyze);
cjxet = -(fjyxi * fjzze) + (fjzxi * fjyze);
cjxze = (fjyxi * fjzet) - (fjzxi * fjyet);
cjyxi = -(fjxet * fjzze) + (fjzet * fjxze);
cjyet = (fjxxi * fjzze) - (fjzxi * fjxze);
cjyze = -(fjxxi * fjzet) + (fjzxi * fjxet);
cjzxi = (fjxet * fjyze) - (fjyet * fjxze);
cjzet = -(fjxxi * fjyze) + (fjyxi * fjxze);
cjzze = (fjxxi * fjyet) - (fjyxi * fjxet);
b[0][0] = -cjxxi - cjxet - cjxze;
b[0][1] = cjxxi - cjxet - cjxze;
b[0][2] = cjxxi + cjxet - cjxze;
b[0][3] = -cjxxi + cjxet - cjxze;
b[0][4] = -b[0][2];
b[0][5] = -b[0][3];
b[0][6] = -b[0][0];
b[0][7] = -b[0][1];
b[1][0] = -cjyxi - cjyet - cjyze;
b[1][1] = cjyxi - cjyet - cjyze;
b[1][2] = cjyxi + cjyet - cjyze;
b[1][3] = -cjyxi + cjyet - cjyze;
b[1][4] = -b[1][2];
b[1][5] = -b[1][3];
b[1][6] = -b[1][0];
b[1][7] = -b[1][1];
b[2][0] = -cjzxi - cjzet - cjzze;
b[2][1] = cjzxi - cjzet - cjzze;
b[2][2] = cjzxi + cjzet - cjzze;
b[2][3] = -cjzxi + cjzet - cjzze;
b[2][4] = -b[2][2];
b[2][5] = -b[2][3];
b[2][6] = -b[2][0];
b[2][7] = -b[2][1];
*volume = Real_t(8.) * (fjxet * cjxet + fjyet * cjyet + fjzet * cjzet);
}
KOKKOS_INLINE_FUNCTION void
SumElemFaceNormal(Real_t* normalX0, Real_t* normalY0, Real_t* normalZ0, Real_t* normalX1,
Real_t* normalY1, Real_t* normalZ1, Real_t* normalX2, Real_t* normalY2,
Real_t* normalZ2, Real_t* normalX3, Real_t* normalY3, Real_t* normalZ3,
const Real_t x0, const Real_t y0, const Real_t z0, const Real_t x1,
const Real_t y1, const Real_t z1, const Real_t x2, const Real_t y2,
const Real_t z2, const Real_t x3, const Real_t y3, const Real_t z3)
{
Real_t bisectX0 = Real_t(0.5) * (x3 + x2 - x1 - x0);
Real_t bisectY0 = Real_t(0.5) * (y3 + y2 - y1 - y0);
Real_t bisectZ0 = Real_t(0.5) * (z3 + z2 - z1 - z0);
Real_t bisectX1 = Real_t(0.5) * (x2 + x1 - x3 - x0);
Real_t bisectY1 = Real_t(0.5) * (y2 + y1 - y3 - y0);
Real_t bisectZ1 = Real_t(0.5) * (z2 + z1 - z3 - z0);
Real_t areaX = Real_t(0.25) * (bisectY0 * bisectZ1 - bisectZ0 * bisectY1);
Real_t areaY = Real_t(0.25) * (bisectZ0 * bisectX1 - bisectX0 * bisectZ1);
Real_t areaZ = Real_t(0.25) * (bisectX0 * bisectY1 - bisectY0 * bisectX1);
*normalX0 += areaX;
*normalX1 += areaX;
*normalX2 += areaX;
*normalX3 += areaX;
*normalY0 += areaY;
*normalY1 += areaY;
*normalY2 += areaY;
*normalY3 += areaY;
*normalZ0 += areaZ;
*normalZ1 += areaZ;
*normalZ2 += areaZ;
*normalZ3 += areaZ;
}
KOKKOS_INLINE_FUNCTION void
CalcElemNodeNormals(Real_t pfx[8], Real_t pfy[8], Real_t pfz[8], const Real_t x[8],
const Real_t y[8], const Real_t z[8])
{
for(Index_t i = 0; i < 8; ++i)
{
pfx[i] = Real_t(0.0);
pfy[i] = Real_t(0.0);
pfz[i] = Real_t(0.0);
}
SumElemFaceNormal(&pfx[0], &pfy[0], &pfz[0], &pfx[1], &pfy[1], &pfz[1], &pfx[2],
&pfy[2], &pfz[2], &pfx[3], &pfy[3], &pfz[3], x[0], y[0], z[0], x[1],
y[1], z[1], x[2], y[2], z[2], x[3], y[3], z[3]);
SumElemFaceNormal(&pfx[0], &pfy[0], &pfz[0], &pfx[4], &pfy[4], &pfz[4], &pfx[5],
&pfy[5], &pfz[5], &pfx[1], &pfy[1], &pfz[1], x[0], y[0], z[0], x[4],
y[4], z[4], x[5], y[5], z[5], x[1], y[1], z[1]);
SumElemFaceNormal(&pfx[1], &pfy[1], &pfz[1], &pfx[5], &pfy[5], &pfz[5], &pfx[6],
&pfy[6], &pfz[6], &pfx[2], &pfy[2], &pfz[2], x[1], y[1], z[1], x[5],
y[5], z[5], x[6], y[6], z[6], x[2], y[2], z[2]);
SumElemFaceNormal(&pfx[2], &pfy[2], &pfz[2], &pfx[6], &pfy[6], &pfz[6], &pfx[7],
&pfy[7], &pfz[7], &pfx[3], &pfy[3], &pfz[3], x[2], y[2], z[2], x[6],
y[6], z[6], x[7], y[7], z[7], x[3], y[3], z[3]);
SumElemFaceNormal(&pfx[3], &pfy[3], &pfz[3], &pfx[7], &pfy[7], &pfz[7], &pfx[4],
&pfy[4], &pfz[4], &pfx[0], &pfy[0], &pfz[0], x[3], y[3], z[3], x[7],
y[7], z[7], x[4], y[4], z[4], x[0], y[0], z[0]);
SumElemFaceNormal(&pfx[4], &pfy[4], &pfz[4], &pfx[7], &pfy[7], &pfz[7], &pfx[6],
&pfy[6], &pfz[6], &pfx[5], &pfy[5], &pfz[5], x[4], y[4], z[4], x[7],
y[7], z[7], x[6], y[6], z[6], x[5], y[5], z[5]);
}
KOKKOS_INLINE_FUNCTION void
SumElemStressesToNodeForces(const Real_t B[][8], const Real_t stress_xx,
const Real_t stress_yy, const Real_t stress_zz, Real_t fx[],
Real_t fy[], Real_t fz[])
{
for(Index_t i = 0; i < 8; i++)
{
fx[i] = -(stress_xx * B[0][i]);
fy[i] = -(stress_yy * B[1][i]);
fz[i] = -(stress_zz * B[2][i]);
}
}
static inline void
IntegrateStressForElems(Domain& domain, Real_t* sigxx, Real_t* sigyy, Real_t* sigzz,
Real_t* determ, Index_t numElem, Index_t numNode)
{
Index_t numElem8 = numElem * 8;
ResizeBuffer((numElem8 * sizeof(Real_t) + 4096) * 3);
Real_t* fx_elem = AllocateFromBuffer<Real_t>(numElem8);
Real_t* fy_elem = AllocateFromBuffer<Real_t>(numElem8);
Real_t* fz_elem = AllocateFromBuffer<Real_t>(numElem8);
Kokkos::parallel_for(
"IntegrateStressForElems A", numElem, KOKKOS_LAMBDA(const int k) {
const Index_t* const elemToNode = &domain.nodelist(k, 0);
Real_t B[3][8];
Real_t x_local[8];
Real_t y_local[8];
Real_t z_local[8];
CollectDomainNodesToElemNodes(domain, elemToNode, x_local, y_local, z_local);
CalcElemShapeFunctionDerivatives(x_local, y_local, z_local, B, &determ[k]);
CalcElemNodeNormals(B[0], B[1], B[2], x_local, y_local, z_local);
SumElemStressesToNodeForces(B, sigxx[k], sigyy[k], sigzz[k], &fx_elem[k * 8],
&fy_elem[k * 8], &fz_elem[k * 8]);
});
int team_size = 1;
if(Kokkos::DefaultExecutionSpace().concurrency() > 1024) team_size = 128;
Kokkos::parallel_for(
"IntegrateStressForElems B",
Kokkos::TeamPolicy<>((numNode + 127) / 128, team_size, 2),
KOKKOS_LAMBDA(const typename Kokkos::TeamPolicy<>::member_type& team) {
const Index_t gnode_begin = team.league_rank() * 128;
const Index_t gnode_end =
(gnode_begin + 128 < numNode) ? gnode_begin + 128 : numNode;
Kokkos::parallel_for(
Kokkos::TeamThreadRange(team, gnode_begin, gnode_end),
[&](const Index_t& gnode) {
Index_t count = domain.nodeElemCount(gnode);
Index_t* cornerList = domain.nodeElemCornerList(gnode);
reduce_double3 f_tmp;
Kokkos::parallel_reduce(
Kokkos::ThreadVectorRange(team, count),
[&](const Index_t& i,
reduce_double3& tmp) { // vectorized with ivdep
Index_t elem = cornerList[i];
tmp.x += fx_elem[elem];
tmp.y += fy_elem[elem];
tmp.z += fz_elem[elem];
},
f_tmp);
Kokkos::single(Kokkos::PerThread(team), [&]() {
domain.fx(gnode) += f_tmp.x;
domain.fy(gnode) += f_tmp.y;
domain.fz(gnode) += f_tmp.z;
});
});
});
}
KOKKOS_INLINE_FUNCTION void
VoluDer(const Real_t x0, const Real_t x1, const Real_t x2, const Real_t x3,
const Real_t x4, const Real_t x5, const Real_t y0, const Real_t y1,
const Real_t y2, const Real_t y3, const Real_t y4, const Real_t y5,
const Real_t z0, const Real_t z1, const Real_t z2, const Real_t z3,
const Real_t z4, const Real_t z5, Real_t& dvdx, Real_t& dvdy, Real_t& dvdz)
{
const Real_t twelfth = Real_t(1.0) / Real_t(12.0);
dvdx = (y1 + y2) * (z0 + z1) - (y0 + y1) * (z1 + z2) + (y0 + y4) * (z3 + z4) -
(y3 + y4) * (z0 + z4) - (y2 + y5) * (z3 + z5) + (y3 + y5) * (z2 + z5);
dvdy = -(x1 + x2) * (z0 + z1) + (x0 + x1) * (z1 + z2) - (x0 + x4) * (z3 + z4) +
(x3 + x4) * (z0 + z4) + (x2 + x5) * (z3 + z5) - (x3 + x5) * (z2 + z5);
dvdz = -(y1 + y2) * (x0 + x1) + (y0 + y1) * (x1 + x2) - (y0 + y4) * (x3 + x4) +
(y3 + y4) * (x0 + x4) + (y2 + y5) * (x3 + x5) - (y3 + y5) * (x2 + x5);
dvdx *= twelfth;
dvdy *= twelfth;
dvdz *= twelfth;
}
KOKKOS_INLINE_FUNCTION
void
CalcElemVolumeDerivative(
const Int_t& i,
const Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>>& dvdx,
const Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>>& dvdy,
const Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>>& dvdz,
const Real_t x[8], const Real_t y[8], const Real_t z[8])
{
#pragma nounroll
for(int j = 0; j < 4; j++)
{
VoluDer(x[(j + 1) % 4], x[(j + 2) % 4], x[(j + 3) % 4], x[(j + 0) % 4 + 4],
x[(j + 1) % 4 + 4], x[(j + 3) % 4 + 4], y[(j + 1) % 4], y[(j + 2) % 4],
y[(j + 3) % 4], y[(j + 0) % 4 + 4], y[(j + 1) % 4 + 4],
y[(j + 3) % 4 + 4], z[(j + 1) % 4], z[(j + 2) % 4], z[(j + 3) % 4],
z[(j + 0) % 4 + 4], z[(j + 1) % 4 + 4], z[(j + 3) % 4 + 4], dvdx(i, j),
dvdy(i, j), dvdz(i, j));
VoluDer(x[(j + 3) % 4 + 4], x[(j + 2) % 4 + 4], x[(j + 1) % 4 + 4],
x[(j + 0) % 4], x[(j + 3) % 4], x[(j + 1) % 4], y[(j + 3) % 4 + 4],
y[(j + 2) % 4 + 4], y[(j + 1) % 4 + 4], y[(j + 0) % 4], y[(j + 3) % 4],
y[(j + 1) % 4], z[(j + 3) % 4 + 4], z[(j + 2) % 4 + 4],
z[(j + 1) % 4 + 4], z[(j + 0) % 4], z[(j + 3) % 4], z[(j + 1) % 4],
dvdx(i, j + 4), dvdy(i, j + 4), dvdz(i, j + 4));
}
}
KOKKOS_INLINE_FUNCTION
void
CalcElemFBHourglassForce(const Real_t* xd, const Real_t hourgam[][8],
const Real_t& coefficient, Real_t* hgfx)
{
Real_t hxx[4];
for(Index_t i = 0; i < 4; i++)
{
hxx[i] = hourgam[i][0] * xd[0] + hourgam[i][1] * xd[1] + hourgam[i][2] * xd[2] +
hourgam[i][3] * xd[3] + hourgam[i][4] * xd[4] + hourgam[i][5] * xd[5] +
hourgam[i][6] * xd[6] + hourgam[i][7] * xd[7];
}
for(Index_t i = 0; i < 8; i++)
{
hgfx[i] = coefficient * (hourgam[0][i] * hxx[0] + hourgam[1][i] * hxx[1] +
hourgam[2][i] * hxx[2] + hourgam[3][i] * hxx[3]);
}
}
struct Gamma
{
Real_t gamma[4][8];
Gamma()
{
gamma[0][0] = Real_t(1.);
gamma[0][1] = Real_t(1.);
gamma[0][2] = Real_t(-1.);
gamma[0][3] = Real_t(-1.);
gamma[0][4] = Real_t(-1.);
gamma[0][5] = Real_t(-1.);
gamma[0][6] = Real_t(1.);
gamma[0][7] = Real_t(1.);
gamma[1][0] = Real_t(1.);
gamma[1][1] = Real_t(-1.);
gamma[1][2] = Real_t(-1.);
gamma[1][3] = Real_t(1.);
gamma[1][4] = Real_t(-1.);
gamma[1][5] = Real_t(1.);
gamma[1][6] = Real_t(1.);
gamma[1][7] = Real_t(-1.);
gamma[2][0] = Real_t(1.);
gamma[2][1] = Real_t(-1.);
gamma[2][2] = Real_t(1.);
gamma[2][3] = Real_t(-1.);
gamma[2][4] = Real_t(1.);
gamma[2][5] = Real_t(-1.);
gamma[2][6] = Real_t(1.);
gamma[2][7] = Real_t(-1.);
gamma[3][0] = Real_t(-1.);
gamma[3][1] = Real_t(1.);
gamma[3][2] = Real_t(-1.);
gamma[3][3] = Real_t(1.);
gamma[3][4] = Real_t(1.);
gamma[3][5] = Real_t(-1.);
gamma[3][6] = Real_t(1.);
gamma[3][7] = Real_t(-1.);
}
};
static inline void
CalcFBHourglassForceForElems(
Domain& domain, Real_t* determ,
const Kokkos::View<const Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> x8n,
const Kokkos::View<const Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> y8n,
const Kokkos::View<const Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> z8n,
const Kokkos::View<const Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> dvdx,
const Kokkos::View<const Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> dvdy,
const Kokkos::View<const Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> dvdz,
Real_t hourg, Index_t numElem, Index_t numNode)
{
Index_t numElem8 = numElem * 8;
Real_t* fx_elem;
Real_t* fy_elem;
Real_t* fz_elem;
if(do_atomic == 0)
{
fx_elem = AllocateFromBuffer<Real_t>(numElem8);
fy_elem = AllocateFromBuffer<Real_t>(numElem8);
fz_elem = AllocateFromBuffer<Real_t>(numElem8);
}
Gamma G;
Int_t do_atomic_dev = do_atomic;
Kokkos::parallel_for(
"CalcFBHourglassForceForElems A", numElem, KOKKOS_LAMBDA(const int& i2) {
Real_t *fx_local, *fy_local, *fz_local;
Real_t hgfx[8];
Real_t hourgam[4][8];
Real_t xd1[8];
const Index_t* elemToNode = &domain.nodelist(i2, 0);
Index_t i3 = 8 * i2;
Real_t volinv = Real_t(1.0) / determ[i2];
for(Index_t i1 = 0; i1 < 4; ++i1)
{
Real_t hourmodx = 0.0;
for(int j = 0; j < 8; j++)
hourmodx += x8n(i2, j) * G.gamma[i1][j];
Real_t hourmody = 0.0;
for(int j = 0; j < 8; j++)
hourmody += y8n(i2, j) * G.gamma[i1][j];
Real_t hourmodz = 0.0;
for(int j = 0; j < 8; j++)
hourmodz += z8n(i2, j) * G.gamma[i1][j];
#pragma ivdep
for(int j = 0; j < 8; j++)
hourgam[i1][j] = G.gamma[i1][j] - volinv * (dvdx(i2, j) * hourmodx +
dvdy(i2, j) * hourmody +
dvdz(i2, j) * hourmodz);
}
const Real_t ss1 = domain.ss(i2);
const Real_t mass1 = domain.elemMass(i2);
const Real_t volume13 = CBRT(determ[i2]);
const Index_t n0si2 = elemToNode[0];
const Index_t n1si2 = elemToNode[1];
const Index_t n2si2 = elemToNode[2];
const Index_t n3si2 = elemToNode[3];
const Index_t n4si2 = elemToNode[4];
const Index_t n5si2 = elemToNode[5];
const Index_t n6si2 = elemToNode[6];
const Index_t n7si2 = elemToNode[7];
const Real_t coefficient = -hourg * Real_t(0.01) * ss1 * mass1 / volume13;
xd1[0] = domain.xd(n0si2);
xd1[1] = domain.xd(n1si2);
xd1[2] = domain.xd(n2si2);
xd1[3] = domain.xd(n3si2);
xd1[4] = domain.xd(n4si2);
xd1[5] = domain.xd(n5si2);
xd1[6] = domain.xd(n6si2);
xd1[7] = domain.xd(n7si2);
CalcElemFBHourglassForce(xd1, hourgam, coefficient, hgfx);
if(!do_atomic_dev)
{
fx_local = &fx_elem[i3];
fx_local[0] = hgfx[0];
fx_local[1] = hgfx[1];
fx_local[2] = hgfx[2];
fx_local[3] = hgfx[3];
fx_local[4] = hgfx[4];
fx_local[5] = hgfx[5];
fx_local[6] = hgfx[6];
fx_local[7] = hgfx[7];
}
else
{
Kokkos::atomic_add(&domain.fx(n0si2), hgfx[0]);
Kokkos::atomic_add(&domain.fx(n1si2), hgfx[1]);
Kokkos::atomic_add(&domain.fx(n2si2), hgfx[2]);
Kokkos::atomic_add(&domain.fx(n3si2), hgfx[3]);
Kokkos::atomic_add(&domain.fx(n4si2), hgfx[4]);
Kokkos::atomic_add(&domain.fx(n5si2), hgfx[5]);
Kokkos::atomic_add(&domain.fx(n6si2), hgfx[6]);
Kokkos::atomic_add(&domain.fx(n7si2), hgfx[7]);
}
xd1[0] = domain.yd(n0si2);
xd1[1] = domain.yd(n1si2);
xd1[2] = domain.yd(n2si2);
xd1[3] = domain.yd(n3si2);
xd1[4] = domain.yd(n4si2);
xd1[5] = domain.yd(n5si2);
xd1[6] = domain.yd(n6si2);
xd1[7] = domain.yd(n7si2);
CalcElemFBHourglassForce(xd1, hourgam, coefficient, hgfx);
if(!do_atomic_dev)
{
fy_local = &fy_elem[i3];
fy_local[0] = hgfx[0];
fy_local[1] = hgfx[1];
fy_local[2] = hgfx[2];
fy_local[3] = hgfx[3];
fy_local[4] = hgfx[4];
fy_local[5] = hgfx[5];
fy_local[6] = hgfx[6];
fy_local[7] = hgfx[7];
}
else
{
Kokkos::atomic_add(&domain.fy(n0si2), hgfx[0]);
Kokkos::atomic_add(&domain.fy(n1si2), hgfx[1]);
Kokkos::atomic_add(&domain.fy(n2si2), hgfx[2]);
Kokkos::atomic_add(&domain.fy(n3si2), hgfx[3]);
Kokkos::atomic_add(&domain.fy(n4si2), hgfx[4]);
Kokkos::atomic_add(&domain.fy(n5si2), hgfx[5]);
Kokkos::atomic_add(&domain.fy(n6si2), hgfx[6]);
Kokkos::atomic_add(&domain.fy(n7si2), hgfx[7]);
}
xd1[0] = domain.zd(n0si2);
xd1[1] = domain.zd(n1si2);
xd1[2] = domain.zd(n2si2);
xd1[3] = domain.zd(n3si2);
xd1[4] = domain.zd(n4si2);
xd1[5] = domain.zd(n5si2);
xd1[6] = domain.zd(n6si2);
xd1[7] = domain.zd(n7si2);
CalcElemFBHourglassForce(xd1, hourgam, coefficient, hgfx);
if(!do_atomic_dev)
{
fz_local = &fz_elem[i3];
fz_local[0] = hgfx[0];
fz_local[1] = hgfx[1];
fz_local[2] = hgfx[2];
fz_local[3] = hgfx[3];
fz_local[4] = hgfx[4];
fz_local[5] = hgfx[5];
fz_local[6] = hgfx[6];
fz_local[7] = hgfx[7];
}
else
{
Kokkos::atomic_add(&domain.fz(n0si2), hgfx[0]);
Kokkos::atomic_add(&domain.fz(n1si2), hgfx[1]);
Kokkos::atomic_add(&domain.fz(n2si2), hgfx[2]);
Kokkos::atomic_add(&domain.fz(n3si2), hgfx[3]);
Kokkos::atomic_add(&domain.fz(n4si2), hgfx[4]);
Kokkos::atomic_add(&domain.fz(n5si2), hgfx[5]);
Kokkos::atomic_add(&domain.fz(n6si2), hgfx[6]);
Kokkos::atomic_add(&domain.fz(n7si2), hgfx[7]);
}
});
if(!do_atomic)
{
int team_size = 1;
if(Kokkos::DefaultExecutionSpace().concurrency() > 1024) team_size = 128;
Kokkos::parallel_for(
"CalcFBHourglassForceForElems B",
Kokkos::TeamPolicy<>((numNode + 127) / 128, team_size, 2),
KOKKOS_LAMBDA(const typename Kokkos::TeamPolicy<>::member_type& team) {
const Index_t gnode_begin = team.league_rank() * 128;
const Index_t gnode_end =
(gnode_begin + 128 < numNode) ? gnode_begin + 128 : numNode;
Kokkos::parallel_for(
Kokkos::TeamThreadRange(team, gnode_begin, gnode_end),
[&](const Index_t& gnode) {
Index_t count = domain.nodeElemCount(gnode);
Index_t* cornerList = domain.nodeElemCornerList(gnode);
reduce_double3 f_tmp;
Kokkos::parallel_reduce(
Kokkos::ThreadVectorRange(team, count),
[&](const Index_t& i,
reduce_double3& tmp) { // vectorized with ivdep
Index_t elem = cornerList[i];
tmp.x += fx_elem[elem];
tmp.y += fy_elem[elem];
tmp.z += fz_elem[elem];
},
f_tmp);
Kokkos::single(Kokkos::PerThread(team), [&]() {
domain.fx(gnode) += f_tmp.x;
domain.fy(gnode) += f_tmp.y;
domain.fz(gnode) += f_tmp.z;
});
});
});
}
}
static inline void
CalcHourglassControlForElems(Domain& domain, Real_t determ[], Real_t hgcoef)
{
Index_t numElem = domain.numElem();
Index_t numElem8 = numElem * 8;
ResizeBuffer((numElem8 * sizeof(Real_t) + 4096) * (do_atomic ? 6 : 9));
Real_t* dvdx = AllocateFromBuffer<Real_t>(numElem8);
Real_t* dvdy = AllocateFromBuffer<Real_t>(numElem8);
Real_t* dvdz = AllocateFromBuffer<Real_t>(numElem8);
Real_t* x8n = AllocateFromBuffer<Real_t>(numElem8);
Real_t* y8n = AllocateFromBuffer<Real_t>(numElem8);
Real_t* z8n = AllocateFromBuffer<Real_t>(numElem8);
Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> v_x8n(x8n, numElem,
8);
Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> v_y8n(y8n, numElem,
8);
Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> v_z8n(z8n, numElem,
8);
Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> v_dvdx(dvdx, numElem,
8);
Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> v_dvdy(dvdy, numElem,
8);
Kokkos::View<Real_t**, Kokkos::MemoryTraits<Kokkos::Unmanaged>> v_dvdz(dvdz, numElem,
8);
int error = 0;
Kokkos::parallel_reduce(
"CalcHourglassControlForElems", numElem,
KOKKOS_LAMBDA(const int i, int& err) {
Real_t x1[8], y1[8], z1[8];
Index_t* elemToNode = &domain.nodelist(i, 0);
CollectDomainNodesToElemNodes(domain, elemToNode, x1, y1, z1);
CalcElemVolumeDerivative(i, v_dvdx, v_dvdy, v_dvdz, x1, y1, z1);
for(Index_t ii = 0; ii < 8; ++ii)
{
v_x8n(i, ii) = x1[ii];
v_y8n(i, ii) = y1[ii];
v_z8n(i, ii) = z1[ii];
}
determ[i] = domain.volo(i) * domain.v(i);
if(domain.v(i) <= Real_t(0.0))
{
err++;
}
},
error);
if(error)
#if USE_MPI
MPI_Abort(MPI_COMM_WORLD, VolumeError);
#else
exit(VolumeError);
#endif
if(hgcoef > Real_t(0.))
{
CalcFBHourglassForceForElems(domain, determ, v_x8n, v_y8n, v_z8n, v_dvdx, v_dvdy,
v_dvdz, hgcoef, numElem, domain.numNode());
}
return;
}
static inline void
CalcVolumeForceForElems(Domain& domain)
{
Index_t numElem = domain.numElem();
if(numElem != 0)
{
Real_t hgcoef = domain.hgcoef();
Kokkos::View<Real_t*> sigxx("sigxx", numElem);
Kokkos::View<Real_t*> sigyy("sigyy", numElem);
Kokkos::View<Real_t*> sigzz("sigzz", numElem);
Kokkos::View<Real_t*> determ("determ", numElem);
InitStressTermsForElems(domain, sigxx.data(), sigyy.data(), sigzz.data(),
numElem);
IntegrateStressForElems(domain, sigxx.data(), sigyy.data(), sigzz.data(),
determ.data(), numElem, domain.numNode());
// check for negative element volume
int error = 0;
Kokkos::parallel_reduce(
"CalcVolumeForceForElems", numElem,
KOKKOS_LAMBDA(const int k, int& err) {
if(determ[k] <= Real_t(0.0))
{
err++;
}
},
error);
if(error)
#if USE_MPI
MPI_Abort(MPI_COMM_WORLD, VolumeError);
#else
exit(VolumeError);
#endif
CalcHourglassControlForElems(domain, determ.data(), hgcoef);
}
}
static inline void
CalcForceForNodes(Domain& domain)
{
Index_t numNode = domain.numNode();
#if USE_MPI
CommRecv(domain, MSG_COMM_SBN, 3, domain.sizeX() + 1, domain.sizeY() + 1,
domain.sizeZ() + 1, true, false);
#endif
Kokkos::parallel_for(
"CalcForceForNodes", numNode, KOKKOS_LAMBDA(const int i) {
domain.fx(i) = Real_t(0.0);
domain.fy(i) = Real_t(0.0);
domain.fz(i) = Real_t(0.0);
});
CalcVolumeForceForElems(domain);
#if USE_MPI
Domain_member fieldData[3];
fieldData[0] = &Domain::fx;
fieldData[1] = &Domain::fy;
fieldData[2] = &Domain::fz;
CommSend(domain, MSG_COMM_SBN, 3, fieldData, domain.sizeX() + 1, domain.sizeY() + 1,
domain.sizeZ() + 1, true, false);
CommSBN(domain, 3, fieldData);
#endif
}
static inline void
CalcAccelerationForNodes(Domain& domain, Index_t numNode)
{
Kokkos::parallel_for(
"CalcAccelerationForNodes", numNode, KOKKOS_LAMBDA(const int i) {
domain.xdd(i) = domain.fx(i) / domain.nodalMass(i);
domain.ydd(i) = domain.fy(i) / domain.nodalMass(i);
domain.zdd(i) = domain.fz(i) / domain.nodalMass(i);
});
}
static inline void
ApplyAccelerationBoundaryConditionsForNodes(Domain& domain)
{
Index_t size = domain.sizeX();
Index_t numNodeBC = (size + 1) * (size + 1);
if(!domain.symmXempty() != 0)
{
Kokkos::parallel_for(
"ApplyAccelerationBoundaryConditionsForNodes A", numNodeBC,
KOKKOS_LAMBDA(const int i) { domain.xdd(domain.symmX(i)) = Real_t(0.0); });
}
if(!domain.symmYempty() != 0)
{
Kokkos::parallel_for(
"ApplyAccelerationBoundaryConditionsForNodes B", numNodeBC,
KOKKOS_LAMBDA(const int i) { domain.ydd(domain.symmY(i)) = Real_t(0.0); });
}
if(!domain.symmZempty() != 0)
{
Kokkos::parallel_for(
"ApplyAccelerationBoundaryConditionsForNodes C", numNodeBC,
KOKKOS_LAMBDA(const int i) { domain.zdd(domain.symmZ(i)) = Real_t(0.0); });
}
}
static inline void
CalcVelocityForNodes(Domain& domain, const Real_t dt, const Real_t u_cut, Index_t numNode)
{
Kokkos::parallel_for(
"CalcVelocityForNodes", numNode, KOKKOS_LAMBDA(const int i) {
Real_t xdtmp, ydtmp, zdtmp;
xdtmp = domain.xd(i) + domain.xdd(i) * dt;
if(FABS(xdtmp) < u_cut) xdtmp = Real_t(0.0);
domain.xd(i) = xdtmp;
ydtmp = domain.yd(i) + domain.ydd(i) * dt;
if(FABS(ydtmp) < u_cut) ydtmp = Real_t(0.0);
domain.yd(i) = ydtmp;
zdtmp = domain.zd(i) + domain.zdd(i) * dt;
if(FABS(zdtmp) < u_cut) zdtmp = Real_t(0.0);
domain.zd(i) = zdtmp;
});
}
static inline void
CalcPositionForNodes(Domain& domain, const Real_t dt, Index_t numNode)
{
Kokkos::parallel_for(
"CalcPositionForNodes", numNode, KOKKOS_LAMBDA(const int i) {
domain.x(i) += domain.xd(i) * dt;
domain.y(i) += domain.yd(i) * dt;
domain.z(i) += domain.zd(i) * dt;
});
}
static inline void
LagrangeNodal(Domain& domain)
{
#ifdef SEDOV_SYNC_POS_VEL_EARLY
Domain_member fieldData[6];
#endif
const Real_t delt = domain.deltatime();
Real_t u_cut = domain.u_cut();
CalcForceForNodes(domain);
#if USE_MPI
# ifdef SEDOV_SYNC_POS_VEL_EARLY
CommRecv(domain, MSG_SYNC_POS_VEL, 6, domain.sizeX() + 1, domain.sizeY() + 1,
domain.sizeZ() + 1, false, false);
# endif
#endif
CalcAccelerationForNodes(domain, domain.numNode());
ApplyAccelerationBoundaryConditionsForNodes(domain);
CalcVelocityForNodes(domain, delt, u_cut, domain.numNode());
CalcPositionForNodes(domain, delt, domain.numNode());
#if USE_MPI
# ifdef SEDOV_SYNC_POS_VEL_EARLY
fieldData[0] = &Domain::x;
fieldData[1] = &Domain::y;
fieldData[2] = &Domain::z;
fieldData[3] = &Domain::xd;
fieldData[4] = &Domain::yd;
fieldData[5] = &Domain::zd;
CommSend(domain, MSG_SYNC_POS_VEL, 6, fieldData, domain.sizeX() + 1,
domain.sizeY() + 1, domain.sizeZ() + 1, false, false);
CommSyncPosVel(domain);
# endif
#endif
return;
}
KOKKOS_INLINE_FUNCTION Real_t
CalcElemVolume(const Real_t x0, const Real_t x1, const Real_t x2, const Real_t x3,
const Real_t x4, const Real_t x5, const Real_t x6, const Real_t x7,
const Real_t y0, const Real_t y1, const Real_t y2, const Real_t y3,
const Real_t y4, const Real_t y5, const Real_t y6, const Real_t y7,
const Real_t z0, const Real_t z1, const Real_t z2, const Real_t z3,
const Real_t z4, const Real_t z5, const Real_t z6, const Real_t z7)
{
Real_t twelveth = Real_t(1.0) / Real_t(12.0);
Real_t dx61 = x6 - x1;
Real_t dy61 = y6 - y1;
Real_t dz61 = z6 - z1;
Real_t dx70 = x7 - x0;
Real_t dy70 = y7 - y0;
Real_t dz70 = z7 - z0;
Real_t dx63 = x6 - x3;
Real_t dy63 = y6 - y3;
Real_t dz63 = z6 - z3;
Real_t dx20 = x2 - x0;
Real_t dy20 = y2 - y0;
Real_t dz20 = z2 - z0;
Real_t dx50 = x5 - x0;
Real_t dy50 = y5 - y0;
Real_t dz50 = z5 - z0;
Real_t dx64 = x6 - x4;
Real_t dy64 = y6 - y4;
Real_t dz64 = z6 - z4;
Real_t dx31 = x3 - x1;
Real_t dy31 = y3 - y1;
Real_t dz31 = z3 - z1;
Real_t dx72 = x7 - x2;
Real_t dy72 = y7 - y2;
Real_t dz72 = z7 - z2;
Real_t dx43 = x4 - x3;
Real_t dy43 = y4 - y3;
Real_t dz43 = z4 - z3;
Real_t dx57 = x5 - x7;
Real_t dy57 = y5 - y7;
Real_t dz57 = z5 - z7;
Real_t dx14 = x1 - x4;
Real_t dy14 = y1 - y4;
Real_t dz14 = z1 - z4;
Real_t dx25 = x2 - x5;
Real_t dy25 = y2 - y5;
Real_t dz25 = z2 - z5;
#define TRIPLE_PRODUCT(x1, y1, z1, x2, y2, z2, x3, y3, z3) \
((x1) * ((y2) * (z3) - (z2) * (y3)) + (x2) * ((z1) * (y3) - (y1) * (z3)) + \
(x3) * ((y1) * (z2) - (z1) * (y2)))
Real_t volume = TRIPLE_PRODUCT(dx31 + dx72, dx63, dx20, dy31 + dy72, dy63, dy20,
dz31 + dz72, dz63, dz20) +
TRIPLE_PRODUCT(dx43 + dx57, dx64, dx70, dy43 + dy57, dy64, dy70,
dz43 + dz57, dz64, dz70) +
TRIPLE_PRODUCT(dx14 + dx25, dx61, dx50, dy14 + dy25, dy61, dy50,
dz14 + dz25, dz61, dz50);
#undef TRIPLE_PRODUCT
volume *= twelveth;
return volume;
}
KOKKOS_INLINE_FUNCTION
Real_t
CalcElemVolume(const Real_t x[8], const Real_t y[8], const Real_t z[8])
{
return CalcElemVolume(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], y[0], y[1],
y[2], y[3], y[4], y[5], y[6], y[7], z[0], z[1], z[2], z[3],
z[4], z[5], z[6], z[7]);
}
KOKKOS_INLINE_FUNCTION
Real_t
AreaFace(const Real_t x0, const Real_t x1, const Real_t x2, const Real_t x3,
const Real_t y0, const Real_t y1, const Real_t y2, const Real_t y3,
const Real_t z0, const Real_t z1, const Real_t z2, const Real_t z3)
{
Real_t fx = (x2 - x0) - (x3 - x1);
Real_t fy = (y2 - y0) - (y3 - y1);
Real_t fz = (z2 - z0) - (z3 - z1);
Real_t gx = (x2 - x0) + (x3 - x1);
Real_t gy = (y2 - y0) + (y3 - y1);
Real_t gz = (z2 - z0) + (z3 - z1);
Real_t area = (fx * fx + fy * fy + fz * fz) * (gx * gx + gy * gy + gz * gz) -
(fx * gx + fy * gy + fz * gz) * (fx * gx + fy * gy + fz * gz);
return area;
}
KOKKOS_INLINE_FUNCTION Real_t
CalcElemCharacteristicLength(const Real_t x[8], const Real_t y[8], const Real_t z[8],
const Real_t volume)
{
Real_t a, charLength = Real_t(0.0);
a = AreaFace(x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3], z[0], z[1], z[2], z[3]);
charLength = MAX(a, charLength);
a = AreaFace(x[4], x[5], x[6], x[7], y[4], y[5], y[6], y[7], z[4], z[5], z[6], z[7]);
charLength = MAX(a, charLength);
a = AreaFace(x[0], x[1], x[5], x[4], y[0], y[1], y[5], y[4], z[0], z[1], z[5], z[4]);
charLength = MAX(a, charLength);
a = AreaFace(x[1], x[2], x[6], x[5], y[1], y[2], y[6], y[5], z[1], z[2], z[6], z[5]);
charLength = MAX(a, charLength);
a = AreaFace(x[2], x[3], x[7], x[6], y[2], y[3], y[7], y[6], z[2], z[3], z[7], z[6]);
charLength = MAX(a, charLength);
a = AreaFace(x[3], x[0], x[4], x[7], y[3], y[0], y[4], y[7], z[3], z[0], z[4], z[7]);
charLength = MAX(a, charLength);
charLength = Real_t(4.0) * volume / SQRT(charLength);
return charLength;
}
KOKKOS_INLINE_FUNCTION void
CalcElemVelocityGradient(const Real_t* const xvel, const Real_t* const yvel,
const Real_t* const zvel, const Real_t b[][8], const Real_t detJ,
Real_t* const d)
{
const Real_t inv_detJ = Real_t(1.0) / detJ;
Real_t dyddx, dxddy, dzddx, dxddz, dzddy, dyddz;
const Real_t* const pfx = b[0];
const Real_t* const pfy = b[1];
const Real_t* const pfz = b[2];
d[0] = inv_detJ * (pfx[0] * (xvel[0] - xvel[6]) + pfx[1] * (xvel[1] - xvel[7]) +
pfx[2] * (xvel[2] - xvel[4]) + pfx[3] * (xvel[3] - xvel[5]));
d[1] = inv_detJ * (pfy[0] * (yvel[0] - yvel[6]) + pfy[1] * (yvel[1] - yvel[7]) +
pfy[2] * (yvel[2] - yvel[4]) + pfy[3] * (yvel[3] - yvel[5]));
d[2] = inv_detJ * (pfz[0] * (zvel[0] - zvel[6]) + pfz[1] * (zvel[1] - zvel[7]) +
pfz[2] * (zvel[2] - zvel[4]) + pfz[3] * (zvel[3] - zvel[5]));
dyddx = inv_detJ * (pfx[0] * (yvel[0] - yvel[6]) + pfx[1] * (yvel[1] - yvel[7]) +
pfx[2] * (yvel[2] - yvel[4]) + pfx[3] * (yvel[3] - yvel[5]));
dxddy = inv_detJ * (pfy[0] * (xvel[0] - xvel[6]) + pfy[1] * (xvel[1] - xvel[7]) +
pfy[2] * (xvel[2] - xvel[4]) + pfy[3] * (xvel[3] - xvel[5]));
dzddx = inv_detJ * (pfx[0] * (zvel[0] - zvel[6]) + pfx[1] * (zvel[1] - zvel[7]) +
pfx[2] * (zvel[2] - zvel[4]) + pfx[3] * (zvel[3] - zvel[5]));
dxddz = inv_detJ * (pfz[0] * (xvel[0] - xvel[6]) + pfz[1] * (xvel[1] - xvel[7]) +
pfz[2] * (xvel[2] - xvel[4]) + pfz[3] * (xvel[3] - xvel[5]));
dzddy = inv_detJ * (pfy[0] * (zvel[0] - zvel[6]) + pfy[1] * (zvel[1] - zvel[7]) +
pfy[2] * (zvel[2] - zvel[4]) + pfy[3] * (zvel[3] - zvel[5]));
dyddz = inv_detJ * (pfz[0] * (yvel[0] - yvel[6]) + pfz[1] * (yvel[1] - yvel[7]) +
pfz[2] * (yvel[2] - yvel[4]) + pfz[3] * (yvel[3] - yvel[5]));
d[5] = Real_t(.5) * (dxddy + dyddx);
d[4] = Real_t(.5) * (dxddz + dzddx);
d[3] = Real_t(.5) * (dzddy + dyddz);
}
void
CalcKinematicsForElems(Domain& domain, Real_t deltaTime, Index_t numElem)
{
Kokkos::parallel_for(
"CalcKinematicsForElems", numElem, KOKKOS_LAMBDA(const int k) {
Real_t B[3][8];
Real_t D[6];
Real_t x_local[8];
Real_t y_local[8];
Real_t z_local[8];
Real_t xd_local[8];
Real_t yd_local[8];
Real_t zd_local[8];
Real_t detJ = Real_t(0.0);
Real_t volume;
Real_t relativeVolume;
const Index_t* const elemToNode = &domain.nodelist(k, 0);
CollectDomainNodesToElemNodes(domain, elemToNode, x_local, y_local, z_local);
volume = CalcElemVolume(x_local, y_local, z_local);
relativeVolume = volume / domain.volo(k);
domain.vnew(k) = relativeVolume;
domain.delv(k) = relativeVolume - domain.v(k);
domain.arealg(k) =
CalcElemCharacteristicLength(x_local, y_local, z_local, volume);
for(Index_t lnode = 0; lnode < 8; ++lnode)
{
Index_t gnode = elemToNode[lnode];
xd_local[lnode] = domain.c_xd(gnode);
yd_local[lnode] = domain.c_yd(gnode);
zd_local[lnode] = domain.c_zd(gnode);
}
Real_t dt2 = Real_t(0.5) * deltaTime;
for(Index_t j = 0; j < 8; ++j)
{
x_local[j] -= dt2 * xd_local[j];
y_local[j] -= dt2 * yd_local[j];
z_local[j] -= dt2 * zd_local[j];
}
CalcElemShapeFunctionDerivatives(x_local, y_local, z_local, B, &detJ);
CalcElemVelocityGradient(xd_local, yd_local, zd_local, B, detJ, D);
domain.dxx(k) = D[0];
domain.dyy(k) = D[1];
domain.dzz(k) = D[2];
});
}
static inline void
CalcLagrangeElements(Domain& domain)
{
Index_t numElem = domain.numElem();
if(numElem > 0)
{
const Real_t deltatime = domain.deltatime();
domain.AllocateStrains(numElem);
CalcKinematicsForElems(domain, deltatime, numElem);
int error = 0;
Kokkos::parallel_reduce(
"CalcLagrangeElements", numElem,
KOKKOS_LAMBDA(const int k, int& err) {
Real_t vdov = domain.dxx(k) + domain.dyy(k) + domain.dzz(k);
Real_t vdovthird = vdov / Real_t(3.0);
domain.vdov(k) = vdov;
domain.dxx(k) -= vdovthird;
domain.dyy(k) -= vdovthird;
domain.dzz(k) -= vdovthird;
if(domain.vnew(k) <= Real_t(0.0))
{
err++;
}
},
error);
if(error)
#if USE_MPI
MPI_Abort(MPI_COMM_WORLD, VolumeError);
#else
exit(VolumeError);
#endif
domain.DeallocateStrains();
}
}
static inline void
CalcMonotonicQGradientsForElems(Domain& domain)
{
Index_t numElem = domain.numElem();
Kokkos::parallel_for(
"CalcMonotonicQGradientsForElems", numElem, KOKKOS_LAMBDA(const int i) {
const Real_t ptiny = Real_t(1.e-36);
Real_t ax, ay, az;
Real_t dxv, dyv, dzv;
const Index_t* elemToNode = &domain.nodelist(i, 0);
Index_t n0 = elemToNode[0];
Index_t n1 = elemToNode[1];
Index_t n2 = elemToNode[2];
Index_t n3 = elemToNode[3];
Index_t n4 = elemToNode[4];
Index_t n5 = elemToNode[5];
Index_t n6 = elemToNode[6];
Index_t n7 = elemToNode[7];
Real_t x0 = domain.x(n0);
Real_t x1 = domain.x(n1);
Real_t x2 = domain.x(n2);
Real_t x3 = domain.x(n3);
Real_t x4 = domain.x(n4);
Real_t x5 = domain.x(n5);
Real_t x6 = domain.x(n6);
Real_t x7 = domain.x(n7);
Real_t y0 = domain.y(n0);
Real_t y1 = domain.y(n1);
Real_t y2 = domain.y(n2);
Real_t y3 = domain.y(n3);
Real_t y4 = domain.y(n4);
Real_t y5 = domain.y(n5);
Real_t y6 = domain.y(n6);
Real_t y7 = domain.y(n7);
Real_t z0 = domain.z(n0);
Real_t z1 = domain.z(n1);
Real_t z2 = domain.z(n2);
Real_t z3 = domain.z(n3);
Real_t z4 = domain.z(n4);
Real_t z5 = domain.z(n5);
Real_t z6 = domain.z(n6);
Real_t z7 = domain.z(n7);
Real_t xv0 = domain.xd(n0);
Real_t xv1 = domain.xd(n1);
Real_t xv2 = domain.xd(n2);
Real_t xv3 = domain.xd(n3);
Real_t xv4 = domain.xd(n4);
Real_t xv5 = domain.xd(n5);
Real_t xv6 = domain.xd(n6);
Real_t xv7 = domain.xd(n7);
Real_t yv0 = domain.yd(n0);
Real_t yv1 = domain.yd(n1);
Real_t yv2 = domain.yd(n2);
Real_t yv3 = domain.yd(n3);
Real_t yv4 = domain.yd(n4);
Real_t yv5 = domain.yd(n5);
Real_t yv6 = domain.yd(n6);
Real_t yv7 = domain.yd(n7);
Real_t zv0 = domain.zd(n0);
Real_t zv1 = domain.zd(n1);
Real_t zv2 = domain.zd(n2);
Real_t zv3 = domain.zd(n3);
Real_t zv4 = domain.zd(n4);
Real_t zv5 = domain.zd(n5);
Real_t zv6 = domain.zd(n6);
Real_t zv7 = domain.zd(n7);
Real_t vol = domain.volo(i) * domain.vnew(i);
Real_t norm = Real_t(1.0) / (vol + ptiny);
Real_t dxj = Real_t(-0.25) * ((x0 + x1 + x5 + x4) - (x3 + x2 + x6 + x7));
Real_t dyj = Real_t(-0.25) * ((y0 + y1 + y5 + y4) - (y3 + y2 + y6 + y7));
Real_t dzj = Real_t(-0.25) * ((z0 + z1 + z5 + z4) - (z3 + z2 + z6 + z7));
Real_t dxi = Real_t(0.25) * ((x1 + x2 + x6 + x5) - (x0 + x3 + x7 + x4));
Real_t dyi = Real_t(0.25) * ((y1 + y2 + y6 + y5) - (y0 + y3 + y7 + y4));
Real_t dzi = Real_t(0.25) * ((z1 + z2 + z6 + z5) - (z0 + z3 + z7 + z4));
Real_t dxk = Real_t(0.25) * ((x4 + x5 + x6 + x7) - (x0 + x1 + x2 + x3));
Real_t dyk = Real_t(0.25) * ((y4 + y5 + y6 + y7) - (y0 + y1 + y2 + y3));
Real_t dzk = Real_t(0.25) * ((z4 + z5 + z6 + z7) - (z0 + z1 + z2 + z3));
ax = dyi * dzj - dzi * dyj;
ay = dzi * dxj - dxi * dzj;
az = dxi * dyj - dyi * dxj;
domain.delx_zeta(i) = vol / SQRT(ax * ax + ay * ay + az * az + ptiny);
ax *= norm;
ay *= norm;
az *= norm;
dxv = Real_t(0.25) * ((xv4 + xv5 + xv6 + xv7) - (xv0 + xv1 + xv2 + xv3));
dyv = Real_t(0.25) * ((yv4 + yv5 + yv6 + yv7) - (yv0 + yv1 + yv2 + yv3));
dzv = Real_t(0.25) * ((zv4 + zv5 + zv6 + zv7) - (zv0 + zv1 + zv2 + zv3));
domain.delv_zeta(i) = ax * dxv + ay * dyv + az * dzv;
ax = dyj * dzk - dzj * dyk;
ay = dzj * dxk - dxj * dzk;
az = dxj * dyk - dyj * dxk;
domain.delx_xi(i) = vol / SQRT(ax * ax + ay * ay + az * az + ptiny);
ax *= norm;
ay *= norm;
az *= norm;
dxv = Real_t(0.25) * ((xv1 + xv2 + xv6 + xv5) - (xv0 + xv3 + xv7 + xv4));
dyv = Real_t(0.25) * ((yv1 + yv2 + yv6 + yv5) - (yv0 + yv3 + yv7 + yv4));
dzv = Real_t(0.25) * ((zv1 + zv2 + zv6 + zv5) - (zv0 + zv3 + zv7 + zv4));
domain.delv_xi(i) = ax * dxv + ay * dyv + az * dzv;
ax = dyk * dzi - dzk * dyi;
ay = dzk * dxi - dxk * dzi;
az = dxk * dyi - dyk * dxi;
domain.delx_eta(i) = vol / SQRT(ax * ax + ay * ay + az * az + ptiny);
ax *= norm;
ay *= norm;
az *= norm;
dxv = Real_t(-0.25) * ((xv0 + xv1 + xv5 + xv4) - (xv3 + xv2 + xv6 + xv7));
dyv = Real_t(-0.25) * ((yv0 + yv1 + yv5 + yv4) - (yv3 + yv2 + yv6 + yv7));
dzv = Real_t(-0.25) * ((zv0 + zv1 + zv5 + zv4) - (zv3 + zv2 + zv6 + zv7));
domain.delv_eta(i) = ax * dxv + ay * dyv + az * dzv;
});
}
static inline void
CalcMonotonicQRegionForElems(Domain& domain, Int_t r, Real_t ptiny)
{
Real_t monoq_limiter_mult = domain.monoq_limiter_mult();
Real_t monoq_max_slope = domain.monoq_max_slope();
Real_t qlc_monoq = domain.qlc_monoq();
Real_t qqc_monoq = domain.qqc_monoq();
Kokkos::parallel_for(
"CalcMonotonicQRegionForElems", domain.regElemSize(r),
KOKKOS_LAMBDA(const int i) {
Index_t ielem = domain.regElemlist(r, i);
Real_t qlin, qquad;
Real_t phixi, phieta, phizeta;
Int_t bcMask = domain.elemBC(ielem);
Real_t delvm = 0.0, delvp = 0.0;
Real_t norm = Real_t(1.) / (domain.delv_xi(ielem) + ptiny);
switch(bcMask & XI_M)
{
case XI_M_COMM:
case 0: delvm = domain.delv_xi(domain.lxim(ielem)); break;
case XI_M_SYMM: delvm = domain.delv_xi(ielem); break;
case XI_M_FREE: delvm = Real_t(0.0); break;
default:
printf("Error in switch at %s line %d\n", __FILE__, __LINE__);
delvm = 0;
break;
}
switch(bcMask & XI_P)
{
case XI_P_COMM:
case 0: delvp = domain.delv_xi(domain.lxip(ielem)); break;
case XI_P_SYMM: delvp = domain.delv_xi(ielem); break;
case XI_P_FREE: delvp = Real_t(0.0); break;
default:
printf("Error in switch at %s line %d\n", __FILE__, __LINE__);
delvp = 0;
break;
}
delvm = delvm * norm;
delvp = delvp * norm;
phixi = Real_t(.5) * (delvm + delvp);
delvm *= monoq_limiter_mult;
delvp *= monoq_limiter_mult;
if(delvm < phixi) phixi = delvm;
if(delvp < phixi) phixi = delvp;
if(phixi < Real_t(0.)) phixi = Real_t(0.);
if(phixi > monoq_max_slope) phixi = monoq_max_slope;
norm = Real_t(1.) / (domain.delv_eta(ielem) + ptiny);
switch(bcMask & ETA_M)
{
case ETA_M_COMM:
case 0: delvm = domain.delv_eta(domain.letam(ielem)); break;
case ETA_M_SYMM: delvm = domain.delv_eta(ielem); break;
case ETA_M_FREE: delvm = Real_t(0.0); break;
default:
printf("Error in switch at %s line %d\n", __FILE__, __LINE__);
delvm = 0;
break;
}
switch(bcMask & ETA_P)
{
case ETA_P_COMM:
case 0: delvp = domain.delv_eta(domain.letap(ielem)); break;
case ETA_P_SYMM: delvp = domain.delv_eta(ielem); break;
case ETA_P_FREE: delvp = Real_t(0.0); break;
default:
printf("Error in switch at %s line %d\n", __FILE__, __LINE__);
delvp = 0;
break;
}
delvm = delvm * norm;
delvp = delvp * norm;
phieta = Real_t(.5) * (delvm + delvp);
delvm *= monoq_limiter_mult;
delvp *= monoq_limiter_mult;
if(delvm < phieta) phieta = delvm;
if(delvp < phieta) phieta = delvp;
if(phieta < Real_t(0.)) phieta = Real_t(0.);
if(phieta > monoq_max_slope) phieta = monoq_max_slope;
norm = Real_t(1.) / (domain.delv_zeta(ielem) + ptiny);
switch(bcMask & ZETA_M)
{
case ZETA_M_COMM:
case 0: delvm = domain.delv_zeta(domain.lzetam(ielem)); break;
case ZETA_M_SYMM: delvm = domain.delv_zeta(ielem); break;
case ZETA_M_FREE: delvm = Real_t(0.0); break;
default:
printf("Error in switch at %s line %d\n", __FILE__, __LINE__);
delvm = 0;
break;
}
switch(bcMask & ZETA_P)
{
case ZETA_P_COMM:
case 0: delvp = domain.delv_zeta(domain.lzetap(ielem)); break;
case ZETA_P_SYMM: delvp = domain.delv_zeta(ielem); break;
case ZETA_P_FREE: delvp = Real_t(0.0); break;
default:
printf("Error in switch at %s line %d\n", __FILE__, __LINE__);
delvp = 0;
break;
}
delvm = delvm * norm;
delvp = delvp * norm;
phizeta = Real_t(.5) * (delvm + delvp);
delvm *= monoq_limiter_mult;
delvp *= monoq_limiter_mult;
if(delvm < phizeta) phizeta = delvm;
if(delvp < phizeta) phizeta = delvp;
if(phizeta < Real_t(0.)) phizeta = Real_t(0.);
if(phizeta > monoq_max_slope) phizeta = monoq_max_slope;
if(domain.vdov(ielem) > Real_t(0.))
{
qlin = Real_t(0.);
qquad = Real_t(0.);
}
else
{
Real_t delvxxi = domain.delv_xi(ielem) * domain.delx_xi(ielem);
Real_t delvxeta = domain.delv_eta(ielem) * domain.delx_eta(ielem);
Real_t delvxzeta = domain.delv_zeta(ielem) * domain.delx_zeta(ielem);
if(delvxxi > Real_t(0.)) delvxxi = Real_t(0.);
if(delvxeta > Real_t(0.)) delvxeta = Real_t(0.);
if(delvxzeta > Real_t(0.)) delvxzeta = Real_t(0.);
Real_t rho =
domain.elemMass(ielem) / (domain.volo(ielem) * domain.vnew(ielem));
qlin =
-qlc_monoq * rho *
(delvxxi * (Real_t(1.) - phixi) + delvxeta * (Real_t(1.) - phieta) +
delvxzeta * (Real_t(1.) - phizeta));
qquad = qqc_monoq * rho *
(delvxxi * delvxxi * (Real_t(1.) - phixi * phixi) +
delvxeta * delvxeta * (Real_t(1.) - phieta * phieta) +
delvxzeta * delvxzeta * (Real_t(1.) - phizeta * phizeta));
}
domain.qq(ielem) = qquad;
domain.ql(ielem) = qlin;
});
}
static inline void
CalcMonotonicQForElems(Domain& domain)
{
const Real_t ptiny = Real_t(1.e-36);
for(Index_t r = 0; r < domain.numReg(); ++r)
{
if(domain.regElemSize(r) > 0)
{
CalcMonotonicQRegionForElems(domain, r, ptiny);
}
}
}
static inline void
CalcQForElems(Domain& domain)
{
Index_t numElem = domain.numElem();
if(numElem != 0)
{
Int_t allElem = numElem + /* local elem */
2 * domain.sizeX() * domain.sizeY() + /* plane ghosts */
2 * domain.sizeX() * domain.sizeZ() + /* row ghosts */
2 * domain.sizeY() * domain.sizeZ(); /* col ghosts */
domain.AllocateGradients(numElem, allElem);
#if USE_MPI
CommRecv(domain, MSG_MONOQ, 3, domain.sizeX(), domain.sizeY(), domain.sizeZ(),
true, true);
#endif
CalcMonotonicQGradientsForElems(domain);
#if USE_MPI
Domain_member fieldData[3];
fieldData[0] = &Domain::delv_xi;
fieldData[1] = &Domain::delv_eta;
fieldData[2] = &Domain::delv_zeta;
CommSend(domain, MSG_MONOQ, 3, fieldData, domain.sizeX(), domain.sizeY(),
domain.sizeZ(), true, true);
CommMonoQ(domain);
#endif
CalcMonotonicQForElems(domain);
domain.DeallocateGradients();
Index_t idx = 0;
Kokkos::parallel_reduce(
"CalcQForElems", numElem,
KOKKOS_LAMBDA(const Index_t& i, Index_t& count) {
if(domain.q(i) > domain.qstop())
{
count++;
}
},
idx);
if(idx > 0)
{
#if USE_MPI
MPI_Abort(MPI_COMM_WORLD, QStopError);
#else
exit(QStopError);
#endif
}
}
}
KOKKOS_INLINE_FUNCTION
void
CalcPressureForElem(Real_t& p_new_i, Real_t& bvc_i, Real_t& pbvc_i, const Real_t& e_old_i,
const Real_t& compression_i, const Real_t& vnewc_e,
const Real_t& pmin, const Real_t& p_cut, const Real_t& eosvmax)
{
const Real_t c1s = Real_t(2.0) / Real_t(3.0);
bvc_i = c1s * (compression_i + Real_t(1.));
pbvc_i = c1s;
p_new_i = bvc_i * e_old_i;
if(FABS(p_new_i) < p_cut) p_new_i = Real_t(0.0);
if(vnewc_e >= eosvmax) /* impossible condition here? */
p_new_i = Real_t(0.0);
if(p_new_i < pmin) p_new_i = pmin;
}
static inline void
CalcEnergyForElems(Real_t* p_new, Real_t* e_new, Real_t* q_new, Real_t* bvc, Real_t* pbvc,
Real_t* p_old, Real_t* e_old, Real_t* q_old, Real_t* compression,
Real_t* compHalfStep, Real_t* vnewc, Real_t* work, Real_t* delvc,
Real_t pmin, Real_t p_cut, Real_t e_cut, Real_t q_cut, Real_t emin,
Real_t* qq_old, Real_t* ql_old, Real_t rho0, Real_t eosvmax,
Index_t length, Domain& domain, Index_t r)
{
Kokkos::parallel_for(
"CalcEnergyForElems", length, KOKKOS_LAMBDA(const int i) {
const Real_t delvc_i = delvc[i];
const Real_t p_old_i = p_old[i];
const Real_t q_old_i = q_old[i];
Real_t e_new_i = e_old[i] - Real_t(0.5) * delvc_i * (p_old_i + q_old_i) +
Real_t(0.5) * work[i];
if(e_new_i < emin)
{
e_new_i = emin;
}
Real_t bvc_i, pbvc_i;
Real_t pHalfStep_i;
const Real_t vnewc_e = vnewc[domain.regElemlist(r, i)];
const Real_t compHalfStep_i = compHalfStep[i];
CalcPressureForElem(pHalfStep_i, bvc_i, pbvc_i, e_new_i, compHalfStep_i,
vnewc_e, pmin, p_cut, eosvmax);
Real_t vhalf = Real_t(1.) / (Real_t(1.) + compHalfStep_i);
Real_t q_new_i;
const Real_t ql_old_i = ql_old[i];
const Real_t qq_old_i = qq_old[i];
if(delvc_i > Real_t(0.))
{
q_new_i /* = qq_old[i] = ql_old[i] */ = Real_t(0.);
}
else
{
Real_t ssc =
(pbvc_i * e_new_i + vhalf * vhalf * bvc_i * pHalfStep_i) / rho0;
if(ssc <= Real_t(.1111111e-36))
{
ssc = Real_t(.3333333e-18);
}
else
{
ssc = SQRT(ssc);
}
q_new_i = (ssc * ql_old_i + qq_old_i);
}
e_new_i = e_new_i + Real_t(0.5) * delvc_i *
(Real_t(3.0) * (p_old_i + q_old_i) -
Real_t(4.0) * (pHalfStep_i + q_new_i));
e_new_i += Real_t(0.5) * work[i];
if(FABS(e_new_i) < e_cut)
{
e_new_i = Real_t(0.);
}
if(e_new_i < emin)
{
e_new_i = emin;
}
Real_t p_new_i;
const Real_t compression_i = compression[i];
CalcPressureForElem(p_new_i, bvc_i, pbvc_i, e_new_i, compression_i, vnewc_e,
pmin, p_cut, eosvmax);
const Real_t sixth = Real_t(1.0) / Real_t(6.0);
Real_t q_tilde;
if(delvc_i > Real_t(0.))
{
q_tilde = Real_t(0.);
}
else
{
Real_t ssc =
(pbvc_i * e_new_i + vnewc_e * vnewc_e * bvc_i * p_new_i) / rho0;
if(ssc <= Real_t(.1111111e-36))
{
ssc = Real_t(.3333333e-18);
}
else
{
ssc = SQRT(ssc);
}
q_tilde = (ssc * ql_old_i + qq_old_i);
}
e_new_i =
e_new_i - (Real_t(7.0) * (p_old_i + q_old_i) -
Real_t(8.0) * (pHalfStep_i + q_new_i) + (p_new_i + q_tilde)) *
delvc_i * sixth;
if(FABS(e_new_i) < e_cut)
{
e_new_i = Real_t(0.);
}
if(e_new_i < emin)
{
e_new_i = emin;
}
CalcPressureForElem(p_new_i, bvc_i, pbvc_i, e_new_i, compression_i, vnewc_e,
pmin, p_cut, eosvmax);
bvc[i] = bvc_i;
pbvc[i] = pbvc_i;
p_new[i] = p_new_i;
if(delvc_i <= Real_t(0.))
{
Real_t ssc =
(pbvc_i * e_new_i + vnewc_e * vnewc_e * bvc_i * p_new_i) / rho0;
if(ssc <= Real_t(.1111111e-36))
{
ssc = Real_t(.3333333e-18);
}
else
{
ssc = SQRT(ssc);
}
q_new_i = (ssc * ql_old_i + qq_old_i);
if(FABS(q_new_i) < q_cut) q_new_i = Real_t(0.);
}
q_new[i] = q_new_i;
e_new[i] = e_new_i;
});
return;
}
static inline void
CalcSoundSpeedForElems(Domain& domain, Real_t* vnewc, Real_t rho0, Real_t* enewc,
Real_t* pnewc, Real_t* pbvc, Real_t* bvc, Real_t ss4o3,
Index_t len, Index_t r)
{
Kokkos::parallel_for(
"CalcSoundSpeedForElems", len, KOKKOS_LAMBDA(const int i) {
Index_t ielem = domain.regElemlist(r, i);
Real_t ssTmp =
(pbvc[i] * enewc[i] + vnewc[ielem] * vnewc[ielem] * bvc[i] * pnewc[i]) /
rho0;
if(ssTmp <= Real_t(.1111111e-36))
{
ssTmp = Real_t(.3333333e-18);
}
else
{
ssTmp = SQRT(ssTmp);
}
domain.ss(ielem) = ssTmp;
});
}
static inline void
EvalEOSForElems(Domain& domain, Real_t* vnewc, Int_t numElemReg, Index_t r, Int_t rep)
{
Real_t e_cut = domain.e_cut();
Real_t p_cut = domain.p_cut();
Real_t ss4o3 = domain.ss4o3();
Real_t q_cut = domain.q_cut();
Real_t eosvmax = domain.eosvmax();
Real_t eosvmin = domain.eosvmin();
Real_t pmin = domain.pmin();
Real_t emin = domain.emin();
Real_t rho0 = domain.refdens();
ResizeBuffer((numElemReg * sizeof(Real_t) + 4096) * 16);
Real_t* e_old = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* delvc = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* p_old = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* q_old = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* compression = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* compHalfStep = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* qq_old = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* ql_old = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* work = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* p_new = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* e_new = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* q_new = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* bvc = AllocateFromBuffer<Real_t>(numElemReg);
Real_t* pbvc = AllocateFromBuffer<Real_t>(numElemReg);
for(Int_t j = 0; j < rep; j++)
{
Kokkos::parallel_for(
"EvalEOSForElems A", numElemReg, KOKKOS_LAMBDA(const int i) {
Index_t ielem = domain.regElemlist(r, i);
e_old[i] = domain.c_e(ielem);
delvc[i] = domain.c_delv(ielem);
p_old[i] = domain.c_p(ielem);
q_old[i] = domain.c_q(ielem);
qq_old[i] = domain.c_qq(ielem);
ql_old[i] = domain.c_ql(ielem);
const Real_t vnewc_ielem = vnewc[ielem];
Real_t vchalf;
compression[i] = Real_t(1.) / vnewc_ielem - Real_t(1.);
vchalf = vnewc_ielem - delvc[i] * Real_t(.5);
compHalfStep[i] = Real_t(1.) / vchalf - Real_t(1.);
if(eosvmin != Real_t(0.))
{
if(vnewc_ielem <= eosvmin)
{ /* impossible due to calling func? */
compHalfStep[i] = compression[i];
}
}
if(eosvmax != Real_t(0.))
{
if(vnewc_ielem >= eosvmax)
{ /* impossible due to calling func? */
p_old[i] = Real_t(0.);
compression[i] = Real_t(0.);
compHalfStep[i] = Real_t(0.);
}
}
work[i] = Real_t(0.);
});
CalcEnergyForElems(p_new, e_new, q_new, bvc, pbvc, p_old, e_old, q_old,
compression, compHalfStep, vnewc, work, delvc, pmin, p_cut,
e_cut, q_cut, emin, qq_old, ql_old, rho0, eosvmax, numElemReg,
domain, r);
}
Kokkos::parallel_for(
"EvalEOSForElems F", numElemReg, KOKKOS_LAMBDA(const int i) {
Index_t ielem = domain.regElemlist(r, i);
domain.p(ielem) = p_new[i];
domain.e(ielem) = e_new[i];
domain.q(ielem) = q_new[i];
});
CalcSoundSpeedForElems(domain, vnewc, rho0, e_new, p_new, pbvc, bvc, ss4o3,
numElemReg, r);
}
static inline void
ApplyMaterialPropertiesForElems(Domain& domain)
{
Index_t numElem = domain.numElem();
if(numElem != 0)
{
Real_t eosvmin = domain.eosvmin();
Real_t eosvmax = domain.eosvmax();
Kokkos::View<Real_t*> vnewc("vnewc", numElem);
Kokkos::parallel_for(
"ApplyMaterialPropertiesForElems A", numElem,
KOKKOS_LAMBDA(const int i) { vnewc[i] = domain.vnew(i); });
if(eosvmin != Real_t(0.))
{
Kokkos::parallel_for(
"ApplyMaterialPropertiesForElems B", numElem, KOKKOS_LAMBDA(const int i) {
if(vnewc[i] < eosvmin) vnewc[i] = eosvmin;
});
}
if(eosvmax != Real_t(0.))
{
Kokkos::parallel_for(
"ApplyMaterialPropertiesForElems C", numElem, KOKKOS_LAMBDA(const int i) {
if(vnewc[i] > eosvmax) vnewc[i] = eosvmax;
});
}
int error = 0;
Kokkos::parallel_reduce(
"ApplyMaterialPropertiesForElems", numElem,
KOKKOS_LAMBDA(const int i, int& err) {
Real_t vc = domain.v(i);
if(eosvmin != Real_t(0.))
{
if(vc < eosvmin) vc = eosvmin;
}
if(eosvmax != Real_t(0.))
{
if(vc > eosvmax) vc = eosvmax;
}
if(vc <= 0.)
{
err++;
}
},
error);
if(error != 0)
#if USE_MPI
MPI_Abort(MPI_COMM_WORLD, VolumeError);
#else
exit(VolumeError);
#endif
for(Int_t r = 0; r < domain.numReg(); r++)
{
Index_t numElemReg = domain.regElemSize(r);
// Index_t *regElemList = domain.regElemlist(r);
Int_t rep;
if(r < domain.numReg() / 2)
rep = 1;
else if(r < (domain.numReg() - (domain.numReg() + 15) / 20))
rep = 1 + domain.cost();
else
rep = 10 * (1 + domain.cost());
EvalEOSForElems(domain, vnewc.data(), numElemReg, r, rep);
}
}
}
static inline void
UpdateVolumesForElems(Domain& domain, Real_t v_cut, Index_t length)
{
if(length != 0)
{
Kokkos::parallel_for(
"UpdateVolumesForElems", length, KOKKOS_LAMBDA(const int i) {
Real_t tmpV = domain.vnew(i);
if(FABS(tmpV - Real_t(1.0)) < v_cut) tmpV = Real_t(1.0);
domain.v(i) = tmpV;
});
}
return;
}
static inline void
LagrangeElements(Domain& domain, Index_t numElem)
{
CalcLagrangeElements(domain);
CalcQForElems(domain);
ApplyMaterialPropertiesForElems(domain);
UpdateVolumesForElems(domain, domain.v_cut(), numElem);
}
static inline void
CalcCourantConstraintForElems(Domain& domain, Index_t length, Index_t r, Real_t qqc,
Real_t& dtcourant)
{
typedef Kokkos::View<Real_t*> view_real_t;
Real_t qqc2 = Real_t(64.0) * qqc * qqc;
Real_t dtcourant_tmp = dtcourant;
Index_t courant_elem = -1;
MinFinder result;
Kokkos::parallel_reduce(
"CalcCourantConstraintForElems", length,
KOKKOS_LAMBDA(const int i, MinFinder& minf) {
Index_t indx = domain.regElemlist(r, i);
Real_t dtf = domain.ss(indx) * domain.ss(indx);
if(domain.vdov(indx) < Real_t(0.))
{
dtf = dtf + qqc2 * domain.arealg(indx) * domain.arealg(indx) *
domain.vdov(indx) * domain.vdov(indx);
}
dtf = SQRT(dtf);
dtf = domain.arealg(indx) / dtf;
MinFinder tmp(dtf, i);
if(domain.vdov(indx) != Real_t(0.))
{
minf += tmp;
}
},
result);
dtcourant_tmp = result.val;
if(dtcourant_tmp > dtcourant)
{
dtcourant_tmp = dtcourant;
}
courant_elem = result.i;
if(courant_elem != -1)
{
dtcourant = dtcourant_tmp;
}
return;
}
static inline void
CalcHydroConstraintForElems(Domain& domain, Index_t length, Index_t r, Real_t dvovmax,
Real_t& dthydro)
{
typedef Kokkos::View<Real_t*> view_real_t;
Real_t dthydro_tmp = dthydro;
Index_t hydro_elem = -1;
MinFinder result;
Kokkos::parallel_reduce(
"CalcHydroConstraintForElems", length,
KOKKOS_LAMBDA(const int i, MinFinder& minf) {
Index_t indx = domain.regElemlist(r, i);
if(domain.vdov(indx) != Real_t(0.))
{
Real_t dtdvov = dvovmax / (FABS(domain.vdov(indx)) + Real_t(1.e-20));
MinFinder tmp(dtdvov, i);
if(domain.vdov(indx) != Real_t(0.))
{
minf += tmp;
}
}
},
result);
if(result.val > dthydro)
{
result.val = dthydro;
}
if(result.i != -1)
{
dthydro = result.val;
}
return;
}
static inline void
CalcTimeConstraintsForElems(Domain& domain)
{
domain.dtcourant() = 1.0e+20;
domain.dthydro() = 1.0e+20;
for(Index_t r = 0; r < domain.numReg(); ++r)
{
CalcCourantConstraintForElems(domain, domain.regElemSize(r), r, domain.qqc(),
domain.dtcourant());
CalcHydroConstraintForElems(domain, domain.regElemSize(r), r, domain.dvovmax(),
domain.dthydro());
}
}
static inline void
LagrangeLeapFrog(Domain& domain)
{
#ifdef SEDOV_SYNC_POS_VEL_LATE
Domain_member fieldData[6];
#endif
LagrangeNodal(domain);
#ifdef SEDOV_SYNC_POS_VEL_LATE
#endif
LagrangeElements(domain, domain.numElem());
#if USE_MPI
# ifdef SEDOV_SYNC_POS_VEL_LATE
CommRecv(domain, MSG_SYNC_POS_VEL, 6, domain.sizeX() + 1, domain.sizeY() + 1,
domain.sizeZ() + 1, false, false);
fieldData[0] = &Domain::x;
fieldData[1] = &Domain::y;
fieldData[2] = &Domain::z;
fieldData[3] = &Domain::xd;
fieldData[4] = &Domain::yd;
fieldData[5] = &Domain::zd;
CommSend(domain, MSG_SYNC_POS_VEL, 6, fieldData, domain.sizeX() + 1,
domain.sizeY() + 1, domain.sizeZ() + 1, false, false);
# endif
#endif
CalcTimeConstraintsForElems(domain);
#if USE_MPI
# ifdef SEDOV_SYNC_POS_VEL_LATE
CommSyncPosVel(domain);
# endif
#endif
}
int
main(int argc, char* argv[])
{
Int_t numRanks;
Int_t myRank;
struct cmdLineOpts opts;
#if USE_MPI
Domain_member fieldData;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
#else
numRanks = 1;
myRank = 0;
#endif
Kokkos::initialize(argc, argv);
{
Kokkos::Tools::pushRegion("initialization");
opts.its = 9999999;
opts.nx = 30;
opts.numReg = 11;
opts.numFiles = (int) (numRanks + 10) / 9;
opts.showProg = 0;
opts.quiet = 0;
opts.viz = 0;
opts.balance = 1;
opts.cost = 1;
opts.do_atomic = 0;
ParseCommandLineOptions(argc, argv, myRank, &opts);
if(opts.do_atomic == 1)
do_atomic = 1;
else
do_atomic = 0;
if((myRank == 0) && (opts.quiet == 0))
{
printf("Running problem size %d^3 per domain until completion\n", opts.nx);
printf("Num processors: %d\n", numRanks);
printf("Total number of elements: %lld\n\n",
(long long int) (numRanks * opts.nx * opts.nx * opts.nx));
printf("To run other sizes, use -s <integer>.\n");
printf("To run a fixed number of iterations, use -i <integer>.\n");
printf("To run a more or less balanced region set, use -b <integer>.\n");
printf("To change the relative costs of regions, use -c <integer>.\n");
printf("To print out progress, use -p\n");
printf("To write an output file for VisIt, use -v\n");
printf("See help (-h) for more options\n\n");
}
Int_t col, row, plane, side;
InitMeshDecomp(numRanks, myRank, &col, &row, &plane, &side);
// Build the main data structure and initialize it
Domain locDom(numRanks, col, row, plane, opts.nx, side, opts.numReg, opts.balance,
opts.cost);
#if USE_MPI
fieldData = &Domain::nodalMass;
// Initial domain boundary communication
CommRecv(locDom, MSG_COMM_SBN, 1, locDom.sizeX() + 1, locDom.sizeY() + 1,
locDom.sizeZ() + 1, true, false);
CommSend(locDom, MSG_COMM_SBN, 1, &fieldData, locDom.sizeX() + 1,
locDom.sizeY() + 1, locDom.sizeZ() + 1, true, false);
CommSBN(locDom, 1, &fieldData);
// End initialization
MPI_Barrier(MPI_COMM_WORLD);
#endif
Kokkos::Tools::popRegion();
#if USE_MPI
double start = MPI_Wtime();
#else
timeval start;
gettimeofday(&start, nullptr);
#endif
uint32_t _time_incrp = 0;
uint32_t _leap_frogp = 0;
Kokkos::Tools::createProfileSection("TimeIncr", &_time_incrp);
Kokkos::Tools::createProfileSection("LeapFrog", &_leap_frogp);
while((locDom.time() < locDom.stoptime()) && (locDom.cycle() < opts.its))
{
Kokkos::Tools::startSection(_time_incrp);
// CAUSAL_BEGIN("Iteration")
TimeIncrement(locDom);
Kokkos::Tools::stopSection(_time_incrp);
Kokkos::Tools::startSection(_leap_frogp);
LagrangeLeapFrog(locDom);
Kokkos::Tools::stopSection(_leap_frogp);
CAUSAL_PROGRESS_NAMED("Iteration")
// CAUSAL_END("Iteration")
if((opts.showProg != 0) && (opts.quiet == 0) && (myRank == 0))
{
printf("cycle = %d, time = %e, dt=%e\n", locDom.cycle(),
double(locDom.time()), double(locDom.deltatime()));
}
Kokkos::Tools::markEvent("completed_timestep");
CAUSAL_PROGRESS
}
Kokkos::Tools::destroyProfileSection(_time_incrp);
Kokkos::Tools::destroyProfileSection(_leap_frogp);
double elapsed_time;
#if USE_MPI
elapsed_time = MPI_Wtime() - start;
#else
timeval end;
gettimeofday(&end, NULL);
elapsed_time = (double) (end.tv_sec - start.tv_sec) +
((double) (end.tv_usec - start.tv_usec)) / 1000000;
#endif
double elapsed_timeG;
#if USE_MPI
MPI_Reduce(&elapsed_time, &elapsed_timeG, 1, MPI_DOUBLE, MPI_MAX, 0,
MPI_COMM_WORLD);
#else
elapsed_timeG = elapsed_time;
#endif
Kokkos::Tools::pushRegion("finalization");
if(opts.viz)
{
DumpToVisit(locDom, opts.numFiles, myRank, numRanks);
}
if((myRank == 0) && (opts.quiet == 0))
{
VerifyAndWriteFinalOutput(elapsed_timeG, locDom, opts.nx, numRanks);
}
Kokkos::Tools::popRegion();
buffer = Kokkos::View<Real_t*>();
}
Kokkos::finalize();
#if USE_MPI
MPI_Finalize();
#endif
return 0;
}