1#ifndef SEAMS_TUM_DEVICE_H_
2#define SEAMS_TUM_DEVICE_H_
18#ifdef SEAMS_HAS_OFFLOAD
19#pragma omp declare target
25inline bool bonded(
const int *deg,
const int *cols,
int nAtoms,
int kMax,
27 if (a < 0 || b < 0 || a >= nAtoms || b >= nAtoms) {
31 const int row = a * kMax;
32 for (
int t = 0; t < d; ++t) {
33 if (cols[row + t] == b) {
40inline bool inSix(
const int *r,
int atom) {
41 for (
int t = 0; t < 6; ++t) {
50 for (
int i = 0; i < 6; ++i) {
60 for (
int i = 0; i < 6; ++i) {
69 for (
int i = 0; i < 6; ++i) {
77inline bool shareNeigh(
const int *deg,
const int *cols,
int nAtoms,
int kMax,
79 const int da = deg[a];
80 const int ra = a * kMax;
81 for (
int t = 0; t < da; ++t) {
82 if (
bonded(deg, cols, nAtoms, kMax, b, cols[ra + t])) {
91inline int hopsAtMost(
const int *deg,
const int *cols,
int nAtoms,
int kMax,
92 int a,
int b,
int cap) {
96 if (
bonded(deg, cols, nAtoms, kMax, a, b)) {
102 if (
shareNeigh(deg, cols, nAtoms, kMax, a, b)) {
110 int nAtoms,
int kMax) {
111 const int pairI[9] = {0, 1, 2, 3, 4, 5, 0, 1, 2};
112 const int pairJ[9] = {2, 3, 4, 5, 0, 1, 3, 4, 5};
113 const int ringHops[9] = {2, 2, 2, 2, 2, 2, 3, 3, 3};
114 for (
int t = 0; t < 9; ++t) {
115 if (
hopsAtMost(deg, cols, nAtoms, kMax, r[pairI[t]], r[pairJ[t]],
116 ringHops[t] - 1) >= 0) {
124 int kMax,
int n1,
int n2,
int atomOne,
126 const bool n1one =
bonded(deg, cols, nAtoms, kMax, atomOne, n1);
127 const bool n1two =
bonded(deg, cols, nAtoms, kMax, atomTwo, n1);
128 if (!n1one && !n1two) {
132 return bonded(deg, cols, nAtoms, kMax, atomTwo, n2);
134 return bonded(deg, cols, nAtoms, kMax, atomOne, n2);
138 int kMax,
const int *trip,
const int *
ring) {
139 for (
int i = 0; i < 3; ++i) {
140 for (
int j = 0; j < 6; ++j) {
141 if (
bonded(deg, cols, nAtoms, kMax,
ring[j], trip[i])) {
150 int kMax,
const int *b1,
const int *b2) {
156 const int l1 = b1[0];
157 const int l2 = b1[1];
158 for (
int k = 0; k < 6; ++k) {
159 const int mk = b2[k];
160 if (
bonded(deg, cols, nAtoms, kMax, l1, mk)) {
167 if (
bonded(deg, cols, nAtoms, kMax, l2, mk)) {
182 for (
int k = 0; k <= 5; ++k) {
188 evenT[ie++] = b2[ck];
193 if (!
basalNeighbours(deg, cols, nAtoms, kMax, evenT[1], evenT[2], compare1,
201 const int *C,
int nC,
int skipA,
int skipB) {
205 while (i < nA && j < nB && k < nC) {
209 if (x == y && y == z) {
210 if (x != skipA && x != skipB) {
239 const int *C,
int nC,
int skipA,
int skipB,
int *out,
245 while (i < nA && j < nB && k < nC) {
249 if (x == y && y == z) {
250 if (x != skipA && x != skipB && n < cap) {
281#pragma omp atomic capture
290inline void enumSixFrom(
int i,
const int *deg,
const int *cols,
int nAtoms,
291 int kMax,
int maxRings,
int *nRings,
int *ringAtoms,
293 const int di = deg[i];
297 const int irow = i * kMax;
298 for (
int ia = 0; ia < di; ++ia) {
299 const int a = cols[irow + ia];
300 for (
int ib = ia + 1; ib < di; ++ib) {
301 const int b = cols[irow + ib];
302 const int da = deg[a];
303 const int db = deg[b];
304 const int arow = a * kMax;
305 const int brow = b * kMax;
306 for (
int ix = 0; ix < da; ++ix) {
307 const int x = cols[arow + ix];
308 if (x == i || x == b) {
311 for (
int iy = 0; iy < db; ++iy) {
312 const int y = cols[brow + iy];
313 if (y == i || y == a || y == x) {
316 const int dx = deg[x];
317 const int xrow = x * kMax;
318 for (
int iz = 0; iz < dx; ++iz) {
319 const int z = cols[xrow + iz];
320 if (z == i || z == a || z == b || z == y) {
323 if (!
bonded(deg, cols, nAtoms, kMax, z, y)) {
326 const int cyc[6] = {i, a, x, z, y, b};
328 for (
int t = 1; t < 6; ++t) {
340 if (slot >= maxRings) {
344 const int dest = slot * 6;
345 for (
int t = 0; t < 6; ++t) {
346 ringAtoms[dest + t] = cyc[t];
356 int nAtoms,
int maxPer,
int *throughCount,
361 const int *
ring = ringAtoms + r * 6;
362 for (
int t = 0; t < 6; ++t) {
363 const int atom =
ring[t];
364 if (atom < 0 || atom >= nAtoms) {
367 const int slot =
fetchAdd(throughCount + atom);
369 through[atom * maxPer + slot] = r;
375 for (
int a = 1; a < n; ++a) {
376 const int key = row[a];
378 while (p > 0 && row[p - 1] > key) {
387 const int *deg,
const int *cols,
388 const int *throughCount,
const int *through,
389 int nAtoms,
int kMax,
int maxPer,
int maxPairs,
390 int *nPairs,
int *pairs) {
394 const int *bi = ringAtoms + i * 6;
395 for (
int slot = 0; slot < 2; ++slot) {
396 const int anchor = bi[slot];
397 if (anchor < 0 || anchor >= nAtoms) {
400 const int da = deg[anchor];
401 const int arow = anchor * kMax;
402 for (
int n = 0; n < da; ++n) {
403 const int nb = cols[arow + n];
404 if (nb < 0 || nb >= nAtoms) {
407 const int nr = throughCount[nb];
408 const int *row = through + nb * maxPer;
409 for (
int t = 0; t < nr; ++t) {
410 const int j = row[t];
414 const int *bj = ringAtoms + j * 6;
422 if (slotp < maxPairs) {
423 pairs[slotp * 2] = i;
424 pairs[slotp * 2 + 1] = j;
431inline void applyHcPair(
int p,
const int *nPairs,
const int *pairs,
432 const int *ringAtoms,
const int *throughCount,
433 const int *through,
int nAtoms,
int maxPer,
int *hc) {
437 const int i = pairs[p * 2];
438 const int j = pairs[p * 2 + 1];
441 const int *bi = ringAtoms + i * 6;
442 const int *bj = ringAtoms + j * 6;
443 for (
int q = 0; q < 6; ++q) {
445 for (
int m = 0; m < 3; ++m) {
446 trip[m] = bi[(q + m) % 6];
448 const int nA = throughCount[trip[0]];
449 const int nB = throughCount[trip[1]];
450 const int nC = throughCount[trip[2]];
451 const int *A = through + trip[0] * maxPer;
452 const int *B = through + trip[1] * maxPer;
453 const int *C = through + trip[2] * maxPer;
455 const int nc =
ringsThrough(A, nA, B, nB, C, nC, i, j, cand, 16);
456 for (
int c = 0; c < nc; ++c) {
457 const int kr = cand[c];
458 const int *bk = ringAtoms + kr * 6;
461 for (
int u = 0; u < 6; ++u) {
462 if (!
inSix(trip, bk[u]) && nrst < 3) {
463 rest[nrst++] = bk[u];
473inline void ddcFrom(
int i,
const int *nRings,
const int *ringAtoms,
474 const int *throughCount,
const int *through,
const int *hc,
475 int nAtoms,
int maxPer,
int *ddc) {
482 const int *bi = ringAtoms + i * 6;
485 for (
int m = 0; m < 6; ++m) {
486 const int atom = bi[m];
487 if (atom < 0 || atom >= nAtoms) {
490 const int nr = throughCount[atom];
491 const int *row = through + atom * maxPer;
493 for (
int t = 0; t < nr; ++t) {
499 peri[nPeri++] = row[t];
507 for (
int k = 0; k < 6; ++k) {
509 for (
int t = 0; t < 3; ++t) {
510 trip[t] = bi[(k + t) % 6];
512 const int nA = throughCount[trip[0]];
513 const int nB = throughCount[trip[1]];
514 const int nC = throughCount[trip[2]];
515 const int *A = through + trip[0] * maxPer;
516 const int *B = through + trip[1] * maxPer;
517 const int *C = through + trip[2] * maxPer;
524 const int *p0 = ringAtoms + newP[0] * 6;
525 const int *p1 = ringAtoms + newP[1] * 6;
526 const int *p2 = ringAtoms + newP[2] * 6;
527 const int *p3 = ringAtoms + newP[3] * 6;
528 const int *p4 = ringAtoms + newP[4] * 6;
529 const int *p5 = ringAtoms + newP[5] * 6;
536 const int *pairs[4][2] = {{p0, p2}, {p1, p3}, {p2, p4}, {p3, p5}};
537 for (
int t = 0; t < 4; ++t) {
543 for (
int t = 0; t < 6; ++t) {
548inline void atomIceFrom(
int r,
const int *nRings,
const int *ringAtoms,
549 const int *hc,
const int *ddc,
int nAtoms,
int *atomHc,
554 const int *
ring = ringAtoms + r * 6;
555 const int isHc = hc[r];
556 const int isDdc = ddc[r];
557 for (
int t = 0; t < 6; ++t) {
558 const int a =
ring[t];
559 if (a < 0 || a >= nAtoms) {
574#ifdef SEAMS_HAS_OFFLOAD
575#pragma omp end declare target
Topological network criteria functions.
bool shareNeigh(const int *deg, const int *cols, int nAtoms, int kMax, int a, int b)
bool inSix(const int *r, int atom)
int firstRingThrough(const int *A, int nA, const int *B, int nB, const int *C, int nC, int skipA, int skipB)
void enumSixFrom(int i, const int *deg, const int *cols, int nAtoms, int kMax, int maxRings, int *nRings, int *ringAtoms, int *dropped)
Enumerate hop-bound primitive six-rings whose lowest vertex is i.
void emitBasalFrom(int i, const int *nRings, const int *ringAtoms, const int *deg, const int *cols, const int *throughCount, const int *through, int nAtoms, int kMax, int maxPer, int maxPairs, int *nPairs, int *pairs)
void applyHcPair(int p, const int *nPairs, const int *pairs, const int *ringAtoms, const int *throughCount, const int *through, int nAtoms, int maxPer, int *hc)
void invertOneRing(int r, const int *nRings, const int *ringAtoms, int nAtoms, int maxPer, int *throughCount, int *through)
bool basalNeighbours(const int *deg, const int *cols, int nAtoms, int kMax, int n1, int n2, int atomOne, int atomTwo)
int ringsThrough(const int *A, int nA, const int *B, int nB, const int *C, int nC, int skipA, int skipB, int *out, int cap)
bool bonded(const int *deg, const int *cols, int nAtoms, int kMax, int a, int b)
bool notNeighboursOfRing(const int *deg, const int *cols, int nAtoms, int kMax, const int *trip, const int *ring)
bool commonInThree(const int *a, const int *b, const int *c)
void sortThroughRow(int *row, int n)
void ddcFrom(int i, const int *nRings, const int *ringAtoms, const int *throughCount, const int *through, const int *hc, int nAtoms, int maxPer, int *ddc)
int commonCount(const int *a, const int *b)
void atomIceFrom(int r, const int *nRings, const int *ringAtoms, const int *hc, const int *ddc, int nAtoms, int *atomHc, int *atomDdc)
bool shareAtoms(const int *a, const int *b)
bool hopBoundPrimitiveSix(const int *r, const int *deg, const int *cols, int nAtoms, int kMax)
Hop-bounded Franzblau SP test on a six-cycle of the bond graph.
bool basalConditions(const int *deg, const int *cols, int nAtoms, int kMax, const int *b1, const int *b2)
int hopsAtMost(const int *deg, const int *cols, int nAtoms, int kMax, int a, int b, int cap)
Graph distance from a to b when it is at most cap, else -1.