Я знаю, что на этот вопрос уже дан ответ, но вот похожее хранилище циклов на основе одного лица, которое реализовано в библиотеке OpenFOAM C ++:
Каждая ячейка имеет индекс (ID) в cellList. Для всех лиц определены два списка: «лицо внутреннего владельца» и «лицо соседа». Длина обоих списков граней соответствует количеству внутренних граней в сетке. Владелец лица будет ячейкой с более низким идентификатором в cellList (напротив для лица соседа). Граничные грани записываются в последнюю очередь и имеют ориентированные наружу нормали (из области решения) и, конечно, только одну ячейку-владельца. Нормальная область лица ориентирована так, чтобы она смотрела наружу из ячейки владельца в соседнюю ячейку.
Это хорошо работает, например, для расчета потока. Поток оценивается один раз для каждой грани, и он добавляется к сумме общих граней для ячеек-владельцев и вычитается из соседних ячеек (сумма / вычет определяется на основе ориентации нормали к области лица). Граничные грани сортируются и сохраняются в нижней части списка граней, что позволяет определять граничные условия как фрагменты списка граней (начальная метка, конечная метка граничного участка), что упрощает, таким образом, реализацию граничных условий, а также как повышение эффективности процесса обновления для граничных условий, поскольку оно опирается на решение, обеспечиваемое операциями на внутренних гранях.
Поскольку граничные грани агломерированы в патчи, межпроцессное взаимодействие определяется для связанных (процессорных) патчей и предопределено. Это означает, что, как только петля пересекает граничную сетку, функции доступа верхнего уровня вызывают обернутые вызовы MPI, делая такой код «автоматически» распараллеленным, если он опирается на вышеописанное соединение на основе лица.