¿Cuáles son las estrategias para el Refinamiento de malla adaptable local (AMR local) en mallas no estructuradas?

8

Estoy interesado en AMR local en mallas no estructuradas. Actualmente, estoy trabajando con la biblioteca OpenFOAM: admite AMR local completamente no estructurado:

  • los criterios de refinamiento de celda determinan una lista de celdas que se cortan
  • las celdas seleccionadas se refinan: se reconstruye toda la malla
  • se crea un mapa desde la malla anterior a una nueva
  • se vuelve a calcular la conectividad (celdas de cara, caras de borde, etc.)
  • los campos se asignan a la nueva malla

Dado que las estructuras de datos involucradas son básicamente vectores C ++, la malla se infla, se copia.

Necesito aprender acerca de enfoques alternativos que se pueden construir sobre una malla que utiliza estructuras de datos estáticos. Uno de ellos es el AMR local paralelo de Octree Forrest, presente en p4est y Dendro .

¿Alguien puede señalarme un artículo de revisión reciente sobre estrategias de AMR adaptativas locales para mallas no estructuradas?

El asesoramiento basado en la experiencia sería aún mejor: ¿qué motor AMR local es la opción óptima para la malla no estructurada basada en la estructura de datos fijos?

Necesito una descripción general antes de leer sobre el equilibrio de la comunicación entre árboles en la primera página de un documento. :)

tmarico
fuente
¿Qué quiere decir exactamente con "estructuras de datos estáticos"? Durante el refinamiento de malla, por supuesto, el número de celdas aumenta, por lo que definitivamente debe crecer cierta estructura de datos (su "inflado, copiado"). No estoy seguro de cuál es exactamente su pregunta, me temo.
Wolfgang Bangerth
Bueno, si la malla se basa en estructuras de datos similares a std :: vector, al agregar incluso una sola celda, se creará un nuevo std :: vector (con un mayor tamaño para la nueva celda, sus puntos y caras), y copiando el datos antiguos no refinados a las nuevas estructuras. Con Octree Forrest, si lo entiendo correctamente, no expandiré las estructuras de datos que definen mi malla, Octree Forrest contendrá toda la información necesaria para el refinamiento, y Octree es una estructura de datos dinámica en el sentido de que cambiar una sola celda no copia todo el árbol y lo expande para un solo elemento.
tmaric
Otra nota: dado que estoy en flujos de dos fases, incluso para flujo altamente disperso (muchas burbujas), tendré tal vez hasta un 25% del recuento total de células que necesita ser refinado, lo que significa que para un sistema completamente desestructurado AMR local, cada vez que refino, copio toda la malla solo para el 25% de las células que están activas en el refinamiento.
tmaric
2
Si usa una estructura de datos estática, realmente no hay una manera eficiente de agregar nuevos datos sin copiar laboriosamente los datos antiguos en un nuevo vector. Una operación de inserción / eliminación costaría una operación , donde es la longitud del vector. Hasta donde sé, solo se puede hacer de manera eficiente si utiliza una estructura de datos dinámica (árbol, gráfico, etc.) que utiliza aproximadamente las operaciones . Θ(norte)norteΘ(1)
Paul
2
No sé qué usan otras bibliotecas, pero en deal.II tenemos una combinación de estructuras de datos estáticos y dinámicos: tenemos un std :: vector para cada nivel de la malla jerárquica. Si las celdas se vuelven gruesas, marcamos los elementos del vector como no utilizados. Si las celdas se refinan, los elementos secundarios se colocan en el vector std :: del siguiente nivel, primero en elementos no utilizados, luego se agregan al final. Cuando la reasignación es necesaria porque se agregan elementos, primero contamos cuántos elementos nuevos necesitaremos durante el refinamiento y hacemos una única asignación. En este esquema, el costo de asignación / copia es insignificante.
Wolfgang Bangerth

Respuestas:

4

De los comentarios anteriores, entiendo que desea evitar copiar el vector cuando agrega más celdas. El enfoque más fácil es reservar espacio para la cantidad máxima de celdas que desee tener:

std::vector<YourCellType> myVectorOfCells;
vectorOfCells.reserve(maxNoCells);

Su vector ha asignado espacio para crear celdas maxNoCells pero aún no se han creado celdas. Ahora puede agregar maxNoCells a su vector, cada operación a O(1)tiempo, sin que el vector se copie. Sin embargo, el estándar C ++ requiere que la operación push_back sea tiempo amortizado O(1) . Si agrega más que maxNoCells, el vector se copiará a sí mismo, reservando espacio para k-veces tantas celdas como tenía anteriormente (las implementaciones típicas eligen ak entre 1.4 y 2), para que pueda seguir agregando celdas al vector a O(1)tiempo. Esta operación de cambio de tamaño no lo es O(1).

O(1)norte/ /2norte/ /2O(1)tiempo ... en la medida en que reserve memoria primero, ¡también puede agregar elementos en O (1) tiempo! Como el profesor Bangerth mencionó anteriormente, las estructuras de datos jerárquicos como los árboles también usan vectores internamente para almacenar sus datos.

Sin embargo, creo que es una mejor práctica asignar memoria al comienzo de la simulación. Debe saber cuántas celdas puede necesitar para verificar si tiene suficiente memoria disponible. No desea que su simulación en 200,000 procesadores tenga que reasignar su estructura de datos o quedarse sin memoria y tener que cambiar al disco. En caso de que eso ocurra, mi opinión es que su programa debería fallar en voz alta debido a un error de entrada del usuario.

gnzlbg
fuente
¡Gracias! :) Comprobaré la funcionalidad de la operación de reserva para la estructura dinámica de datos vectoriales en OpenFOAM ... Creo que la operación ahora se ejecuta en función de los datos de malla que se leen desde el disco, llenando la estructura de datos hasta el final .
tmaric