Bases teóricas de los modelos gauge

Variables de programa, condiciones iniciales y ley de Gauss en lphi4, lphi4U1 y lphi4SU2U1, verificadas contra los papers y contra el código. Escrita para el proyecto final.

¿No sos de física? La bitácora del proyecto cuenta lo mismo en palabras simples.

¿Qué es CosmoLattice? explica qué ecuaciones resuelve el código. Esta página baja un nivel: cómo esas ecuaciones se convierten en los números que efectivamente maneja la computadora. Hay que entender eso antes de elegir parámetros para una corrida, porque cada valor de un archivo .in (lambda, q, gU1s, kIR, dt...) está en unidades de programa, y leerlo mal cambia la física que se simula.

Cada paso algebraico marcado con ✓ está reproducido simbólicamente en code/verificar_variables_de_programa.py. El script no corre CosmoLattice ni lee sus fuentes C++: toma las fórmulas publicadas y lo que hace el código, y chequea con sympy que coincidan. Lo único que lee son los .in por defecto, en la comparación final. Las ecuaciones se citan como en la otra página: (Art I, ec. N) y (Manual de usuario, ec. N). Las rutas de código son relativas a CosmoLattice/, en el commit fijado en el README.

Variables de programa: la elección de \((\alpha, f_*, \omega_*)\)

Los campos físicos del recalentamiento tienen amplitudes del orden de \(10^{18}\,\)GeV, y los acoplamientos pueden ser del orden de \(10^{-14}\). Ningún integrador numérico se lleva bien con eso. CosmoLattice reescala todo con tres constantes elegidas por el usuario: una escala de campo \(f_*\), una escala de frecuencia \(\omega_*\) y un exponente \(\alpha\) que define la variable temporal:

\[ \tilde\varphi \equiv \frac{\varphi}{f_*}\,,\qquad d\tilde\eta \equiv a^{-\alpha}\,\omega_*\,dt\,,\qquad d\tilde x^i \equiv \omega_*\,dx^i\,,\qquad \widetilde V \equiv \frac{V}{f_*^2\,\omega_*^2}\,. \]

(Art I, ecs. 174–175)

La acción se factoriza como \(S = (f_*/\omega_*)^2\,\widetilde S\) (Art I, ec. 172), así que las ecuaciones de movimiento en las variables con tilde tienen la misma forma que las físicas:

\[ \tilde\varphi_a'' - a^{-2(1-\alpha)}\tilde\nabla^2\tilde\varphi_a + (3-\alpha)\frac{a'}{a}\tilde\varphi_a' + a^{2\alpha}\,\widetilde V_{,\tilde\varphi_a} = 0\,. \]

(Art I, ec. 176)

La elección natural para un inflatón que oscila en un potencial \(\propto|\varphi|^p\) es tomar \(f_*\) igual a la amplitud inicial \(\varphi_*\), \(\omega_*\) igual a la frecuencia de oscilación en ese momento, y \(\alpha\) tal que el período de oscilación quede constante en tiempo de programa. En general, \(\alpha = 3(p-2)/(p+2)\) (Art I, ec. 464). Para \(p=4\) eso da \(\alpha = 1\) (tiempo conforme) y \(\omega_* = \sqrt\lambda\,\varphi_*\) (Art I, ec. 463). Los tres modelos de este proyecto lo implementan así:

modelo\(\alpha\)\(f_*\)\(\omega_*\)dónde
lphi41initial_amplitudes[0] \(=\varphi_*\)\(\sqrt\lambda\,f_*\)models/lphi4.h
lphi4U11cmplx_field_initial_norm \(=|\phi_*|\)\(\sqrt\lambda\,f_*\)models/lphi4U1.h
lphi4SU2U11SU2Doublet_initial_norm \(=|\Phi_*|\)\(\sqrt\lambda\,f_*\)models/lphi4SU2U1.h

Con esta elección los campos arrancan con amplitud de orden 1 y una oscilación del inflatón dura siempre unas pocas unidades de \(\tilde\eta\). Por eso dt = 0.01 y tMax = 10 en los .in por defecto son tiempos de programa, no segundos ni GeV\(^{-1}\).

El potencial en variables de programa

El control escalar, lphi4, tiene un inflatón con autoacoplamiento cuártico y un campo hijo \(\chi\) acoplado cuadráticamente:

\[ V(\varphi,\chi) = \frac{\lambda}{4}\varphi^4 + \frac12 g^2\varphi^2\chi^2 \ \Longrightarrow\ \widetilde V(\tilde\varphi,\tilde\chi) = \frac14\tilde\varphi^4 + \frac12\,q\,\tilde\varphi^2\tilde\chi^2\,, \qquad q \equiv \frac{g^2\varphi_*^2}{\omega_*^2} = \frac{g^2}{\lambda}\,. \]

(Art I, ecs. 468–470 con \(p=4\))

La última igualdad usa \(\omega_*=\sqrt\lambda\,\varphi_*\). Explica por qué lphi4.h lee q del archivo de entrada y reconstruye el acoplamiento físico como g = sqrt(q * lambda): el parámetro de resonancia \(q\) controla la física del recalentamiento, y \(g\) es sólo un derivado de él.

✓ Chequeos 1–3. Dividir \(V\) por \(f_*^2\omega_*^2\) con \(\varphi = f_*\tilde\varphi\) da exactamente potentialTerms(0) = 0.25*fldS(0)^4 y potentialTerms(1) = 0.5*q*(fldS0*fldS1)^2. Las derivadas coinciden con potDeriv/potDeriv2 de models/lphi4.h, y \(\partial^2\widetilde V/\partial\tilde\varphi^2|_{\chi=0} = 3\tilde\varphi^2\) es la masa efectiva que entra en \(\omega_k\) al generar las fluctuaciones (Art I, ecs. 471–472).

Los modelos gauge siguen la misma lógica. lphi4U1 tiene un solo escalar complejo con \(V=\lambda|\phi|^4\), que en variables de programa queda \(\widetilde V = |\tilde\phi|^4\) (potentialTerms(0) = pow<4>(norm(fldCS))). lphi4SU2U1 implementa

\[ V(\varphi,|\phi|,|\Phi|) = \lambda|\Phi|^4 + g^2|\Phi|^2\varphi^2 + 2h^2|\Phi|^2|\phi|^2 \ \Longrightarrow\ \widetilde V = |\tilde\Phi|^4 + q_G\,|\tilde\Phi|^2\tilde\varphi^2 + 2q_H\,|\tilde\Phi|^2|\tilde\phi|^2\,, \]

(Manual de usuario, ec. 90; models/lphi4SU2U1.h, potentialTerms(0..2))

con \(q_G = g^2/\lambda\) y \(q_H = h^2/\lambda\) por el mismo argumento que en lphi4. Son los qG y qH del .in.

Friedmann en variables de programa

Cuando la expansión la generan los propios campos, el factor de escala sigue la primera ecuación de Friedmann, \(H^2 = \rho/3m_p^2\). En variables de programa, con \(\rho = f_*^2\omega_*^2\,\tilde\rho\) y la regla de la cadena \(a' = \dot a\,a^\alpha/\omega_*\), queda

\[ \Big(\frac{a'}{a}\Big)^2 = \frac{a^{2\alpha}}{3}\Big(\frac{f_*}{m_p}\Big)^2 \big[\widetilde E_K + \widetilde E_G + \widetilde E_V\big]\,. \]

(Art I, ecs. 177–181)

✓ Chequeo 4. La derivación de arriba reproduce la fórmula publicada y la línea que inicializa \(a'\) en include/CosmoInterface/initializers/scalefactorinitializer.h: aDotI = fStar / MPl * sqrt(rhoMC / 3.0) (con \(a_*=1\)).

La consecuencia práctica: \(\omega_*\) no aparece. Toda la influencia de la gravedad sobre la dinámica de los campos pasa por el cociente \(f_*/m_p\). Con \(f_*\sim\varphi_*\) de orden \(m_p\), que es lo que pasa al final de la inflación caótica, la expansión no es una corrección pequeña: hay que simularla de manera autoconsistente (expansion = true).

Los sectores gauge: U(1) y SU(2)

Los escalares cargados se reescalan igual que los singletes, pero los campos gauge se normalizan con \(\omega_*\), no con \(f_*\):

\[ \tilde\phi = \frac{\phi}{f_*}\,,\quad \tilde A_\mu = \frac{A_\mu}{\omega_*}\,; \qquad \tilde\Phi = \frac{\Phi}{f_*}\,,\quad \tilde B_\mu^a = \frac{B_\mu^a}{\omega_*}\,. \]

(Art I, ecs. 279 y 368)

El motivo es que así la variable de enlace no cambia de forma: \(e^{-ig_AQ_A\,\delta x_\mu A_\mu} = e^{-ig_AQ_A\,\delta\tilde x_\mu \tilde A_\mu}\), porque el \(\omega_*\) de \(\tilde A\) cancela el de \(\delta\tilde x\). Por eso los acoplamientos gauge gU1s y gSU2s se escriben en el .in sin ningún reescalado. Los momentos conjugados, en gauge temporal \(\tilde A_0=0\), son

\[ \tilde\pi_\phi \equiv a^{3-\alpha}\tilde\phi'\,,\qquad (\tilde\pi_A)_i \equiv a^{1-\alpha}\tilde F_{0i}\,,\qquad (\tilde\pi_B)^a_i \equiv a^{1-\alpha}\tilde G^a_{0i}\,, \]

(Art I, ecs. 282–283, 371–372)

y la energía cinética (eléctrica) gauge en unidades de programa arrastra un factor \(\omega_*^2/f_*^2\) que los escalares no tienen: \(\widetilde E_K^A = \frac{1}{2a^4}\frac{\omega_*^2}{f_*^2}\sum_i\langle(\tilde\pi_A)_i^2\rangle\) (Art I, ec. 285).

Cuánto se excitan los campos gauge

Al expandir la derivada covariante del doblete aparecen términos \(Q_A^2g_A^2|\Phi|^2|\vec A|^2\) y \(\frac14Q_B^2g_B^2|\Phi|^2\sum_a|\vec B^a|^2\) (Art I, ec. 475). Tienen la misma estructura que el acoplamiento \(\frac12g^2\varphi^2\chi^2\) del control escalar. Por eso, durante la fase lineal, un campo gauge se comporta como un campo hijo escalar con parámetros de resonancia

\[ q_{A*} \equiv \frac{Q_A^2\,g_A^2\,\varphi_*^2}{\omega_*^2}\,,\qquad q_{B*} \equiv \frac{Q_B^2\,g_B^2\,\varphi_*^2}{4\,\omega_*^2}\,, \qquad \varphi_*\equiv\sqrt2\,|\Phi_*|\,. \]

(Art I, ec. 476)

Esto es lo que vuelve controlada la comparación del proyecto. Si se fija \(q_{A*}\) igual al \(q\) del control, el campo gauge entra a la resonancia igual que el hijo escalar. Cualquier diferencia en \(\Omega_{\rm GW}(f)\) aparece recién en la fase no lineal, y ahí es donde entran los términos \(E_iE_j\), \(B_iB_j\) del estrés anisotrópico. Con \(g_A\) y \(g_B\) ambos encendidos, los dos sectores resuenan juntos con \(q_{\rm eff*} = q_{A*}+q_{B*}\) (Art I, discusión posterior a la tabla 1).

Condiciones iniciales: fluctuaciones de vacío

Cada campo arranca como un modo homogéneo más fluctuaciones que imitan el vacío cuántico: \(P_{\delta\varphi}(k) = 1/(2a^2\omega_k)\), con \(\omega_k = \sqrt{k^2+a^2m^2}\) y \(m^2 = V_{,\varphi\varphi}\) evaluada en el fondo (Art I, ec. 428). Para que el lattice reproduzca la varianza del continuo sin depender del volumen, la varianza de cada modo de Fourier discreto tiene que ser

\[ \big\langle|\delta\tilde\varphi(\tilde{\mathbf n})|^2\big\rangle = \Big(\frac{\omega_*}{f_*}\Big)^2\Big(\frac{N}{\delta\tilde x}\Big)^3 \frac{1}{2a^2\sqrt{\tilde k^2+a^2\tilde m^2}}\,. \]

(Art I, ecs. 433–436; Manual de usuario, ec. 62)

El factor \((\omega_*/f_*)^2\) es el que el paper advierte que puede volverse diminuto. Con los valores por defecto de lphi4.in (\(\lambda\sim10^{-13}\)) es \(\lambda\). Esto es física, no un problema numérico: las fluctuaciones de vacío son chicas frente al condensado, y es la resonancia paramétrica la que las amplifica exponencialmente.

✓ Chequeo 5. include/CosmoInterface/initializers/fluctuationsgenerator.h, getFluctuationsNorm, devuelve el rms de la parte real (y, por separado, de la imaginaria) de cada modo: \(\frac{\omega_*}{f_*}\big(L/\delta\tilde x^2\big)^{3/2}(2\omega_k)^{-1/2}/\sqrt2\). Sumando las dos partes, \(2\,\mathrm{Norm}^2\) coincide con la fórmula publicada en \(a=1\), usando \(L=N\delta\tilde x\).

La fase de cada modo se construye superponiendo una onda que viaja a la izquierda y otra a la derecha, con fases aleatorias uniformes y módulos con distribución de Rayleigh (Art I, ecs. 437–438). Así se evita elegir una dirección preferida y el campo resulta gaussiano.

Condiciones iniciales de los campos gauge y la ley de Gauss

La ley de Gauss es una restricción, no una ecuación de evolución: las ecuaciones de movimiento la conservan si se cumple al principio, pero no la corrigen si arranca violada. CosmoLattice la impone al inicializar así (Art I, §7.2):

  1. Los campos gauge arrancan en cero en todos los sitios: \(A_i = B^a_i = 0\) (ecs. 443–444). La energía magnética inicial es exactamente nula.
  2. Los escalares cargados reciben fluctuaciones como en la sección anterior, con una restricción extra: las ondas izquierda y derecha tienen el mismo módulo, y una de las fases queda fijada por las otras (ecs. 452–453). Con eso la carga total inicial es cero, \(J_0(\mathbf k=0)=0\), que es la condición de compatibilidad de Gauss en una caja periódica (ec. 451).
  3. Se calcula la densidad de carga que producen esas fluctuaciones, \(J_0^A = 2g_AQ_A\,\mathrm{Im}[\phi^*\phi']\) (ec. 447), y se eligen las derivadas temporales de los campos gauge para que Gauss se cumpla modo a modo.

En el lattice, la ley de Gauss usa la derivada espacial hacia atrás, \(-\sum_i\Delta_i^-(\tilde\pi_A)_i = 2g_AQ_A(f_*^2/\omega_*^2)\,\mathrm{Im}[\tilde\phi^*\tilde\pi_\phi]\) (Art I, ec. 298; la versión SU(2) es la ec. 388). En Fourier, \(\Delta_i^-\) se vuelve multiplicación por el momento efectivo complejo \(k^-_{{\rm eff},i} = 1-e^{-ik_i}\), cuyo módulo cuadrado es \(|k_{\rm eff}|^2 = \sum_i\big(2-2\cos k_i\big) = \sum_i 4\sin^2(k_i/2)\), el momento de lattice de la ec. 78. La solución que se asigna es

\[ \tilde\pi_i(\mathbf k) = \frac{\overline{k^-_{{\rm eff},i}}}{|k^-_{\rm eff}|^2}\,j_0(\mathbf k)\,, \]

(Art I, ec. 455; include/CosmoInterface/initializers/u1initializer.h, línea 107: conj(keffm(i)) * (1 / keffm2) * j0)

✓ Chequeo 6. \(\sum_i k^-_{{\rm eff},i}\,\tilde\pi_i(\mathbf k) = j_0(\mathbf k)\) idénticamente, para todo \(\mathbf k\neq0\): la asignación de u1initializer.h resuelve la ley de Gauss discreta por construcción, no aproximadamente. Es el mismo argumento que la ec. 450 del continuo, con la derivada del lattice en lugar de \(k_i\). (Una nota técnica: sp.simplify no llega a cancelar las exponenciales complejas por sí solo. El script reintenta con expand_complex antes de declarar falla, y el residuo da cero.)

Esto es lo que hace que la ley de Gauss sea un diagnóstico útil para las corridas del proyecto. Si arranca satisfecha a precisión de máquina, cualquier violación que aparezca después mide el error del integrador y no un defecto de la condición inicial. El Art I (figs. 5 y 8) muestra que con los modelos por defecto se mantiene a precisión de máquina. Es lo primero que hay que chequear en cada corrida gauge de este proyecto.

El escalar complejo y el factor \(\sqrt2\)

El Art I (ec. 9) define \(\phi = (\phi_0+i\phi_1)/\sqrt2\), y en lphi4U1.h cada componente del estado inicial se carga como normCmplx0/sqrt(2). Podía haber un \(\sqrt2\) perdido, según si el código guarda \((\phi_0,\phi_1)\) o \((\mathrm{Re}\,\phi,\mathrm{Im}\,\phi)\). Tres lugares del código lo deciden, y los tres dicen lo mismo: las componentes son \(\mathrm{Re}\,\phi\) e \(\mathrm{Im}\,\phi\), y norm(fldCS) \(=|\phi|\).

Por lo tanto la normalización del código es consistente con el paper. La frase del Manual (discusión posterior a la ec. 90) de que así se obtiene \(\phi_{0*} = |\phi_*|\) también es correcta: \(\phi_0 = \sqrt2\,\mathrm{Re}\,\phi = \sqrt2\cdot|\phi_*|/\sqrt2\).

✓ Chequeo 7. El Lagrangiano \(|\phi'|^2 - V(|\phi|)\) en componentes \((\mathrm{Re}\,\phi,\mathrm{Im}\,\phi)\) reproduce el kernel del código. El módulo equivale a un singlete canónico \(\varphi_r = \sqrt2\,|\phi|\): \(\lambda|\phi|^4 = \tfrac\lambda4\varphi_r^4\) y \(|\phi'|^2 = \tfrac12\varphi_r'^2\). Con eso, la ec. 476 da \(q_{A*} = Q_A^2g_A^2/\lambda\) y \(q_{B*} = Q_B^2g_B^2/(4\lambda)\).

El \(\sqrt2\) sí aparece en dos lugares, y los dos importan para el proyecto:

  1. \(\omega_*\) del código \(= \omega_*\) de la ec. 463 \(/\sqrt2\). El código toma \(\omega_* = \sqrt\lambda\,|\phi_*|\), mientras que la frecuencia natural de oscilación es \(\sqrt\lambda\,\varphi_* = \sqrt{2\lambda}\,|\phi_*|\). No es un error, porque \(\omega_*\) es una elección de unidades. Pero implica dos cosas: en lphi4U1 una unidad de tiempo de programa no es la misma que en lphi4, y \(q_{A*}\) hay que calcularlo con la ec. 476 tal como está escrita, no con el \(\omega_*\) del código (que daría el doble).
  2. Los .in por defecto no son una comparación controlada. lphi4.in y lphi4U1.in escriben el mismo número, 5.6964e18, como amplitud inicial. Pero en lphi4U1 ese número es \(|\phi_*|\), que equivale a un singlete \(\sqrt2\) veces más grande. Resultado: la densidad de energía homogénea inicial de lphi4U1 es 4 veces la de lphi4, y además \(q_{A*}\approx1370\) contra \(q=300\) del control. Los defaults de lphi4SU2U1 (gSU2s = 2·gU1s) dan \(q_{A*}=q_{B*}\approx1370\), la elección \(q_{A*}=q_{B*}\) del Art I, §8.3.

Para que lphi4U1 sea el control más un campo gauge, y nada más, a partir de lphi4.in por defecto:

parámetro de lphi4U1.inpor defectoemparejado con lphi4
cmplx_field_initial_norm5.6964e185.6964e18/√2 = 4.02796e18
cmplx_momentum_initial_norm−6.88343e30−4.86735e30/√2 = −3.44174e30
gU1s (para \(q_{A*}=q=300\))1.11037e−5\(\sqrt{300\lambda}\) = 5.19615e−6

Salen de comparar_defaults() en el script y están registrados en provenance/numbers.json. Con esto el inflatón arranca en el mismo estado físico en las dos corridas, y el campo gauge entra a la resonancia con el mismo \(q\) que el hijo escalar del control. (El control tiene además al hijo \(\chi\), que lphi4U1 no tiene: la comparación es "hijo escalar con \(q\)" contra "hijo gauge con \(q_{A*}=q\)".) Queda por decidir si \(q=300\) es el punto de referencia correcto: es la default del control, no una elección física del proyecto.

El sector SU(2): carga inicial nula y ley de Gauss no abeliana

El doblete sigue la misma normalización que el escalar complejo: MakeSU2Doublet(a, norm/2) carga las cuatro componentes reales con \(|\Phi_*|/2\), así que norm(fldSU2Doublet) \(=|\Phi|\). La energía cinética no lleva ½ (kineticSU2Doublet), y el kernel tiene el ½ de la ec. 369 del Art I (su2doubletkernels.h). Por eso vale el mismo mapa \(\varphi_r=\sqrt2\,|\Phi|\) que usa la ec. 476. Lo que cambia respecto de U(1) es la inicialización, en dos pasos.

1. La carga total tiene que arrancar en cero

En una caja periódica, la ley de Gauss sólo tiene solución si la carga total es nula. Con un doblete hay cuatro cargas: la U(1), \(\propto\mathrm{Im}[\Phi^\dagger\Phi']\), y las tres SU(2), \(\propto\mathrm{Im}[\Phi^\dagger\sigma_a\Phi']\) (Art I, ecs. 447–448). Si las fluctuaciones fueran independientes por componente, las cuatro serían chicas pero no nulas. El Art I (ecs. 451–453) las anula exactamente con dos restricciones, que su2initializer.h implementa tal cual:

✓ Chequeo 8 (carga). Escribí las cuatro densidades de carga como formas bilineales en las componentes reales del doblete (derivadas directamente de \(\Phi=(\phi_0+i\phi_1,\phi_2+i\phi_3)/\sqrt2\), no copiadas del PDF). Después evalué su modo cero con la construcción del código, incluido el término \(-\dot a\,\delta\phi/\sqrt2\) de los momentos. Las cuatro se anulan idénticamente en cada \(\mathbf k\).

El chequeo mostró además algo que no está escrito en ningún lado. La ec. 442 del paper le asigna a cada componente su propia frecuencia \(\omega_{k,n}\), pero el código usa omega0, la de la componente 0, para las cuatro. No es un descuido: con frecuencias distintas por componente la carga no se anula. El script lo muestra con el residuo explícito. En lphi4SU2U1 las cuatro componentes arrancan iguales, así que sus masas coinciden y la diferencia no importa. Sí importaría en un modelo con un doblete inicial asimétrico.

2. Gauss, color por color

La ley de Gauss no abeliana del lattice transporta el momento del sitio vecino con los enlaces: \(\sum_i[\tilde\pi_i(\mathbf n) - U_i^\dagger\tilde\pi_i(\mathbf n-\hat\imath)U_i]/\delta\tilde x\) (Art I, ec. 388). En \(t=0\) el código pone \(B=0\) y unitariza, así que \(U_i=\mathbb I\). El transporte es trivial y, para cada color \(a\), la ecuación es la misma divergencia hacia atrás que en U(1). su2initializer.h la resuelve con la misma fórmula, conj(keffm(i)) * (1 / keffm2) * j0a, que el chequeo 6 ya verificó.

✓ Chequeo 8 (Gauss). Con \(U=\mathbb I\) el lado izquierdo de la ec. 388 se reduce a \(\tilde\pi_i(\mathbf n)-\tilde\pi_i(\mathbf n-\hat\imath)\). Además, comparando código contra código, lo que impone el inicializador (j0a = -dx·ρ^a) es lo que mide gausslaws.h::checkSU2 (RHS = -ρ^a, LHS = (1/dx)·Σ(...)). Lo mismo pasa en U(1).

Un fix reciente de upstream. El medidor SU(2) tenía un dx de más en el lado derecho hasta el commit f6b9c267 (3 de agosto de 2026, "a factor of dx too much in gauss' law SU(2)"). Según su propio comentario, reportaba una violación relativa cercana a 0.6 aun con la restricción exactamente satisfecha. El commit fijado en este proyecto (acc8278) ya lo incluye. Una corrida de lphi4SU2U1 hecha con una versión anterior a esa fecha habría mostrado una violación de Gauss espuria, que no dice nada de la física.

Emparejar lphi4SU2U1 con el control

Los defaults de lphi4SU2U1.in tampoco parten del estado de lphi4: su densidad de energía homogénea inicial es 2.48 veces la del control. Pero el modelo sí puede contener al control exactamente. El término \(g^2|\Phi|^2\varphi^2\) del Manual (ec. 90), escrito con \(\varphi_r=\sqrt2|\Phi|\), es \(\frac12g^2\varphi_r^2\varphi^2\): el mismo acoplamiento que tiene \(\chi\) en lphi4, con qG \(=g^2/\lambda=q\).

parámetro de lphi4SU2U1.inpor defectoemparejado con lphi4
SU2Doublet_initial_norm5.25151e185.6964e18/√2 = 4.02796e18
SU2Doublet_initial_momenta_norm−4.45258e30−4.86735e30/√2 = −3.44174e30
qG (hijo singlete ↔ \(\chi\))50300
gU1s (\(q_{A*}=300\))1.11037e−55.19615e−6
gSU2s (\(q_{B*}=300\))2.22075e−51.03923e−5

Con esto, la corrida SU(2)×U(1) es "el control más dos campos gauge": el doblete oscila como el inflatón de lphi4, el hijo singlete resuena como \(\chi\), y los campos gauge entran con el mismo \(q\). Quedan dos decisiones abiertas, anotadas abajo.

Qué queda abierto

Cómo correr la verificación

python3 code/verificar_variables_de_programa.py

Sólo necesita sympy. Imprime cada cuenta intermedia; las líneas de resultado son:

[OK] V_programa == varphi_pr^4 / 4  (potentialTerms(0) del codigo: 0.25*fldS(0)^4)
[OK] Vint_programa == (q/2) * varphi_pr^2 * chi_pr^2  (potentialTerms: 0.5*q*(fldS0*fldS1)^2)
[OK] d^2V_pr/d(varphi_pr)^2 en el punto homogeneo (chi_pr=0) define la masa m_pr^2 usada en omega_k
[OK] (a'/a)^2 == a^(2 alpha) * (f_star/M_pl)^2 * rho_pr/3  (scalefactorinitializer.h / hubbleconstraint.h)
[OK] 2*Norm(k)^2 == (omega_star/f_star)^2 (L/dx^2)^3 / (2 omega_k)  [formula publicada, a=1]
[OK] (L/dx^2)^3 == (N/dx)^3 cuando L = N*dx
[OK] sum_i k_eff_i * pi_i(k) == j_0(k)  (la asignacion de u1initializer.h resuelve Gauss por construccion)
[OK] x'' del Lagrangiano |phi'|^2 - V(|phi|) == kernel del codigo (-1/2 * V'(|phi|) x/|phi|)
[OK] V = lambda |phi|^4 == (lambda/4) varphi_r^4 con varphi_r = sqrt(2)|phi|
[OK] cinetica |phi'|^2 (codigo) == (1/2) varphi_r'^2 (singlete canonico)
[OK] q_A* == Q_A^2 g_A^2 / lambda
[OK] q_B* == Q_B^2 g_B^2 / (4 lambda)
[OK] omega_* del codigo == omega_* de la ec. 463 / sqrt(2)  (eleccion de unidades, no un error)
[OK] carga U(1): modo cero nulo con la construccion de su2initializer.h
[OK] carga SU(2) a=1: modo cero nulo con la construccion de su2initializer.h
[OK] carga SU(2) a=2: modo cero nulo con la construccion de su2initializer.h
[OK] carga SU(2) a=3: modo cero nulo con la construccion de su2initializer.h
[OK] con frecuencias distintas por componente la carga NO se anula (justifica omega0 comun)
[OK] con U = identidad, pi(x) - U^dag pi(x-i) U == pi(x) - pi(x-i)  (divergencia hacia atras, como U(1))
[OK] g^2|Phi|^2 varphi^2 / (f_*^2 omega_*^2) == (g^2/lambda) |Phi~|^2 varphi~^2  => qG = g^2/lambda
[OK] g^2 |Phi|^2 varphi^2 == (1/2) g^2 varphi_r^2 varphi^2 con varphi_r = sqrt(2)|Phi|  (= hijo de lphi4)
       q de lphi4.in                       = 300
       q_A* de lphi4U1.in (gU1s^2/lambda)  = 1369.91
       q_A*, q_B* de lphi4SU2U1.in         = 1369.91, 1369.93
       rho_inicial(U1) / rho_inicial(lphi4) = 3.99998
       rho_inicial(SU2U1) / rho_inicial(lphi4) = 2.4841
       para igualar a lphi4: cmplx_field_initial_norm    = 4.02796e+18
                             cmplx_momentum_initial_norm = -3.44174e+30
                             gU1s (q_A* = q = 300)       = 5.19615e-06
       (SU2U1: SU2Doublet_initial_norm / _momenta_norm = los mismos dos valores de arriba)
                             gSU2s (q_B* = q = 300)      = 1.03923e-05
                             qG (hijo singlete = chi)    = 300
Todas las verificaciones terminaron OK.

Si una cuenta no cierra, el script frena con AssertionError y muestra el residuo no nulo.