Este es un simple problema de enumeración de simetría. Doy todos los antecedentes aquí, pero no se necesita conocimiento de química cuántica.
La integral de dos partículas es: Y tiene las siguientes 4 simetrías: Tengo una función que calcula la integral y la almacena en una matriz 1D , indexada de la siguiente manera:⟨ i j | k l ⟩ = ∫ ψ * i ( x ) ψ * j ( x ' ) ψ k ( x ) ψ l ( x ' ) ⟨ i j | k l ⟩ = ⟨ j i | l k ⟩ = ⟨ k l | i j ⟩ = ⟨ l k | j i ⟩
int2
int2(ijkl2intindex2(i, j, k, l))
donde la función ijkl2intindex2
devuelve un índice único, teniendo en cuenta las simetrías anteriores. El único requisito es que si realiza un bucle sobre todas las combinaciones de i, j, k, l (de 1 a n cada una), llenará la int2
matriz consecutivamente y asignará el mismo índice a todas las combinaciones de ijkl que están relacionadas por lo anterior 4 simetrías
Mi implementación actual en Fortran está aquí . Es muy lento. ¿Alguien sabe cómo hacer esto de manera efectiva? (En cualquier idioma.)
Sugerencia: si los orbitales son reales, además de las simetrías anteriores, se puede intercambiar y para obtener 8 simetrías en total: y luego uno puede implementar una función muy rápida para indexarlo, vea mi implementación aquí . Me gustaría encontrar un esquema de indexación eficiente para los casos en que los orbitales no son reales.
Nota: las funciones que implementé en realidad aceptan los cuatro números , , , en una notación de "química" , es decir, los argumentos y se intercambian, Pero esto no es importante.j k l ( i j | k l ) = ⟨ i k | j l ⟩ j k
fuente
Respuestas:
[Editar: cuarta vez es el encanto, por fin algo sensato]
Llegué a esto al revés: comencé con otra respuesta que mostraba el enfoque basado en filtros, y usé eso para generar todas las combinaciones válidas para una serie de valores de , y busqué la secuencia en la base de datos de secuencias de enteros en línea. El número de combinaciones es , lo que parece poco probable (¿por qué el 3?). También es donde es el número triangular de , . Habiendo entendido esto, necesitamos saber por qué.n n2(n2+3) t(t(n))+t(t(n−1)) t(a) a t(a)=a(a+1)/2
El primer término es más simple: los pares de pares donde y , donde es el índice triangular de . Eso se cumple con una función como esta:t i d ( i , j ) ≥ t i d ( k , l ) t i d ( a , b ) a , bi≥j tid(i,j)≥tid(k,l) tid(a,b) a,b
donde el segundo bucle es porque no podemos anidar el bucle completo dentro del bucle sin un if / skip para verificar los índices triangulares.l kl l k
El segundo término es donde el primer par es ascendente y el segundo par es descendente (nota, no ==, como se manejan arriba).t(t(n−1))
La combinación de ambos proporciona el conjunto completo, por lo que al unir ambos bucles se obtiene el conjunto completo de índices.
Un problema importante es que estos patrones son difíciles de calcular para un arbitrario i, j, k, l. Por lo tanto, sugeriría un mapa que arroje el índice dado i, j, k, l. Francamente, si está haciendo esto, también podría usar el enfoque de generar + filtro, porque solo necesita hacerlo una vez para un dado . El lado positivo del método anterior es que al menos tiene una estructura de bucle predecible.n
En python podemos escribir el siguiente iterador para darnos los valores idx e i, j, k, l para cada escenario diferente:
En fortran solo tendríamos que ejecutar el ciclo y almacenar los valores. Podemos usar un índice simple para almacenar la combinación i, j, k, l como un valor único ( ), y almacenar estos valores en una matriz cuyo índice es el mismo que el índice encima. Luego podemos iterar sobre esta matriz y recuperar i, j, k, l de los valores. Para obtener el idx para i, j, k, l arbitrario, se requeriría un mapa inverso y un filtro para manejar la simetría, aunque probablemente podríamos construir una función a partir de la estructura anterior. La función de generación de matriz idx en fortran sería:in3+jn2+kn+l
Y luego repítelo así:
fuente
Aquí hay una idea de usar una curva de relleno de espacio simple modificada para devolver la misma clave para los casos de simetría (todos los fragmentos de código están en python).
Notas:
Aquí hay un ejemplo de prueba para n = 2:
Salida para n = 2:
Si es de interés, la función inversa de forge_key es:
fuente
¿No se trata solo de la generalización del problema de indexación de matriz simétrica empaquetada? La solución es offset (i, j) = i * (i + 1) / 2 + j, ¿no es así? ¿No puede duplicar esto e indexar una matriz 4D doblemente simétrica? La implementación que requiere ramificación parece innecesaria.
fuente