La simulación sencilla que se quiere lograr es simplemente dibujar una figura geométrica de una Punta en un plano X, Y, dicho plano X, Y representará el área de la malla en la que se estará trabajando. Imagine que se quiere dibujar una punta en el centro del plano, para proceder con dicha geometría se siguen los pasos sugeridos en el post anterior.
A continuación se muestra una geometría de “Punta” hecha con C++ y Meep
Considere el siguiente diagrama:
Primero que nada se inicializa la función MPI, esto es necesario aunque no se tenga contemplado hacer cálculos en paralelo.
punta.cpp
meep::initialize mpi(argc, argv); // Do this even for non-MPI Meep
Después, se definen algunas variables de resolución y se define que que se utilizará un PML para el área de frontera de la malla. En esta simulación no es necesario hacer esto pero de todas formas se definirá ya que en la mayoría de las simulaciones se necesitará una condición de frontera que absorba las ondas electromagnéticas
punta.cpp
double resolution = 20; // pixels per distance const double pml_thickness = 1.0; const double x = 40 + pml_thickness; const double y = 20 + pml_thickness;
Después, se crea el Volumen que contiene el tamaño de la malla y la resolución y se especifica que el origen de la malla será exactamente en el centro, esto se tiene que definir de esta forma ya que en C++ el origen por default de la malla se encuentra ubicado en a partir de la parte positiva del plano, es decir, la coordenada 0,0 estará en la esquina izquierda inferior.
punta.cpp
grid_volume grid_vol = vol2d(x, y, resolution); // 40x20 2d cell grid_vol.center_origin(); // set the origin as the center of cell
Después, se define la estructura en donde se agrega una referencia al Volumen o malla que se ha creado, también se agrega una referencia con la función que define la geometría que se estará dibujando y por último se le agrega el PML que se definió, ésto con la finalidad de definir condiciones de frontera con un material de absorción perfecto aunque esto no es necesario en esta simulación se define por cuestiones ilustrativas ya que la mayoría de las simulaciones contendrán algún tipo de excitación en donde se requerirá contar con un material de absorción en los limites del volumen que nos de la ilusión de continuidad infinita en el campo electromagnético.
punta.cpp
structure struct_punta(grid_vol, PuntaObject, pml(pml_thickness)); // structure punta
Después, se define un Field que esta vinculado con la estructura y se agrega una instrucción de optimización, cabe mencionar que esta instrucción de optimización no está dada por default en Meep C++ contrariamente a lo que ocurre con Scheme.
punta.cpp
fields field_punta(&struct_punta); field_punta.use_real_fields(); // this is for optimization purposes
Por último, se define el nombre del archivo en estándar HDF5 a generar, es decir, el archivo en donde se escribirán todos los datos de la simulación en el estándar H5, y se finaliza indicándole a Meep que escriba todos los datos de la simulación en dicho archivo por medio del objeto Field.
punta.cpp
h5file *h5_file = field_punta.open_h5file("punta", h5file::WRITE, "", true); field_punta.output_hdf5(Dielectric, grid_vol.surroundings(), h5_file, false, false, "");
Una de las partes importantes de un programa Meep es la función en donde se definen las geometrías, en este caso la función se ve de la siguiente manera:
punta.cpp
double PuntaObject(const vec &p) { if ((p.x() >= 0 && p.x() <= 4) && (p.y() >= -4 && p.y() <= 8)) { if (p.x() == 2 && p.y() == 4) return 0.0; // define area for end point if (p.y() >= 4) { if (p.x() <= (p.y()/2)-2) return 0.0; if (p.x() >= (p.y()/2)-(p.y()-6)) return 0.0; } return 12.0; } return 0.0; }
La forma en que la función de la geometría trabaja es la siguiente: Meep hace un barrido internamente punto por punto en donde evalúa si dicho punto se encuentra en la ecuación que se define dentro de esta función, si el punto pertenece al rango de puntos dentro de la función Meep asignará un épsilon de material definido dentro de la condicional, de otra forma Meep asignará el épsilon de material que se le especifique al final de la función, con esta metodología se puede dibujar prácticamente cualquier cosa.
A continuación se enlista el código de la geometría completo:
punta.cpp
/* * _punta.cpp * * In order to run a simulation using the MEEP C++ interface, the following steps are necessary: * initialize mpi(argc, argv); // do this even for non-MPI Meep * create a meep::volume * create a meep::structure using that volume * create a meep::fields object * add some kind of excitation. * time step the code. Of course, you'll have to create measurements and output whatever data * you are interested in as well. * * Created on: Jul 22, 2011 * Author: ubuntu */ #include #include using namespace meep; double PuntaObject(const vec &p) { if ((p.x() >= 0 && p.x() <= 4) && (p.y() >= -4 && p.y() <= 8)) { if (p.x() == 2 && p.y() == 4) return 0.0; // define area for end point if (p.y() >= 4) { if (p.x() <= (p.y()/2)-2) return 0.0; if (p.x() >= (p.y()/2)-(p.y()-6)) return 0.0; } return 12.0; } return 0.0; } int main(int argc, char **argv) { meep::initialize mpi(argc, argv); // Do this even for non-MPI Meep double resolution = 20; // pixels per distance const double pml_thickness = 1.0; const double x = 40 + pml_thickness; const double y = 20 + pml_thickness; grid_volume grid_vol = vol2d(x, y, resolution); // 40x20 2d cell grid_vol.center_origin(); // set the origin as the center of cell structure struct_punta(grid_vol, PuntaObject, pml(pml_thickness)); // structure punta fields field_punta(&struct_punta); field_punta.use_real_fields(); // this is for optimization purposes h5file *h5_file = field_punta.open_h5file("punta", h5file::WRITE, "", true); field_punta.output_hdf5(Dielectric, grid_vol.surroundings(), h5_file, false, false, ""); return 0; }
Para ejecutar la simulación anterior es necesario crear un shell script en donde se especifican algunos paquetes que ayudarán en la conversión de datos en formato HDF5 a formato de imagen así como también hará todo el compilado del código anterior para obtener los resultados deseados, para el caso de la punta y suponiendo que nuestro programa se llama _punta.cpp se crea el siguiente archivo bash:
make _punta.dac ./_punta.dac h5ls punta-000000.00.h5 h5topng -Zc dkbluered punta-000000.00.h5 rm punta-000000.00.h5 rm _punta.dac
El shell script anterior compila el programa C++ mediante la instrucción make y crea un archivo de ejecución con extensión “.dac” la cual se ejecuta en la siguiente instrucción, a continuación se utiliza un comando propio de el paquete h5utils desarrollado también por el MIT, el comando h5ls enlista el tamaño del dataset creado que vive en el archivo con extensión H5 y en formato HDF5 este enlistado es solamente con fines informativos, a continuación se ejecuta el comando h5topng el cual como describe su nombre hace una conversión de los datos en formato HDF5 a una imagen en formato PNG, y se finaliza removiendo archivos que ya no serán utilizados al final de la simulación ya que lo que nos interesa por ahora es la imagen.
Para concluir con la ejecución del programa Meep creado, se debe ejecutar el shell script que hara todo el trabajo de escribir todos esos comandos por nosotros con la siguiente instrucción, suponiendo que nuestro script se llame _punta.sh.
chmod +x _punta.sh sh _punta.sh
¡Listo!, la simulación nos arrojará el diagrama esperado que se anexa a continuación:
¡Enjoy!
Me gusta mucho que le has dado un giro a tu blog, publicando información bastante interesante sobre lo que estas haciendo actualmente en el doctorado, me gustaria aprender mas, sobre informatica/fisica, espero y me expliques 🙂
felicidades!!
te amo!
No creas que yo se mucho de todo esto jejej pero si te explico 🙂
Te amo!
Hola,
todo muy bien, pero ¿me podrías poner un ejemplo de como se usan los flux y qué módulos se usan con qué parámetros??
gracias
un saludo