<jupyter_start><jupyter_text>window.dataLayer = window.dataLayer || [];  function gtag(){dataLayer.push(arguments);}  gtag('js', new Date());  gtag('config', 'UA-59152712-8'); IDMaxwellNRPy: An Einstein Toolkit Initial Data Thorn for Maxwell's equations Author: <NAME> improvements courtesy <NAME>[comment]:  (Abstract: TODO)[comment]:  (Notebook Status and Validation Notes: TODO) NRPy+ Source Code for this module: [Maxwell/MaxwellCartesian_ID.py](../edit/Maxwell/MaxwellCartesian_ID.py) [\[tutorial\]](Tutorial-MaxwellCartesian.ipynb) Constructs these Maxwell initial data as SymPy expressions. Introduction:In this part of the tutorial, we will construct an Einstein Toolkit (ETK) thorn (module) that will set up *initial data* for Maxwell's equations. In the [Tutorial-MaxwellCartesian](Tutorial-MaxwellCartesian.ipynb), tutorial notebook we used NRPy+ to contruct the SymPy expressions for plane-wave initial data. We will construct this thorn in two steps.1. Call on NRPy+ to convert the SymPy expressions for the initial data into one C-code kernel.2. Write the C code and linkages to the Einstein Toolkit infrastructure (i.e., the .ccl files) to complete this Einstein Toolkit module.  Table of Contents$$\label{toc}$$This notebook is organized as follows1. [Step 1](initializenrpy): Call on NRPy+ to convert the SymPy expression for the Maxwell's equations initial data into a C-code kernel1. [Step 2](einstein): Interfacing with the Einstein Toolkit    1. [Step 2.a](einstein_c): Constructing the Einstein Toolkit C-code calling functions that include the C code kernels    1. [Step 2.b](einstein_ccl): CCL files - Define how this module interacts and interfaces with the larger Einstein Toolkit infrastructure    1. [Step 2.c](einstein_list): Add the C code to the Einstein Toolkit compilation list1. [Step 3](latex_pdf_output): Output this notebook to $\LaTeX$-formatted PDF  Step 1: Call on NRPy+ to convert the SymPy expression for the Maxwell's equations initial data into a C-code kernel \[Back to [top](toc)\]$$\label{initializenrpy}$$After importing the core modules, since we are writing an ETK thorn, we'll need to set `"grid::GridFuncMemAccess"` to `"ETK"`. SymPy expressions for plane wave initial data are written inside [Maxwell/MaxwellCartesian_ID.py](../edit/Maxwell/MaxwellCartesian_ID.py), and we simply import them for use here.<jupyter_code># Step 1: Call on NRPy+ to convert the SymPy expression 
#         for the Maxwell's equations initial data into a C-code kernel

# Step 1a: Import needed NRPy+ core modules:
import NRPy_param_funcs as par
import indexedexp as ixp
import grid as gri
import finite_difference as fin
from outputC import *
import loop


# Step 1b: This is an Einstein Toolkit (ETK) thorn. Here we
#          tell NRPy+ that gridfunction memory access will 
#          therefore be in the "ETK" style.
par.set_parval_from_str("grid::GridFuncMemAccess","ETK")
#Set the spatial dimension parameter to 3.
par.set_parval_from_str("grid::DIM", 3)
DIM = par.parval_from_str("grid::DIM")

import Maxwell.MaxwellCartesian_Evol as mwrhs # This declare the parameter System_to_use needed for MaxwellCartesian_ID
# Step 1c: Call the MaxwellCartesian_ID() function from within the
#          Maxwell/MaxwellCartesian_ID.py.py module.
import Maxwell.MaxwellCartesian_ID as mwid
# Step 3: Set up the plane wave initial data. This sets uu_ID and vv_ID.
mwid.MaxwellCartesian_ID()

# Step 4: Register gridfunctions so they can be written to by NRPy.
# System I:
AID = ixp.register_gridfunctions_for_single_rank1("EVOL","AID")
EID = ixp.register_gridfunctions_for_single_rank1("EVOL","EID")
psiI = gri.register_gridfunctions("EVOL","psiI")

# Step 5: Set the uu and vv gridfunctions to the uu_ID & vv_ID variables 
#         defined by InitialData_PlaneWave().
for i in range(DIM):
    AID[i] = mwid.AidD[i]
    EID[i] = mwid.EidD[i]
psiI = mwid.psi_ID

# Step 4: Register gridfunctions so they can be written to by NRPy.
# System II:
AIID = ixp.register_gridfunctions_for_single_rank1("EVOL","AIID")
EIID = ixp.register_gridfunctions_for_single_rank1("EVOL","EIID")
psiII = gri.register_gridfunctions("EVOL","psiII")
Gamma = gri.register_gridfunctions("EVOL","Gamma")

# Step 5: Set the uu and vv gridfunctions to the uu_ID & vv_ID variables 
#         defined by InitialData_PlaneWave().
for i in range(DIM):
    AIID[i] = mwid.AidD[i]
    EIID[i] = mwid.EidD[i]
psiII = mwid.psi_ID
Gamma = mwid.Gamma_ID

# Step 6: Create the C code output kernel.
Maxwell_ID_to_print = [\
                        lhrh(lhs=gri.gfaccess("out_gfs","AID0"),rhs=AID[0]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","AID1"),rhs=AID[1]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","AID2"),rhs=AID[2]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","EID0"),rhs=EID[0]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","EID1"),rhs=EID[1]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","EID2"),rhs=EID[2]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","psiI"),rhs=psiI),\
                        lhrh(lhs=gri.gfaccess("out_gfs","AIID0"),rhs=AIID[0]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","AIID1"),rhs=AIID[1]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","AIID2"),rhs=AIID[2]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","EIID0"),rhs=EIID[0]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","EIID1"),rhs=EIID[1]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","EIID2"),rhs=EIID[2]),\
                        lhrh(lhs=gri.gfaccess("out_gfs","psiII"),rhs=psiII),\
                        lhrh(lhs=gri.gfaccess("out_gfs","Gamma"),rhs=Gamma),]
Maxwell_ID_CcodeKernel = fin.FD_outputC("returnstring",Maxwell_ID_to_print)

Maxwell_ID_looped = loop.loop(["i2","i1","i0"],["0","0","0"],["cctk_lsh[2]","cctk_lsh[1]","cctk_lsh[0]"],\
                               ["1","1","1"],["#pragma omp parallel for","",""],"",\
                               Maxwell_ID_CcodeKernel.replace("time","cctk_time"))

# Step 7: Create directories for the thorn if they don't exist.
!mkdir MaxwellID     2>/dev/null # 2>/dev/null: Don't throw an error if the directory already exists.
!mkdir MaxwellID/src 2>/dev/null # 2>/dev/null: Don't throw an error if the directory already exists.

# Step 8: Write the C code kernel to file.
with open("MaxwellID/src/Maxwell_ID.h", "w") as file:
    file.write(str(Maxwell_ID_looped))<jupyter_output><empty_output><jupyter_text>Step 2: Interfacing with the Einstein Toolkit \[Back to [top](toc)\]$$\label{einstein}$$  Step 2.a: Constructing the Einstein Toolkit C-code calling functions that include the C code kernels \[Back to [top](toc)\]$$\label{einstein_c}$$We will write another C file with the functions we need here.<jupyter_code>%%writefile MaxwellID/src/InitialData.c
#include <math.h>
#include <stdio.h>

#include "cctk.h"
#include "cctk_Parameters.h"
#include "cctk_Arguments.h"

void Maxwell_InitialData(CCTK_ARGUMENTS)
{
  DECLARE_CCTK_ARGUMENTS
  DECLARE_CCTK_PARAMETERS
  
  const CCTK_REAL *xGF = x;
  const CCTK_REAL *yGF = y;
  const CCTK_REAL *zGF = z;
  const CCTK_REAL *gammaDD00GF = gxx;
  const CCTK_REAL *gammaDD01GF = gxy;
  const CCTK_REAL *gammaDD02GF = gxz;
  const CCTK_REAL *gammaDD11GF = gyy;
  const CCTK_REAL *gammaDD12GF = gyz;
  const CCTK_REAL *gammaDD22GF = gzz;
#include "Maxwell_ID.h"
}<jupyter_output>Writing MaxwellID/src/InitialData.c<jupyter_text>Step 2.b: CCL files - Define how this module interacts and interfaces with the larger Einstein Toolkit infrastructure \[Back to [top](toc)\]$$\label{einstein_ccl}$$Writing a module ("thorn") within the Einstein Toolkit requires that three "ccl" files be constructed, all in the root directory of the thorn:1. `interface.ccl`: defines the gridfunction groups needed, and provides keywords denoting what this thorn provides and what it should inherit from other thorns. Specifically, this file governs the interaction between this thorn and others; more information can be found in the [official Einstein Toolkit documentation](http://cactuscode.org/documentation/referencemanual/ReferenceManualch8.htmlx12-260000C2.2). With "implements", we give our thorn its unique name. By "inheriting" other thorns, we tell the Toolkit that we will rely on variables that exist and are declared "public" within those functions.<jupyter_code>%%writefile MaxwellID/interface.ccl
implements: MaxwellID
inherits: admbase MaxwellEvol grid<jupyter_output>Writing MaxwellID/interface.ccl<jupyter_text>2. `param.ccl`: specifies free parameters within the thorn, enabling them to be set at runtime. It is required to provide allowed ranges and default values for each parameter. More information on this file's syntax can be found in the [official Einstein Toolkit documentation](http://cactuscode.org/documentation/referencemanual/ReferenceManualch8.htmlx12-265000C2.3).<jupyter_code>%%writefile MaxwellID/param.ccl
shares: grid

USES KEYWORD type

restricted:
CCTK_KEYWORD initial_data "Type of initial data"
{
  "toroid"      :: "Toroidal Dipole field"
} "toroid"

restricted:
CCTK_REAL amp "The amplitude of the initial wave packet"
{
 0.0:* :: "Should be positive"
} 1.0

restricted:
CCTK_REAL lam "A parameter describing the size of the wave package"
{
 0.0:* :: "Should be positive"
} 1.0<jupyter_output>Writing MaxwellID/param.ccl<jupyter_text>3. `schedule.ccl`: allocates storage for gridfunctions, defines how the thorn's functions should be scheduled in a broader simulation, and specifies the regions of memory written to or read from gridfunctions. `schedule.ccl`'s official documentation may be found [here](http://cactuscode.org/documentation/referencemanual/ReferenceManualch8.htmlx12-268000C2.4). We specify here the standardized ETK "scheduling bins" in which we want each of our thorn's functions to run.<jupyter_code>%%writefile MaxwellID/schedule.ccl

schedule Maxwell_InitialData at CCTK_INITIAL as Maxwell_InitialData
{
  STORAGE:       MaxwellEvol::system_I[3]
  STORAGE:       MaxwellEvol::system_II[3]
  LANG:          C
  READS: admbase::gxx(Everywhere)
  READS: admbase::gxy(Everywhere)
  READS: admbase::gxz(Everywhere)
  READS: admbase::gyy(Everywhere)
  READS: admbase::gyz(Everywhere)
  READS: admbase::gzz(Everywhere)
  READS: grid::x(Everywhere)
  READS: grid::y(Everywhere)
  READS: grid::y(Everywhere)
  WRITES: AI0GF(Everywhere)
  WRITES: AI1GF(Everywhere)
  WRITES: AI2GF(Everywhere)
  WRITES: EI0GF(Everywhere)
  WRITES: EI1GF(Everywhere)
  WRITES: EI2GF(Everywhere)
  WRITES: psiIGF(Everywhere)
  WRITES: AII0GF(Everywhere)
  WRITES: AII1GF(Everywhere)
  WRITES: AII2GF(Everywhere)
  WRITES: EII0GF(Everywhere)
  WRITES: EII1GF(Everywhere)
  WRITES: EII2GF(Everywhere)
  WRITES: psiIIGF(Everywhere)
  WRITES: GammaGF(Everywhere)
} "Initial data for Maxwell's equations"<jupyter_output>Writing MaxwellID/schedule.ccl<jupyter_text>Step 2.c: Add the C code to the Einstein Toolkit compilation list \[Back to [top](toc)\]$$\label{einstein_list}$$We will also need `make.code.defn`, which indicates the list of files that need to be compiled. This thorn only has the one C file to compile.<jupyter_code>%%writefile MaxwellID/src/make.code.defn
SRCS = InitialData.c<jupyter_output>Writing MaxwellID/src/make.code.defn<jupyter_text>Step 3: Output this notebook to $\LaTeX$-formatted PDF file \[Back to [top](toc)\]$$\label{latex_pdf_output}$$The following code cell converts this Jupyter notebook into a proper, clickable $\LaTeX$-formatted PDF file. After the cell is successfully run, the generated PDF may be found in the root NRPy+ tutorial directory, with filename[Tutorial-ETK_thorn-IDMaxwellNRPy.pdf](Tutorial-ETK_thorn-IDMaxwellNRPy.pdf) (Note that clicking on this link may not work; you may need to open the PDF file through another means.)<jupyter_code>!jupyter nbconvert --to latex --template latex_nrpy_style.tplx --log-level='WARN' Tutorial-ETK_thorn-IDMaxwellNRPy.ipynb
!pdflatex -interaction=batchmode Tutorial-ETK_thorn-IDMaxwellNRPy.tex
!pdflatex -interaction=batchmode Tutorial-ETK_thorn-IDMaxwellNRPy.tex
!pdflatex -interaction=batchmode Tutorial-ETK_thorn-IDMaxwellNRPy.tex
!rm -f Tut*.out Tut*.aux Tut*.log<jupyter_output>[NbConvertApp] Converting notebook Tutorial-ETK_thorn-IDMaxwellNRPy.ipynb to latex
[pandoc warning] Duplicate link reference `[comment]' "source" (line 17, column 1)
[NbConvertApp] Writing 51239 bytes to Tutorial-ETK_thorn-IDMaxwellNRPy.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
{'fraction_non_alphanumeric': 0.10880508015178503, 'fraction_numerical': 0.01788894912104081, 'mean_word_length': 4.661551950898729, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '296206', 'license': 'BSD-2-Clause', 'n_tokens_mistral': 4599, 'n_tokens_neox': 4291, 'n_words': 1223, 'path': 'Tutorial-ETK_thorn-IDMaxwellNRPy.ipynb', 'repo_name': 'leowerneck/NRPyIGM', 'size': '12937'}