Inicio Ejemplos Capturas de pantalla Manual de usuario Logotipo de Bluesky YouTube
OghmaNano Simule células solares orgánicas/de perovskita, OFETs y OLEDs DESCARGAR

Scripting en Python

1. Introducción

En OghmaNano, el scripting en Python funciona editando directamente los archivos de configuración de la simulación en disco y luego invocando el motor de simulación (oghma_core.exe) para ejecutar el modelo. Esta sección describe este flujo de trabajo en detalle.

2. Ejecutar archivos de simulación con Python

Una simulación de OghmaNano está definida completamente por un único archivo de configuración JSON, sim.json. Este archivo contiene el estado completo de la simulación, incluida la estructura del dispositivo, los parámetros del material, los ajustes numéricos y la configuración de salida. En muchos casos, sim.json ya existe como un archivo normal dentro del directorio de simulación.

Al controlar OghmaNano desde Python, el script lee sim.json en memoria usando la biblioteca estándar json de Python, modifica uno o más parámetros y escribe el JSON actualizado de nuevo en disco.

Es crucial que el script de Python se ejecute con su directorio de trabajo configurado en el directorio de simulación — es decir, el directorio que contiene sim.json (y sim.oghma). Este es el directorio desde el cual se lanza oghma_core.exe.

Una vez que el archivo JSON se ha actualizado, el script lanza oghma_core.exe desde ese mismo directorio. El motor de simulación siempre lee sus archivos de entrada desde el directorio de trabajo actual, por lo que si el directorio de trabajo es incorrecto, la simulación fallará o ejecutará el modelo equivocado.

Esta separación de responsabilidades es intencional y explícita: Python es responsable de definir qué cambia en la simulación, mientras que OghmaNano es responsable de ejecutar la física utilizando los archivos presentes en el directorio actual.

El ejemplo siguiente demuestra este proceso cargando sim.json, modificando la movilidad de portadores de la primera capa del dispositivo, escribiendo la configuración actualizada de nuevo en disco y luego ejecutando la simulación desde el directorio de simulación.


       import json
       import os
       import sys

       f=open('sim.json')              #abrir el archivo sim.json
       lines=f.readlines()
       f.close()
       lines="".join(lines)    #convertir el texto en un objeto json de python
     data = json.loads(lines)

     #Editar un valor (use firefox como visor json
     # para ayudarle a averiguar qué valor editar)
     # esta vez estamos editando la movilidad de la capa 1
     data['epitaxy']['segment1']['shape_dos']['mue_y']=1.0


     #convertir el objeto json de nuevo en una cadena
     jstr = json.dumps(data, sort_keys=False, indent='\t')

     #escribirlo de nuevo en disco
     f=open('sim.json',"w")
     f.write(jstr)
     f.close()

     #ejecutar la simulación usando oghma_core
     os.system("oghma_core.exe")

Si la simulación en sim.json está configurada para ejecutar una curva J–V, OghmaNano escribirá archivos de salida en el directorio de simulación que contienen magnitudes tales como PCE, factor de llenado, \(J_{sc}\) y \(V_{oc}\).

El ejemplo siguiente muestra cómo leer un archivo de salida JSON y añadir el valor de \(V_{oc}\) a un archivo de texto separado.

f=open('sim_info.dat')
lines=f.readlines()
f.close()
lines="".join(lines)
data = json.loads(lines)

f=open('out.dat',"a")
f.write(str(data["Voc"])+"\n");
f.close()

3. Simulaciones más complejas

En muchos flujos de trabajo de scripting querrá ejecutar la misma simulación base varias veces con distintos valores de parámetro y mantener cada ejecución aislada en su propio directorio. Esta es la forma más sencilla de mantener limpias las salidas y evitar sobrescribir accidentalmente resultados.

El ejemplo siguiente crea un conjunto de directorios correspondientes a cuatro movilidades (1e-5, 1e-6, 1e-7, 1e-8). Para cada directorio:

  1. Crea el directorio (si no existe ya).
  2. Copia el sim.json actual en ese directorio.
  3. Edita el sim.json copiado para establecer la movilidad objetivo.
  4. Cambia el directorio de trabajo a ese directorio.
  5. Ejecuta el solucionador en ese directorio, produciendo salidas locales a esa ejecución.

Este patrón es la base del scripting por lotes en OghmaNano: un directorio por ejecución, un archivo de configuración por ejecución y una carpeta de salida limpia para cada valor de parámetro.


       import json
       import os
       import shutil

       # El script debe iniciarse en el directorio base de simulación
       # (es decir, el directorio que contiene el sim.json de referencia).
       base_dir = os.getcwd()

       mobilities = [1e-5, 1e-6, 1e-7, 1e-8]

       for mu in mobilities:
           # Crear un nombre de directorio que sea fácil de leer y se ordene bien
           run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
           os.makedirs(run_dir, exist_ok=True)

           # Copiar el sim.json base al directorio de ejecución
           src_sim = os.path.join(base_dir, "sim.json")
           dst_sim = os.path.join(run_dir, "sim.json")
           shutil.copyfile(src_sim, dst_sim)

           # Cargar el sim.json copiado y editar la movilidad en ESA copia
           f = open(dst_sim)
           lines = f.readlines()
           f.close()
           lines = "".join(lines)
           data = json.loads(lines)

           # Editar un valor: establecer la movilidad para la primera capa del dispositivo
           data['epitaxy']['segment1']['shape_dos']['mue_y'] = mu

           jstr = json.dumps(data, sort_keys=False, indent='\t')
           f = open(dst_sim, "w")
           f.write(jstr)
           f.close()

           # Cambiar al directorio de ejecución y ejecutar allí el solucionador
           os.chdir(run_dir)

           # Si su comando es "augment.nano" en su lugar, reemplace la cadena de abajo.
           os.system("oghma_core.exe")

           # Volver al directorio base para la siguiente ejecución
           os.chdir(base_dir)

Tras la ejecución, cada directorio contendrá las salidas correspondientes a ese valor de movilidad. En la siguiente sección ampliaremos este script para recopilar resultados clave de cada ejecución y agregarlos en un único archivo resumen.

Representar \(V_{oc}\) frente a la movilidad inversa

Una vez que haya ejecutado un lote de simulaciones en directorios separados, el siguiente paso suele ser extraer una figura de mérito clave de cada ejecución y visualizar la tendencia. Un ejemplo común es leer el voltaje de circuito abierto \(V_{oc}\) desde el archivo de salida JSON (sim_info.dat) y representarlo frente a la movilidad inversa \(1/\mu\).

El script siguiente recorre un conjunto de directorios de ejecución (por ejemplo mu_1e-05, mu_1e-06, ...) y para cada directorio:

  1. Carga sim_info.dat como JSON.
  2. Extrae Voc.
  3. Calcula \(1/\mu\) usando la movilidad asociada a ese directorio.
  4. Escribe un pequeño archivo resumen (voc_vs_inv_mobility.dat).
  5. Representa \(V_{oc}\) frente a \(1/\mu\).

       import json
       import os

       # Opcional: representación gráfica (requiere matplotlib)
       import matplotlib.pyplot as plt

       base_dir = os.getcwd()

       # Las movilidades deben coincidir con los directorios de ejecución generados anteriormente
       mobilities = [1e-5, 1e-6, 1e-7, 1e-8]

       inv_mu = []
       vocs = []

       for mu in mobilities:
           run_dir = os.path.join(base_dir, f"mu_{mu:.0e}")
           info_path = os.path.join(run_dir, "sim_info.dat")

           # Leer el archivo de salida JSON y extraer Voc
           f = open(info_path)
           lines = f.readlines()
           f.close()
           lines = "".join(lines)
           data = json.loads(lines)

           voc = data["Voc"]

           inv_mu.append(1.0 / mu)
           vocs.append(voc)

       # Escribir una pequeña tabla resumen en disco
       out = open("voc_vs_inv_mobility.dat", "w")
       out.write("# inv_mobility(1/mu)    Voc(V)\n")
       for x, y in zip(inv_mu, vocs):
           out.write(f"{x:.6e}    {y}\n")
       out.close()

       # Representar Voc frente a la movilidad inversa
       plt.plot(inv_mu, vocs, "o-")
       plt.xlabel("Movilidad inversa (1/μ)")
       plt.ylabel("Voltaje de circuito abierto Voc (V)")
       plt.title("Voc frente a movilidad inversa")
       plt.grid(True)
       plt.tight_layout()
       plt.show()

📺 Vídeo relacionado

El vídeo siguiente demuestra cómo OghmaNano puede controlarse mediante scripting en Python.

Nota: La API y la interfaz interna de scripting mostradas en el vídeo ahora están obsoletas y ya no se distribuyen, ya que resultaron difíciles de mantener. El flujo de trabajo actual y recomendado consiste en utilizar un script externo de Python para editar directamente los archivos JSON de simulación y luego invocar oghma_core.exe. Este enfoque es más simple, más robusto y más fácil de mantener. Aun así, el vídeo puede seguir siendo útil para comprender el flujo de trabajo general y los casos de uso típicos, pero para el método actualizado siga los pasos descritos arriba.

Scripting en Python de una simulación de célula solar de perovskita en OghmaNano