El problema con el software de química computacional (ORCA, GAMESS, etc.), como se describe en la respuesta de NotEvans y en varios comentarios, es que sólo escupe una lista de desplazamientos químicos y constantes de acoplamiento. Por ejemplo, esto es parte de una salida típica de ORCA:
--------------
Nucleus 34H :
--------------
[...]
Total shielding tensor (ppm):
28.820 -0.203 1.178
-2.079 29.083 1.927
1.392 3.320 24.895
Diagonalized sT*s matrix:
sDSO 23.705 26.255 39.984 iso= 29.981
sPSO -0.555 2.878 -9.468 iso= -2.382
--------------- --------------- ---------------
Total 23.149 29.133 30.516 iso= 27.599
Pasar de una lista de números a algo parecido a un espectro es un asunto completamente distinto. Para ello, habría que utilizar esos parámetros para construir un hamiltoniano de espín:
^Hfree=∑iΩi^Iiz+∑ij2πJij^Iiz^Ijz
y luego realizar una simulación mecánica cuántica, donde un matriz de densidad ρ evoluciona bajo este Hamiltoniano libre, así como bajo cualquier otro Hamiltoniano correspondiente a los pulsos, de acuerdo con la Ecuación de Liouville-von Neumann . Después de la secuencia de impulsos, se puede obtener el FID midiendo el valor esperado del operador ∑i^Ii− a intervalos regulares correspondientes al tiempo de permanencia de la RMN y, a continuación, el espectro mediante la transformación de Fourier.
La mejor herramienta general para ello es Espinacas que se codifica en MATLAB. Spinach es de código abierto, pero MATLAB no (y el código de Spinach no es de código abierto). no en GNU Octave). Por lo tanto, no cumple del todo los criterios de la pregunta, pero pensé que debía mencionarlo de todos modos.
Específicamente para su uso con ORCA El grupo de Stefan Grimme ha trabajado mucho en este ámbito, véase Angew. Chem. Int. Ed. 2017, 56 (46), 14763-14769 . Existen varios scripts de Python capaces de realizar esta simulación del hamiltoniano de espín, así como de trazar el espectro. De hecho, ahora debería ser posible interactuar con todos ellos directamente desde ORCA, de forma que con un ORCA se pueden realizar todos los pasos descritos en el artículo (generación de conformadores, cálculo de propiedades de RMN, simulación del hamiltoniano de espín y representación gráfica). Sugiero consultar el manual de ORCA para más información.
ORCA no es de código abierto propiamente dicho pero es de uso gratuito, que es lo que creo que pretendes en líneas generales (prefiero no entrar en debates sobre qué significa software "libre ).
Por si sirve de algo, si se tienen los conocimientos de programación necesarios, es bastante fácil escribir un script (por ejemplo) en Python que sea capaz de simular sistemas de dos o tres espines (quizá cuatro). Al fin y al cabo, un experimento de RMN es "sólo" un montón de operadores unitarios que actúan sobre matrices de densidad, es decir, mucha, mucha multiplicación de matrices. Por ejemplo, puedes echar un vistazo a parte de mi código MATLAB aquí que simula el primer FID de un experimento HSQC de sensibilidad mejorada. Es bastante trivial portar esto a Python, ya que numpy le proporciona prácticamente todas las funciones que pueda necesitar.
[Descargo de responsabilidad: el código no tiene por qué permanecer ahí para siempre].
El único problema es que esto se escala exponencialmente con el número de giros, por lo que a menos que se haga una optimización seria del código (como la que se hace en Spinach), se vuelve intratable muy rápidamente. (También depende del tipo de espectro que se quiera: un simple experimento de protones en 1D es fácil, pero si se quiere uno en 2D hay que simular varios FID, y la complejidad aumenta rápidamente si se utilizan pulsos con forma y, especialmente, si hay algún tipo de elemento dependiente del espacio, como gradientes de campo pulsados).
Pero si tu molécula se puede "descomponer" en varios sistemas de espín que son pequeños, entonces el espectro global es sólo la suma del espectro de cada sistema de espín, por lo que podrías salirte con la tuya con un código más simple. Nunca he pensado en cómo se podría hacer eso, aunque mi conjetura es que usted querría construir una matriz hamiltoniana, luego pasarla a una función que se llamaría a sí misma recursivamente si la matriz se puede escribir en forma de bloque diagonal.