diff --git a/.ci_with_cmake.sh b/.ci_with_cmake.sh index 3381c4a380..71ea2204e2 100755 --- a/.ci_with_cmake.sh +++ b/.ci_with_cmake.sh @@ -17,12 +17,6 @@ ctest --output-on-failure --timeout 300 export LD_LIBRARY_PATH=/home/runner/local/lib:$LD_LIBRARY_PATH -# Test bout-config basic functionallity -cd ../examples/make-script -PATH=../../build/bin:$PATH bout-config --all -PATH=../../build/bin:$PATH make -./test --help -cd - # Test bout++Config.cmake cd ../examples/conduction cmake . -B build -DCMAKE_PREFIX_PATH=../../build @@ -32,13 +26,6 @@ cd - make install -j 2 rm -rf build -# Test installation with plain `make` -cd ../examples/make-script -rm test -PATH=../../installed/bin:$PATH bout-config --all -PATH=../../installed/bin:$PATH make -./test --help -cd - # Test installation with CMake cd ../examples/conduction cmake . -B build -DCMAKE_PREFIX_PATH=../../installed diff --git a/examples/2Dturbulence_multigrid/.gitignore b/examples/2Dturbulence_multigrid/.gitignore deleted file mode 100644 index 26b1c65f51..0000000000 --- a/examples/2Dturbulence_multigrid/.gitignore +++ /dev/null @@ -1 +0,0 @@ -esel \ No newline at end of file diff --git a/examples/2Dturbulence_multigrid/CMakeLists.txt b/examples/2Dturbulence_multigrid/CMakeLists.txt deleted file mode 100644 index 369d2bf5bc..0000000000 --- a/examples/2Dturbulence_multigrid/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(2Dturbulence_multigrid LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(esel SOURCES esel.cxx) diff --git a/examples/2Dturbulence_multigrid/README.md b/examples/2Dturbulence_multigrid/README.md deleted file mode 100644 index 5edc4076ea..0000000000 --- a/examples/2Dturbulence_multigrid/README.md +++ /dev/null @@ -1,7 +0,0 @@ -2D Turbulence using multigrid -============================= - -This examples demonstrates the use of the multigrid Laplacian inversion solver -for a 2D turbulence based on the physics model implemented in `ESEL` -(Interchange turbulence in the TCV scrape-off layer, Garcia et al, PPCF 2006, -DOI: [10.1088/0741-3335/48/1/L01](https://doi.org/10.1088/0741-3335/48/1/L01)) diff --git a/examples/2Dturbulence_multigrid/data/BOUT.inp b/examples/2Dturbulence_multigrid/data/BOUT.inp deleted file mode 100644 index d467f5fa91..0000000000 --- a/examples/2Dturbulence_multigrid/data/BOUT.inp +++ /dev/null @@ -1,77 +0,0 @@ -timestep = 10 # Timestep length of outputted data -nout = 10 # Number of outputted timesteps - -restart = false - -#nxpe = 4 - -MZ = 256 # Number of Z points -ZMIN = 0 -ZMAX = 15.91549431 # 15.915*2pi = 100. z is in fractions of 2pi -MYG = 0 # No need for Y communications - -[mesh] -nx = 260 # 512 points plus guard cells -ny = 1 - -Lx = 150 -dx = Lx/(nx-4) -#dx = 0.29296875 # Cell spacing = Lx/nx -dy = 1.0 - -[mesh:ddz] -first = c2 # c2 (default), c4, w2, w3 -#upwind = w3 # u1 (default), u4, w3 - -[laplace] -type = multigrid -multigridlevel = 3 -solvertype = 0 -rtol = 1e-07 - -global_flags = 0 -inner_boundary_flags = 0 # Dirichlet -outer_boundary_flags = 0 # Dirichlet - -[solver] -type = pvode -mxstep = 100000000 # max steps before result is deemed not to converge -#atol = 1e-12 # Absolute tolerance -#rtol = 1e-5 # Relative tolerance - -[esel] -test_laplacian = false -zeta = 0.00215 -D = 0.00197 -mu = 0.0388 -bracket = 2 # 0 = std, 1 = simple, 2 = arakawa - -[N] -scale = 1.0 -function = 15*sqrt(2*pi)*gauss(150*x,15) - -bndry_xin = dirichlet_o2(1.0) -bndry_xout = neumann_o2 - -[vort] -scale = 1e-12 -function = (sin(x*2*pi+11)+4*sin(2*x*2*pi+22)+9*sin(3*x*2*pi+33)+16*sin(4*x*2*pi+44)+25*sin(5*x*2*pi+55)+36*sin(6*x*2*pi+66)+49*sin(7*x*2*pi+77))*(sin(z+10)+4*sin(2*z+20)+9*sin(3*z+30)+16*sin(4*z+40)+25*sin(5*z+50)+36*sin(6*z+60)+49*sin(7*z+70)) - -bndry_xin = dirichlet_o2 -bndry_xout = dirichlet_o2 - -[B] # Magnetic field -scale = 1.0 -function = 1.0/(1.0 + 0.694 + (2.15e-3)*150*x) #1/(1+epsilon+zeta*x) - -[sigma_n] # Density sink -scale = 1.0 -function = 0.5*(1.29e-4)*(1.0 + sinh(150*x-50)/cosh(150*x-50)) - -[sigma_T] # Temperature sink -scale = 1.0 -function = 0.5*(3.75e-3)*(1.0 + sinh(150*x-50)/cosh(150*x-50)) - -[sigma_vort] # Vorticity sink -scale = 1.0 -function = 0.5*(1.29e-4)*(1.0 + sinh(150*x-50)/cosh(150*x-50)) diff --git a/examples/2Dturbulence_multigrid/esel.cxx b/examples/2Dturbulence_multigrid/esel.cxx deleted file mode 100644 index 810e1aa018..0000000000 --- a/examples/2Dturbulence_multigrid/esel.cxx +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include -#include -#include -#include - -class ESEL : public PhysicsModel { -private: - Field3D n, vort; // Evolving density, temp and vorticity - Field3D N; // ln(n) - Field3D phi; - Field2D B; // Magnetic field - BoutReal D, mu; // Diffusion coefficients - Field2D sigma_n, sigma_T, sigma_vort; // dissipation terms - BoutReal zeta; // rho/R0 - BRACKET_METHOD bm; // Bracket method for advection terms - std::unique_ptr phiSolver{nullptr}; // Laplacian solver for vort -> phi - bool test_laplacian; // If true, compute the error on the Laplacian inversion and abort - Field3D vort_error; - -protected: - int init(bool UNUSED(restart)) { - - auto& options = Options::root()["esel"]; - - zeta = options["zeta"].withDefault(2.15e-3); - D = options["D"].withDefault(1.97e-3); - mu = options["mu"].withDefault(3.88e-2); - test_laplacian = options["test_laplacian"].withDefault(false); - - // Set sources and sinks from input profile - initial_profile("sigma_n", sigma_n); - initial_profile("sigma_T", sigma_T); - initial_profile("sigma_vort", sigma_vort); - initial_profile("B", B); - - SAVE_ONCE(sigma_n); - - // Poisson brackets: b_hat x Grad(f) dot Grad(g) / B = [f, g] - // Method to use: BRACKET_ARAKAWA, BRACKET_STD or BRACKET_SIMPLE - // Choose method to use for Poisson bracket advection terms - - switch (options["bracket"].withDefault(2)) { - case 0: { - bm = BRACKET_STD; - output << "\tBrackets: default differencing\n"; - break; - } - case 1: { - bm = BRACKET_SIMPLE; - output << "\tBrackets: simplified operator\n"; - break; - } - case 2: { - bm = BRACKET_ARAKAWA; - output << "\tBrackets: Arakawa scheme\n"; - break; - } - case 3: { - bm = BRACKET_CTU; - output << "\tBrackets: Corner Transport Upwind method\n"; - break; - } - default: - output << "ERROR: Invalid choice of bracket method. Must be 0-3\n"; - return 1; - } - - Coordinates* coord = mesh->getCoordinates(); - - // generate coordinate system - coord->Bxy = 1; - - coord->g11 = 1.0; - coord->g22 = 1.0; - coord->g33 = 1.0; - coord->g12 = 0.0; - coord->g13 = 0.0; - coord->g23 = 0.0; - - coord->g_11 = 1.0; - coord->g_22 = 1.0; - coord->g_33 = 1.0; - coord->g_12 = 0.0; - coord->g_13 = 0.0; - coord->g_23 = 0.0; - - coord->geometry(); - - SOLVE_FOR(N, vort); - SAVE_REPEAT(phi); - if (test_laplacian) { - SAVE_REPEAT(vort_error); - } - phiSolver = Laplacian::create(); - phi = 0.0; // Starting phi - - return 0; - } - - Field3D C(const Field3D& f) { return zeta * DDZ(f); } - - int rhs(BoutReal UNUSED(time)) { - mesh->communicate(N, vort); - - phiSolver->setCoefC2(N); - phi = phiSolver->solve(vort, phi); - - mesh->communicate(phi); - - if (test_laplacian) { - - Field3D vort2 = D2DX2(phi) + D2DZ2(phi) + DDX(N) * DDX(phi) + DDZ(N) * DDZ(phi); - vort_error = (vort - vort2); - - dump.write(); - - MPI_Barrier(BoutComm::get()); - - return 1; - } - - // Continuity equation: - ddt(N) = bracket(phi, N, bm) + C(phi) - C(N) + D * Delp2(N) - sigma_n; - - // Vorticity equation: - ddt(vort) = bracket(phi, vort, bm) - C(exp(N)) + mu * Delp2(vort) - sigma_vort * vort; - - // n.b bracket terms do not have minus sign before them because - // B is pointing in -ve y direction in BOUT coordinates. - //// This may be wrong, but it is probably consistently wrong - - return 0; - } -}; - -BOUTMAIN(ESEL); diff --git a/examples/2Dturbulence_multigrid/redistribute_restarts.py b/examples/2Dturbulence_multigrid/redistribute_restarts.py deleted file mode 100755 index 4e2f068401..0000000000 --- a/examples/2Dturbulence_multigrid/redistribute_restarts.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -from boutdata import restart -from sys import argv, exit - -npes = int(argv[1]) - -try: - restarts_directory = argv[2] -except IndexError: - restarts_directory = "restarts_256x256" - -restart.redistribute(npes, path=restarts_directory, output="data", myg=0) - -exit(0) diff --git a/examples/6field-simple/bout_hopper_debug.cmd b/examples/6field-simple/bout_hopper_debug.cmd deleted file mode 100644 index 5591632552..0000000000 --- a/examples/6field-simple/bout_hopper_debug.cmd +++ /dev/null @@ -1,12 +0,0 @@ -#PBS -q debug -#PBS -l mppwidth=128 -#PBS -l mppnppn=24 -#PBS -l walltime=0:10:00 -#PBS -N my_job -#PBS -e my_job.$PBS_JOBID.err -#PBS -e my_job.$PBS_JOBID.out -#PBS -V - -cd $PBS_O_WORKDIR -aprun -n 128 -N 24 ./elm_6f - diff --git a/examples/6field-simple/data/BOUT.inp b/examples/6field-simple/data/BOUT.inp index 2c435ea533..6de7692b71 100644 --- a/examples/6field-simple/data/BOUT.inp +++ b/examples/6field-simple/data/BOUT.inp @@ -18,10 +18,6 @@ MXG = 2 MYG = 2 grid = "cbm18_dens8.grid_nx68ny64.nc" -restart_format = "nc" # Restart file format - -[mesh] -staggergrids = false # Use staggered grids (EXPERIMENTAL) [mesh:paralleltransform] type = shifted # Use shifted metric method diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 022b16e248..849f10e85f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,13 +1,9 @@ -add_subdirectory(2Dturbulence_multigrid) add_subdirectory(6field-simple) add_subdirectory(IMEX/advection-diffusion) add_subdirectory(IMEX/advection-reaction) add_subdirectory(IMEX/diffusion-nl) add_subdirectory(IMEX/drift-wave) add_subdirectory(IMEX/drift-wave-constraint) -add_subdirectory(advdiff) -add_subdirectory(advdiff2) -add_subdirectory(backtrace) add_subdirectory(blob2d) add_subdirectory(blob2d-outerloop) add_subdirectory(blob2d-laplacexz) @@ -22,32 +18,22 @@ add_subdirectory(dalf3) add_subdirectory(eigen-box) add_subdirectory(elm-pb) add_subdirectory(elm-pb-outerloop) -add_subdirectory(em-drift) add_subdirectory(fci-wave) -add_subdirectory(fci-wave-logn) add_subdirectory(finite-volume/diffusion) add_subdirectory(finite-volume/fluid) add_subdirectory(finite-volume/test) add_subdirectory(gas-compress) -add_subdirectory(gravity_reduced) add_subdirectory(gyro-gem) add_subdirectory(hasegawa-wakatani) add_subdirectory(hasegawa-wakatani-3d) add_subdirectory(invertable_operator) -add_subdirectory(jorek-compare) -add_subdirectory(lapd-drift) add_subdirectory(laplacexy/alfven-wave) add_subdirectory(laplacexy/laplace_perp) add_subdirectory(laplacexy/simple) add_subdirectory(laplacexy/simple-hypre) -add_subdirectory(monitor) add_subdirectory(monitor-newapi) add_subdirectory(orszag-tang) add_subdirectory(preconditioning/wave) -add_subdirectory(reconnect-2field) -add_subdirectory(shear-alfven-wave) add_subdirectory(staggered_grid) add_subdirectory(subsampling) -add_subdirectory(tokamak-2fluid) -add_subdirectory(uedge-benchmark) add_subdirectory(wave-slab) diff --git a/examples/advdiff/.gitignore b/examples/advdiff/.gitignore deleted file mode 100644 index e04e9b916a..0000000000 --- a/examples/advdiff/.gitignore +++ /dev/null @@ -1 +0,0 @@ -advdiff \ No newline at end of file diff --git a/examples/advdiff/CMakeLists.txt b/examples/advdiff/CMakeLists.txt deleted file mode 100644 index 531cfb743a..0000000000 --- a/examples/advdiff/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(advdiff LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(advdiff - SOURCES advdiff.cxx - EXTRA_FILES slab.grd.nc) diff --git a/examples/advdiff/README b/examples/advdiff/README deleted file mode 100644 index 3a04e7da8d..0000000000 --- a/examples/advdiff/README +++ /dev/null @@ -1,16 +0,0 @@ -1) Generate grid in IDL: -> idl -IDL> Generate_Grid, /save ;;-you can set dimensions here, otherwise using the default 30x32 -IDL> exit - -2) Compile the code -> source set_bout_top.sh -> gmake - -3) Run the code -> mpirun -np 2 ./advdiff - -4) View the results -> idl -IDL> @runidl -IDL> exit diff --git a/examples/advdiff/advdiff.cxx b/examples/advdiff/advdiff.cxx deleted file mode 100644 index 2e7d3748fc..0000000000 --- a/examples/advdiff/advdiff.cxx +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************* - * Advection-Diffusion Example - * - * MVU 19-july-2011 - *******************************************************************/ - -#include -#include - -class AdvDiff : public PhysicsModel { -private: - // Evolving variables - Field3D V; - -protected: - int init(bool restarting) { - // 2D initial profiles - Field2D V0; - - // Read initial conditions - - Coordinates* coord = mesh->getCoordinates(); - - mesh->get(V0, "V0"); - mesh->get(coord->dx, "dx"); - mesh->get(coord->dy, "dy"); - - // read options - - // Set evolving variables - SOLVE_FOR(V); - - if (!restarting) { - // Set variables to these values (+ the initial perturbation) - // NOTE: This must be after the calls to bout_solve - V += V0; - } - return 0; - } - - int rhs(BoutReal UNUSED(t)) { - // Run communications - mesh->communicate(V); - - //ddt(V) = D2DX2(V) + 0.5*DDX(V) + D2DY2(V); - ddt(V) = DDX(V); - - return 0; - } -}; - -BOUTMAIN(AdvDiff); diff --git a/examples/advdiff/data/BOUT.inp b/examples/advdiff/data/BOUT.inp deleted file mode 100644 index 0ae41282b0..0000000000 --- a/examples/advdiff/data/BOUT.inp +++ /dev/null @@ -1,60 +0,0 @@ -# settings file for BOUT++ -# - -################################################## -# settings used by the core code - -nout = 10 # number of time-steps -timestep = 0.01 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 16 # number of points in z direction -zperiod = 10 - -MXG = 2 -MYG = 2 - -grid = "./slab.grd.nc" - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 -second = C2 -upwind = U1 - -[mesh:ddy] - -first = C4 -second = C2 -upwind = U1 - -[mesh:ddz] - -first = C2 -second = C2 -upwind = U1 - -################################################## -# Solver settings - -[solver] - -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -bndry_all = neumann # Zero-gradient on all boundaries - -[V] -scale = 1 # initial perturbation for V -function = exp(-((x-0.5)/0.2)^2) * exp(-((y/(2*pi)-0.5)/0.2)^2) diff --git a/examples/advdiff/generate_grid.pro b/examples/advdiff/generate_grid.pro deleted file mode 100644 index 55cbc9b848..0000000000 --- a/examples/advdiff/generate_grid.pro +++ /dev/null @@ -1,167 +0,0 @@ -; Create an input file for 2D advection-diffusion equation example -;=================================================================; - -@pdb2idl - -PRO generate_grid, $ -nx=nx, ny=ny, rxy=rxy, zxy=zxy, metric=metric, core=core,$ -file=file, save=save, plot=plot, debug=debug - -; -; -; - - IF NOT KEYWORD_SET(nx) THEN nx = 30 - IF NOT KEYWORD_SET(ny) THEN ny = 32 - IF NOT KEYWORD_SET(file) THEN file="./slab.grd.nc" - - - - - ;;-domain boundaries - Rt0=0.5 ;;-reference location [m] - Rmin=Rt0-0.5 ;;-left boundary [m] - Rmax=Rt0+0.5 ;;-right boundary [m] - Zmin=0.0 ;;-bottom boundary [m] - Zmax=1.0 ;;-top boundary [m] - - dR=(Rmax-Rmin)/(nx-1) - dZ=(Zmax-Zmin)/(ny-1) - - hthe0=(Zmax-Zmin)/(2*!PI) - hthe = FLTARR(nx, ny) + hthe0 - - - - ;;-actual coordinates are needed only for plotting - Rxy=fltarr(nx,ny) - Zxy=fltarr(nx,ny) - - dx=fltarr(nx,ny) - dy=fltarr(nx,ny) - - - - - - ;;-set geometry and magnetic field on the grid - for ix=0,nx-1 do begin - for jy=0,ny-1 do begin - - Rxy[ix,jy]=Rmin+dR*ix - Zxy[ix,jy]=Zmin+dZ*jy - - dx[ix,jy] = dR - dy[ix,jy] = dZ - ;;dy[ix,jy] = 2.0*!PI/ny - - endfor - endfor - - - - ;;-set background 2D profiles - V0 = FLTARR(nx, ny) - - - - Ln=1e10 ;;-density decay length [m] - - for ix=0,nx-1 do begin - for jy=0,ny-1 do begin - - V0[ix,jy] = 1e0 - - endfor - endfor - - - ;;-set elements of metric tensor - g11=fltarr(nx,ny) - g22=fltarr(nx,ny) - g33=fltarr(nx,ny) - g12=fltarr(nx,ny) - g13=fltarr(nx,ny) - g23=fltarr(nx,ny) - - g11[*,*] = dR^2 - g22[*,*] = dZ^2 - g33[*,*] = 1.0 - g12[*,*] = 0.0 - g13[*,*] = 0.0 - g23[*,*] = 0.0 - - - if keyword_set(CORE) then begin - ;; entire domain inside 'core' - periodic - ixseps1 = nx - ixseps2 = nx - jyseps1_1 = -1 - jyseps2_2 = ny-1 - endif else begin - ;; Topology: Set all points outside separatrix - ;; so NOT periodic in Y - ixseps1 = 0 - ixseps2 = 0 - jyseps1_1 = -1 - jyseps2_2 = ny-1 - endelse - jyseps1_2=ny/2 - jyseps2_1=ny/2 - - - if keyword_set(SAVE) then begin - - print, "Writing data to ", file - - f = file_open(file, /create) - - status = file_write(f, "nx", nx) - status = file_write(f, "ny", ny) - - - status = file_write(f, "Rxy", Rxy) - status = file_write(f, "Zxy", Zxy) - - - ;;-supply metric tensor if not calculating internally - status = file_write(f, "g11", g11) - status = file_write(f, "g22", g22) - status = file_write(f, "g33", g33) - status = file_write(f, "g12", g12) - status = file_write(f, "g13", g13) - status = file_write(f, "g23", g23) - - - ;;-flags for setting topology (may be needed) - status = file_write(f, "ixseps1", ixseps1) - status = file_write(f, "ixseps2", ixseps2) - status = file_write(f, "jyseps1_1", jyseps1_1) - status = file_write(f, "jyseps2_2", jyseps2_2) - status = file_write(f, "jyseps2_1", jyseps2_1) - status = file_write(f, "jyseps1_2", jyseps1_2) - - - ;;-initial profile - status = file_write(f, "V0", V0) - - - - ;;-some auxiliary quantities (may be needed) - status = file_write(f, "hthe", hthe) - status = file_write(f, "hthe0", hthe0) - - status = file_write(f, "dx", dx) - status = file_write(f, "dy", dy) - - - file_close, f - - endif - - -; -; -; -if keyword_set(DEBUG) then STOP -END diff --git a/examples/advdiff/idlsave.pro b/examples/advdiff/idlsave.pro deleted file mode 100644 index c35a6ad2d3..0000000000 --- a/examples/advdiff/idlsave.pro +++ /dev/null @@ -1,6 +0,0 @@ -; IDL Version 8.0 (linux x86_64 m64) -; Journal File for umansky1@smaug -; Working directory: /afs/fepcluster/home/umansky1/Projects/fledge/bppWork/examples/advect_simple -; Date: Tue Sep 27 18:41:04 2011 - -@runidl diff --git a/examples/advdiff/runidl.pro b/examples/advdiff/runidl.pro deleted file mode 100644 index 350762aa00..0000000000 --- a/examples/advdiff/runidl.pro +++ /dev/null @@ -1,15 +0,0 @@ -loadct,39 - -v=collect(path='./data', var='V') -g=file_import('./slab.grd.nc') -rxy=g.rxy -zxy=g.zxy - - - -nt=n_elements(v[0,0,0,*]) - -nlev=30 -level=1+findgen(nlev)/(nlev-1) - -for it=0,nt-1 do begin CONTOUR, reform(v[*,*,10,it]), rxy, zxy, lev=level, chars=3, /xst, /yst, /iso & wait,1.0 diff --git a/examples/advdiff/set_bout_top.sh b/examples/advdiff/set_bout_top.sh deleted file mode 100644 index 7feaf956c4..0000000000 --- a/examples/advdiff/set_bout_top.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -#export BOUT_TOP=$HOME/BOUT/bout++/ -export BOUT_TOP=/Users/hong/soft/BOUT/ -rm -f pdb2idl.so -ln -s $BOUT_TOP/../pdb2idl/pdb2idl.so diff --git a/examples/advdiff/slab.grd.nc b/examples/advdiff/slab.grd.nc deleted file mode 100644 index 01027d4f59..0000000000 Binary files a/examples/advdiff/slab.grd.nc and /dev/null differ diff --git a/examples/advdiff2/.gitignore b/examples/advdiff2/.gitignore deleted file mode 100644 index e04e9b916a..0000000000 --- a/examples/advdiff2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -advdiff \ No newline at end of file diff --git a/examples/advdiff2/CMakeLists.txt b/examples/advdiff2/CMakeLists.txt deleted file mode 100644 index e90a00d72f..0000000000 --- a/examples/advdiff2/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(advdiff2 LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(advdiff2 - SOURCES header.hxx - init.cxx - rhs.cxx - EXTRA_FILES slab.grd.nc) diff --git a/examples/advdiff2/README b/examples/advdiff2/README deleted file mode 100644 index 7dbba6b6cc..0000000000 --- a/examples/advdiff2/README +++ /dev/null @@ -1,19 +0,0 @@ -This version demonstrates splitting the source into multiple files. - - -1) Generate grid in IDL: -> idl -IDL> Generate_Grid, /save ;;-you can set dimensions here, otherwise using the default 30x32 -IDL> exit - -2) Compile the code -> source set_bout_top.sh -> gmake - -3) Run the code -> mpirun -np 2 ./advdiff - -4) View the results -> idl -IDL> @runidl -IDL> exit diff --git a/examples/advdiff2/data/BOUT.inp b/examples/advdiff2/data/BOUT.inp deleted file mode 100644 index 0ae41282b0..0000000000 --- a/examples/advdiff2/data/BOUT.inp +++ /dev/null @@ -1,60 +0,0 @@ -# settings file for BOUT++ -# - -################################################## -# settings used by the core code - -nout = 10 # number of time-steps -timestep = 0.01 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 16 # number of points in z direction -zperiod = 10 - -MXG = 2 -MYG = 2 - -grid = "./slab.grd.nc" - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 -second = C2 -upwind = U1 - -[mesh:ddy] - -first = C4 -second = C2 -upwind = U1 - -[mesh:ddz] - -first = C2 -second = C2 -upwind = U1 - -################################################## -# Solver settings - -[solver] - -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -bndry_all = neumann # Zero-gradient on all boundaries - -[V] -scale = 1 # initial perturbation for V -function = exp(-((x-0.5)/0.2)^2) * exp(-((y/(2*pi)-0.5)/0.2)^2) diff --git a/examples/advdiff2/generate_grid.pro b/examples/advdiff2/generate_grid.pro deleted file mode 100644 index 55cbc9b848..0000000000 --- a/examples/advdiff2/generate_grid.pro +++ /dev/null @@ -1,167 +0,0 @@ -; Create an input file for 2D advection-diffusion equation example -;=================================================================; - -@pdb2idl - -PRO generate_grid, $ -nx=nx, ny=ny, rxy=rxy, zxy=zxy, metric=metric, core=core,$ -file=file, save=save, plot=plot, debug=debug - -; -; -; - - IF NOT KEYWORD_SET(nx) THEN nx = 30 - IF NOT KEYWORD_SET(ny) THEN ny = 32 - IF NOT KEYWORD_SET(file) THEN file="./slab.grd.nc" - - - - - ;;-domain boundaries - Rt0=0.5 ;;-reference location [m] - Rmin=Rt0-0.5 ;;-left boundary [m] - Rmax=Rt0+0.5 ;;-right boundary [m] - Zmin=0.0 ;;-bottom boundary [m] - Zmax=1.0 ;;-top boundary [m] - - dR=(Rmax-Rmin)/(nx-1) - dZ=(Zmax-Zmin)/(ny-1) - - hthe0=(Zmax-Zmin)/(2*!PI) - hthe = FLTARR(nx, ny) + hthe0 - - - - ;;-actual coordinates are needed only for plotting - Rxy=fltarr(nx,ny) - Zxy=fltarr(nx,ny) - - dx=fltarr(nx,ny) - dy=fltarr(nx,ny) - - - - - - ;;-set geometry and magnetic field on the grid - for ix=0,nx-1 do begin - for jy=0,ny-1 do begin - - Rxy[ix,jy]=Rmin+dR*ix - Zxy[ix,jy]=Zmin+dZ*jy - - dx[ix,jy] = dR - dy[ix,jy] = dZ - ;;dy[ix,jy] = 2.0*!PI/ny - - endfor - endfor - - - - ;;-set background 2D profiles - V0 = FLTARR(nx, ny) - - - - Ln=1e10 ;;-density decay length [m] - - for ix=0,nx-1 do begin - for jy=0,ny-1 do begin - - V0[ix,jy] = 1e0 - - endfor - endfor - - - ;;-set elements of metric tensor - g11=fltarr(nx,ny) - g22=fltarr(nx,ny) - g33=fltarr(nx,ny) - g12=fltarr(nx,ny) - g13=fltarr(nx,ny) - g23=fltarr(nx,ny) - - g11[*,*] = dR^2 - g22[*,*] = dZ^2 - g33[*,*] = 1.0 - g12[*,*] = 0.0 - g13[*,*] = 0.0 - g23[*,*] = 0.0 - - - if keyword_set(CORE) then begin - ;; entire domain inside 'core' - periodic - ixseps1 = nx - ixseps2 = nx - jyseps1_1 = -1 - jyseps2_2 = ny-1 - endif else begin - ;; Topology: Set all points outside separatrix - ;; so NOT periodic in Y - ixseps1 = 0 - ixseps2 = 0 - jyseps1_1 = -1 - jyseps2_2 = ny-1 - endelse - jyseps1_2=ny/2 - jyseps2_1=ny/2 - - - if keyword_set(SAVE) then begin - - print, "Writing data to ", file - - f = file_open(file, /create) - - status = file_write(f, "nx", nx) - status = file_write(f, "ny", ny) - - - status = file_write(f, "Rxy", Rxy) - status = file_write(f, "Zxy", Zxy) - - - ;;-supply metric tensor if not calculating internally - status = file_write(f, "g11", g11) - status = file_write(f, "g22", g22) - status = file_write(f, "g33", g33) - status = file_write(f, "g12", g12) - status = file_write(f, "g13", g13) - status = file_write(f, "g23", g23) - - - ;;-flags for setting topology (may be needed) - status = file_write(f, "ixseps1", ixseps1) - status = file_write(f, "ixseps2", ixseps2) - status = file_write(f, "jyseps1_1", jyseps1_1) - status = file_write(f, "jyseps2_2", jyseps2_2) - status = file_write(f, "jyseps2_1", jyseps2_1) - status = file_write(f, "jyseps1_2", jyseps1_2) - - - ;;-initial profile - status = file_write(f, "V0", V0) - - - - ;;-some auxiliary quantities (may be needed) - status = file_write(f, "hthe", hthe) - status = file_write(f, "hthe0", hthe0) - - status = file_write(f, "dx", dx) - status = file_write(f, "dy", dy) - - - file_close, f - - endif - - -; -; -; -if keyword_set(DEBUG) then STOP -END diff --git a/examples/advdiff2/header.hxx b/examples/advdiff2/header.hxx deleted file mode 100644 index 9e6f92431f..0000000000 --- a/examples/advdiff2/header.hxx +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef INCLUDE_GUARD_H -#define INCLUDE_GUARD_H - -#include - -class AdvDiff : public PhysicsModel { - // Evolving variables - Field3D V; - -protected: - int init(bool restarting) override; - int rhs(BoutReal) override; -}; - -#endif diff --git a/examples/advdiff2/init.cxx b/examples/advdiff2/init.cxx deleted file mode 100644 index 7954f7b543..0000000000 --- a/examples/advdiff2/init.cxx +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -#include "header.hxx" - -int AdvDiff::init(bool restarting) { - // 2D initial profiles - Field2D V0; - - // Read initial conditions - mesh->get(V0, "V0"); - mesh->get(mesh->getCoordinates()->dx, "dx"); - mesh->get(mesh->getCoordinates()->dy, "dy"); - - // read options - - // Set evolving variables - SOLVE_FOR(V); - - if (!restarting) { - // Set variables to these values (+ the initial perturbation) - // NOTE: This must be after the calls to bout_solve - V += V0; - } - - return 0; -} - -BOUTMAIN(AdvDiff) diff --git a/examples/advdiff2/rhs.cxx b/examples/advdiff2/rhs.cxx deleted file mode 100644 index 9799175b4b..0000000000 --- a/examples/advdiff2/rhs.cxx +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include - -#include "header.hxx" - -int AdvDiff::rhs(BoutReal UNUSED(t)) { - // Run communications - V.getMesh()->communicate(V); - - ddt(V) = DDX(V); - - return 0; -} diff --git a/examples/advdiff2/runidl.pro b/examples/advdiff2/runidl.pro deleted file mode 100644 index 350762aa00..0000000000 --- a/examples/advdiff2/runidl.pro +++ /dev/null @@ -1,15 +0,0 @@ -loadct,39 - -v=collect(path='./data', var='V') -g=file_import('./slab.grd.nc') -rxy=g.rxy -zxy=g.zxy - - - -nt=n_elements(v[0,0,0,*]) - -nlev=30 -level=1+findgen(nlev)/(nlev-1) - -for it=0,nt-1 do begin CONTOUR, reform(v[*,*,10,it]), rxy, zxy, lev=level, chars=3, /xst, /yst, /iso & wait,1.0 diff --git a/examples/advdiff2/set_bout_top.sh b/examples/advdiff2/set_bout_top.sh deleted file mode 100644 index 7feaf956c4..0000000000 --- a/examples/advdiff2/set_bout_top.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -#export BOUT_TOP=$HOME/BOUT/bout++/ -export BOUT_TOP=/Users/hong/soft/BOUT/ -rm -f pdb2idl.so -ln -s $BOUT_TOP/../pdb2idl/pdb2idl.so diff --git a/examples/advdiff2/slab.grd.nc b/examples/advdiff2/slab.grd.nc deleted file mode 100644 index 01027d4f59..0000000000 Binary files a/examples/advdiff2/slab.grd.nc and /dev/null differ diff --git a/examples/backtrace/.gitignore b/examples/backtrace/.gitignore deleted file mode 100644 index f587f481cd..0000000000 --- a/examples/backtrace/.gitignore +++ /dev/null @@ -1 +0,0 @@ -backtrace \ No newline at end of file diff --git a/examples/backtrace/CMakeLists.txt b/examples/backtrace/CMakeLists.txt deleted file mode 100644 index 4eac38e51a..0000000000 --- a/examples/backtrace/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(backtrace LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(backtrace SOURCES backtrace.cxx) diff --git a/examples/backtrace/README.md b/examples/backtrace/README.md deleted file mode 100644 index ed18497164..0000000000 --- a/examples/backtrace/README.md +++ /dev/null @@ -1,40 +0,0 @@ -Backtrace Example -================= - -This demonstrates what the exception backtrace looks like when something goes -wrong in a physics model or in BOUT++. Requires both backtrace to be enabled -(done by default) and debug symbols (`--enable-debug` with `configure` or -`-DCMAKE_BUILD_TYPE=Debug` with `CMake` in both BOUT++ _and_ this example). - -The output should look something like: - -``` -... -c is inf -Error encountered -====== Exception path ====== -[bt] #10 ./backtrace() [0x40a27e] -_start at /home/abuild/rpmbuild/BUILD/glibc-2.33/csu/../sysdeps/x86_64/start.S:122 -[bt] #9 /lib64/libc.so.6(__libc_start_main+0xd5) [0x7fecbfa28b25] -__libc_start_main at /usr/src/debug/glibc-2.33-4.1.x86_64/csu/../csu/libc-start.c:332 -[bt] #8 ./backtrace() [0x40a467] -main at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:32 (discriminator 9) -[bt] #7 /path/to/BOUT-dev/build/libbout++.so(_ZN6Solver8setModelEP12PhysicsModel+0xb5) [0x7fecc0ca2e93] -Solver::setModel(PhysicsModel*) at /path/to/BOUT-dev/build/../src/solver/solver.cxx:94 -[bt] #6 /path/to/BOUT-dev/build/libbout++.so(_ZN12PhysicsModel10initialiseEP6Solver+0xc0) [0x7fecc0cad594] -PhysicsModel::initialise(Solver*) at /path/to/BOUT-dev/build/../include/bout/physicsmodel.hxx:93 (discriminator 5) -[bt] #5 ./backtrace() [0x40a986] -Backtrace::init(bool) at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:27 -[bt] #4 ./backtrace() [0x40a3cf] -f3() at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:19 -[bt] #3 ./backtrace() [0x40a3be] -f2(int) at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:15 -[bt] #2 ./backtrace() [0x40a386] -f1() at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:13 (discriminator 2) -[bt] #1 ./backtrace(_ZN13BoutExceptionC1IA19_cJEEERKT_DpRKT0_+0xba) [0x40ae16] -BoutException::BoutException(char const (&) [19]) at /path/to/BOUT-dev/build/../include/bout/../boutexception.hxx:28 (discriminator 2) -====== Back trace ====== - -====== Exception thrown ====== -Tomatoes are red? -``` diff --git a/examples/backtrace/backtrace.cxx b/examples/backtrace/backtrace.cxx deleted file mode 100644 index 1a096704e9..0000000000 --- a/examples/backtrace/backtrace.cxx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Check for backtrace after throw - */ - -#include -#include - -void f1() { - BoutReal a = 1; - BoutReal b = 0; - BoutReal c = a / b; - output.write("c is {:f}\n", c); - throw BoutException("Tomatoes are red?\n"); -} -void f2(int UNUSED(a)) { f1(); } - -int f3() { - f2(1); - return 0; -} - -class Backtrace : public PhysicsModel { -protected: - int init(bool UNUSED(restarting)) override { - f3(); - - return 1; - } - int rhs(BoutReal UNUSED(time)) override { return 1; } -}; - -BOUTMAIN(Backtrace) diff --git a/examples/backtrace/data/BOUT.inp b/examples/backtrace/data/BOUT.inp deleted file mode 100644 index fcb97a8522..0000000000 --- a/examples/backtrace/data/BOUT.inp +++ /dev/null @@ -1,5 +0,0 @@ - -[mesh] -nx = 12 -ny = 5 -nz = 2 diff --git a/examples/blob2d/CMakeLists.txt b/examples/blob2d/CMakeLists.txt index 41803df112..a4772874d9 100644 --- a/examples/blob2d/CMakeLists.txt +++ b/examples/blob2d/CMakeLists.txt @@ -8,4 +8,5 @@ endif() bout_add_example(blob2d SOURCES blob2d.cxx - DATA_DIRS delta_0.25 delta_1 delta_10 two_blobs) + DATA_DIRS delta_0.25 delta_1 delta_10 two_blobs data + EXTRA_FILES blob_velocity.py) diff --git a/examples/blob2d/blob2d.cxx b/examples/blob2d/blob2d.cxx index 7007bbeb77..032416ac72 100644 --- a/examples/blob2d/blob2d.cxx +++ b/examples/blob2d/blob2d.cxx @@ -46,7 +46,7 @@ class Blob2D : public PhysicsModel { nullptr}; ///< Performs Laplacian inversions to calculate phi protected: - int init(bool UNUSED(restarting)) { + int init(bool UNUSED(restarting)) override { /******************Reading options *****************/ @@ -114,17 +114,42 @@ class Blob2D : public PhysicsModel { phi = 0.0; // Starting guess for first solve (if iterative) /************ Tell BOUT++ what to solve ************/ - SOLVE_FOR(n, omega); - // Output phi - SAVE_REPEAT(phi); - SAVE_ONCE(rho_s, c_s, Omega_i); - return 0; } - int rhs(BoutReal UNUSED(t)) { + /// Add variables to the output. This can be used to calculate + /// diagnostics + /// + /// @param[inout] state A nested dictionary that can be added to + void outputVars(Options& state) override { + // Set time-varying quantity (assignRepeat) + state["phi"].assignRepeat(phi).setAttributes({{"units", "V"}, + {"conversion", Te0}, + {"standard_name", "potential"}, + {"long_name", "Plasma potential"}}); + + // Force updates to non-varying quantities + state["rho_s"].force(rho_s).setAttributes( + {{"units", "m"}, + {"conversion", 1}, + {"standard_name", "length normalisation"}, + {"long_name", "Gyro-radius length normalisation"}}); + + state["c_s"].force(c_s).setAttributes({{"units", "m/s"}, + {"conversion", 1}, + {"standard_name", "velocity normalisation"}, + {"long_name", "Sound speed normalisation"}}); + + state["Omega_i"].force(Omega_i).setAttributes( + {{"units", "s^-1"}, + {"conversion", 1}, + {"standard_name", "frequency normalisation"}, + {"long_name", "Cyclotron frequency normalisation"}}); + } + + int rhs(BoutReal UNUSED(t)) override { // Run communications //////////////////////////////////////////////////////////////////////////// diff --git a/examples/boutcore/blob/BOUT.inp b/examples/boutcore/blob/BOUT.inp deleted file mode 100644 index 07df540918..0000000000 --- a/examples/boutcore/blob/BOUT.inp +++ /dev/null @@ -1,119 +0,0 @@ -# settings file for BOUT++ -# -# Blob simulation in a 2D slab -# -# This case has blob size -# -# delta = 0.3*256 ~ 10 * delta_* - - -# settings used by the core code - -nout = 50 # number of time-steps -timestep = 50 # time between outputs [1/wci] - -[mesh] - -nx = 260 # Note: 4 guard cells -ny = 1 -nz = 256 - -dx = 0.3 # Grid spacing [rho_s] -dz = 0.3 - - -MXG = 2 # Number of X guard cells -MYG = 0 # No y derivatives, so no guard cells needed in y - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 -second = C2 -upwind = W3 - -[mesh:ddy] - -first = C2 -second = C2 -upwind = W3 - -[mesh:ddz] - -first = FFT -second = FFT -upwind = W3 - -################################################### -# Time-integration solver - -[solver] - -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 10000 # Maximum internal steps per output - -################################################### -# Electrostatic potential solver -# These options are used if boussinesq = false - -[phiSolver] -type = petsc # Needed if Boussinesq = false -pctype = user # Preconditioning type - -fourth_order = true # 4th order or 2nd order - -flags = 0 # inversion flags for phi -# 0 = Zero value -# 10 = Zero gradient AC inner & outer -# 15 = Zero gradient AC and DC -# 768 = Zero laplace inner & outer - -[phiSolver:precon] # Preconditioner (if pctype=user) -filter = 0.0 # Must not filter solution -flags = 49152 # set_rhs i.e. identity matrix in boundaries - -################################################### -# Electrostatic potential solver (Boussinesq) - -[phiBoussinesq] -# By default type is tri (serial) or spt (parallel) -flags = 0 - -################################################## -# general settings for the model - -[model] - -Te0 = 5 # Electron Temperature (eV) - -n0 = 2e+18 # Background plasma density (m^-3) - -compressible = false # Compressibility? - -boussinesq = true # Boussinesq approximation (no perturbed n in vorticity) - -D_vort = 1e-06 # Viscosity -D_n = 1e-06 # Diffusion - -R_c = 1.5 # Radius of curvature (m) - -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -bndry_all = neumann # Zero-gradient on all boundaries - -[n] # Density -scale = 1.0 # size of perturbation - -height = 0.5 -width = 0.05 - -function = 1 + height * exp(-((x-0.25)/width)^2 - ((z/(2*pi) - 0.5)/width)^2) diff --git a/examples/boutcore/data/BOUT.inp b/examples/boutcore/data/BOUT.inp deleted file mode 100644 index 00736474ac..0000000000 --- a/examples/boutcore/data/BOUT.inp +++ /dev/null @@ -1,16 +0,0 @@ -nout = 10 -timestep = 0.1 - -[mesh] -n = 1 -nx = n+2*MXG -ny = n -nz = n -dy = 1/n/2/pi - -MXG = 1 -MYG = 1 - -[solver] -rtol = 1e-14 -atol = 1e-18 diff --git a/examples/boutpp/blob2d.py b/examples/boutpp/blob2d.py index 4dc8ea60ac..4341cb8975 100755 --- a/examples/boutpp/blob2d.py +++ b/examples/boutpp/blob2d.py @@ -5,7 +5,7 @@ # # 2D blob simulations # -# Copyright: NR Walkden, B Dudson, D Schwörer; 2012, 2017, 2018 +# Copyright: NR Walkden, B Dudson, D Bold; 2012, 2017, 2018 # ################################################################### diff --git a/examples/boutpp/blob2d_legacy.py b/examples/boutpp/blob2d_legacy.py deleted file mode 100755 index 7d05ec1e4a..0000000000 --- a/examples/boutpp/blob2d_legacy.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/python3 -# -*- coding: utf-8 - -#!################################################################## -# -# 2D blob simulations -# -# Copyright: NR Walkden, B Dudson, D Schwörer; 2012, , 2017 -# -################################################################### - -import boutpp as bc -from numpy import sqrt -from boutpp import bracket, DDZ, Delp2 -import sys - -bc.init("-d blob".split(" ") + sys.argv[1:]) -mesh = bc.Mesh.getGlobal() -n = bc.Field3D.fromMesh(mesh) -omega = bc.Field3D.fromMesh(mesh) -phi = bc.Field3D.fromMesh(mesh) - -phiSolver = bc.Laplacian() - -options = bc.Options("model") -# Temperature in eV -Te0 = options.get("Te0", 30) -e = options.get("e", 1.602e-19) -m_i = options.get("m_i", 2 * 1.667e-27) -m_e = options.get("m_e", 9.11e-31) - -# Background density in cubic m -n0 = options.get("n0", 1e19) -# Viscous diffusion coefficient -D_vort = options.get("D_vort", 0) -# Density diffusion coefficient -D_n = options.get("D_n", 0) - -# Radius of curvature [m] -R_c = options.get("R_c", 1.5) -# Parallel connection length [m] -L_par = options.get("L_par", 10) - -# Value of magnetic field strength [T] -B0 = options.get("B0", 0.35) - - -# System option switches - -# Include compressible ExB term in density equation -compressible = options.get("compressible", False) -# Use Boussinesq approximation in vorticity -boussinesq = options.get("boussinesq", True) -# Sheath closure -sheath = options.get("sheath", True) - - -Omega_i = e * B0 / m_i # Cyclotron Frequency -c_s = sqrt(e * Te0 / m_i) # Bohm sound speed -rho_s = c_s / Omega_i # Bohm gyro-radius - -print("\n\n\t----------Parameters: ------------ \n\tOmega_i = %e /s,\n\t" - "c_s = %e m/s,\n\trho_s = %e m\n" % (Omega_i, c_s, rho_s)) - -# Calculate delta_*, blob size scaling -print("\tdelta_* = rho_s * (dn/n) * %e " - % (pow(L_par * L_par / (R_c * rho_s), 1. / 5))) - -# /************ Create a solver for potential ********/ - -if boussinesq: - # BOUT.inp section "phiBoussinesq" - phiSolver = bc.Laplacian(bc.Options("phiBoussinesq")) -else: - # BOUT.inp section "phiSolver" - phiSolver = bc.Laplacian(bc.Options("phiSolver")) - -phi = bc.Field3D.fromMesh(mesh) -phi.set(0.0) # Starting guess for first solve (if iterative) - -# /************ Tell BOUT++ what to solve ************/ - -model = bc.PhysicsModelBase() -model.solve_for(n=n, omega=omega) -# model.save_repeat(phi=phi) -# model.save_once(rho_s=rho_s,c_s=c_s,Omega_i=Omega_i) - - -def rhs(time): - global n, omega, phi - # Run communications - ###################################### - mesh.communicate(n, omega) - - # Invert div(n grad(phi)) = grad(n) grad(phi) + n Delp_perp^2(phi) = omega - ###################################### - # Set the time derivative by adding/... to it - # make sure to never overwrite it - # ddt_n = bla does NOT set the time derivative - ddt_n = n.ddt() - ddt_n.set(0) - if not boussinesq: - # Including full density in vorticit inversion - # Update the 'C' coefficient. See invert_laplace.hxx - phiSolver.setCoefC(n) - # Use previous solution as guess - phi = phiSolver.solve(omega / n, phi) - else: - # Background density only (1 in normalised units) - phi = phiSolver.solve(omega, phi) - - mesh.communicate(phi) - - # Density Evolution - # / - - ddt_n += -bracket(phi, n, "BRACKET_SIMPLE") # ExB term - ddt_n += 2 * DDZ(n) * (rho_s / R_c) # Curvature term - ddt_n += D_n * Delp2(n) # Diffusion term - - if compressible: - ddt_n -= 2 * n * DDZ(phi) * (rho_s / R_c) # ExB Compression term - - if sheath: - # Sheath closure - ddt_n += n * phi * (rho_s / L_par) # - (n - 1)*(rho_s/L_par) - - # Vorticity evolution - # / - # ExB term - ddt_omega = -bracket(phi, omega, "BRACKET_SIMPLE") - ddt_omega += 2 * DDZ(n) * (rho_s / R_c) / n - # Viscous diffusion term - ddt_omega += D_vort * Delp2(omega) / n - - if sheath: - ddt_omega += phi * (rho_s / L_par) - # other option to set time derivaitve: - # create a field and set it in the end - omega.ddt(ddt_omega) - -# Start the simulation -model.setRhs(rhs) -model.solve() diff --git a/examples/conducting-wall-mode/cwm.cxx b/examples/conducting-wall-mode/cwm.cxx index 3b3fba1a45..6ad23033ee 100644 --- a/examples/conducting-wall-mode/cwm.cxx +++ b/examples/conducting-wall-mode/cwm.cxx @@ -14,14 +14,13 @@ class CWM : public PhysicsModel { private: // 2D initial profiles - Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, rho0, Ajpar0; - Vector2D b0xcv; // for curvature terms + Field2D Ni0, Te0; // 3D evolving fields - Field3D rho, te, ajpar; + Field3D rho, te; // Derived 3D variables - Field3D phi, jpar; + Field3D phi; // e-i Collision frequency Field3D nu; @@ -33,8 +32,8 @@ class CWM : public PhysicsModel { Field2D Rxy, Bpxy, Btxy, hthe, Zxy; // parameters - BoutReal Te_x, Ti_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; - BoutReal lambda_ei, lambda_ii; + BoutReal Te_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; + BoutReal lambda_ei; BoutReal nu_hat, wci, nueix; bool bout_exb; // Use BOUT-06 expression for ExB velocity @@ -48,12 +47,6 @@ class CWM : public PhysicsModel { // Coefficients for linear sheath problem Field2D LAMBDA1, LAMBDA2; - // My ixseps variables - int my_ixseps; - - // Communication object - FieldGroup comms; - // Coordinate system Coordinates* coord; @@ -63,43 +56,20 @@ class CWM : public PhysicsModel { int init(bool UNUSED(restarting)) override { Field2D I; // Shear factor - output.write("Solving 6-variable 2-fluid equations\n"); - /************* LOAD DATA FROM GRID FILE ****************/ // Load 2D profiles (set to zero if not found) - mesh->get(Ni0, "Ni0"); - mesh->get(Ti0, "Ti0"); - mesh->get(Te0, "Te0"); - mesh->get(Vi0, "Vi0"); - mesh->get(Ve0, "Ve0"); - mesh->get(phi0, "phi0"); - mesh->get(rho0, "rho0"); - mesh->get(Ajpar0, "Ajpar0"); + GRID_LOAD(Ni0, Te0); coord = mesh->getCoordinates(); - // Load magnetic curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // b0xkappa terms - // Load metrics - mesh->get(Rxy, "Rxy"); - mesh->get(Zxy, "Zxy"); - mesh->get(Bpxy, "Bpxy"); - mesh->get(Btxy, "Btxy"); - mesh->get(hthe, "hthe"); + GRID_LOAD(Rxy, Zxy, Bpxy, Btxy, hthe); mesh->get(coord->dx, "dpsi"); mesh->get(I, "sinty"); // Load normalisation values - mesh->get(Te_x, "Te_x"); - mesh->get(Ti_x, "Ti_x"); - mesh->get(Ni_x, "Ni_x"); - mesh->get(bmag, "bmag"); - - // Get separatrix location - mesh->get(my_ixseps, "ixseps1"); + GRID_LOAD(Te_x, Ni_x, bmag); Ni_x *= 1.0e14; bmag *= 1.0e4; @@ -129,7 +99,6 @@ class CWM : public PhysicsModel { if (lowercase(ptstr) == "shifted") { ShearFactor = 0.0; // I disappears from metric - b0xcv.z += I * b0xcv.x; } /************** CALCULATE PARAMETERS *****************/ @@ -138,7 +107,6 @@ class CWM : public PhysicsModel { fmei = 1. / 1836.2 / AA; lambda_ei = 24. - log(sqrt(Ni_x) / Te_x); - lambda_ii = 23. - log(ZZ * ZZ * ZZ * sqrt(2. * Ni_x) / pow(Ti_x, 1.5)); wci = 9.58e3 * ZZ * bmag / AA; nueix = 2.91e-6 * Ni_x * lambda_ei / pow(Te_x, 1.5); nu_hat = zeff * nueix / wci; @@ -162,15 +130,7 @@ class CWM : public PhysicsModel { // Normalise profiles Ni0 /= Ni_x / 1.0e14; - Ti0 /= Te_x; Te0 /= Te_x; - phi0 /= Te_x; - Vi0 /= Vi_x; - - // Normalise curvature term - b0xcv.x /= (bmag / 1e4); - b0xcv.y *= rho_s * rho_s; - b0xcv.z *= rho_s * rho_s; // Normalise geometry Rxy /= rho_s; @@ -210,31 +170,9 @@ class CWM : public PhysicsModel { // Tell BOUT++ which variables to evolve // add evolving variables to the communication object - SOLVE_FOR(rho); - comms.add(rho); - - SOLVE_FOR(te); - comms.add(te); + SOLVE_FOR(rho, te); - // Set boundary conditions for phi - phi.setBoundary("phi"); - - /************** SETUP COMMUNICATIONS **************/ - - // add extra variables to communication - comms.add(phi); - - /*************** DUMP VARIABLES TO OUTPUT**********/ - dump.add(phi, "phi", 1); - - SAVE_ONCE(Ni0, Te0, phi0, rho0); SAVE_ONCE(Rxy, Bpxy, Btxy, Zxy, hthe); - - SAVE_ONCE(Te_x, Ti_x, Ni_x); - SAVE_ONCE(AA, ZZ, zeff, rho_s, wci, bmag); - dump.addOnce(mesh->LocalNx, "ngx"); - dump.addOnce(mesh->LocalNy, "ngy"); - dump.addOnce(mesh->LocalNz, "ngz"); SAVE_ONCE(nu_hat, hthe0); // Create a solver for the Laplacian @@ -245,17 +183,86 @@ class CWM : public PhysicsModel { ////////////////////////////////////////////////////////////////// + /// Add variables to the output. This can be used to calculate + /// diagnostics + /// + /// @param[inout] state A nested dictionary that can be added to + void outputVars(Options& state) override { + // Set time-varying quantity (assignRepeat) + state["phi"].assignRepeat(phi).setAttributes({{"units", "V"}, + {"conversion", Te_x}, + {"standard_name", "potential"}, + {"long_name", "Plasma potential"}}); + + // Force updates to non-varying quantities + state["Ni0"].force(Ni0).setAttributes( + {{"units", "m^-3"}, + {"conversion", Ni_x}, + {"standard_name", "background ion density"}, + {"long_name", "Background ion number density"}}); + + state["Te0"].force(Te0).setAttributes( + {{"units", "eV"}, + {"conversion", Te_x}, + {"standard_name", "background electron temperature"}, + {"long_name", "Background electron temperature"}}); + + state["rho_s"].force(rho_s).setAttributes( + {{"units", "m"}, + {"conversion", 1}, + {"standard_name", "length normalisation"}, + {"long_name", "Gyro-radius length normalisation"}}); + + state["wci"].force(wci).setAttributes( + {{"units", "s^-1"}, + {"conversion", 1}, + {"standard_name", "frequency normalisation"}, + {"long_name", "Cyclotron frequency normalisation"}}); + + state["Te_x"].force(Te_x).setAttributes( + {{"units", "eV"}, + {"conversion", 1}, + {"standard_name", "temperature normalisation"}, + {"long_name", "Temperature normalisation"}}); + + state["Ni_x"].force(Ni_x).setAttributes( + {{"units", "m^-3"}, + {"conversion", 1}, + {"standard_name", "density temperature"}, + {"long_name", "Number density normalisation"}}); + + state["bmag"].force(bmag).setAttributes({{"units", "G"}, + {"conversion", 1}, + {"standard_name", "B field normalisation"}, + {"long_name", "B field normalisation"}}); + + state["AA"].force(AA).setAttributes({{"units", ""}, + {"conversion", 1}, + {"standard_name", "amu"}, + {"long_name", "Atomic mass number"}}); + + state["ZZ"].force(ZZ).setAttributes({{"units", ""}, + {"conversion", 1}, + {"standard_name", "ion charge"}, + {"long_name", "Ion charge"}}); + + state["zeff"].force(zeff).setAttributes({{"units", ""}, + {"conversion", 1}, + {"standard_name", "Zeff"}, + {"long_name", "Effective ion charge"}}); + } + /////////////////////////////////////////////////////////////////// // Function called at each time step // Time derivatives calculated here - int rhs(BoutReal UNUSED(t)) { + int rhs(BoutReal UNUSED(t)) override { // Invert vorticity to get phi // Solves \nabla^2_\perp x + (1./c)*\nabla_perp c\cdot\nabla_\perp x + a x = b phi = phiSolver->solve(rho / Ni0); // Communicate variables - mesh->communicate(comms); + mesh->communicate(phi, te, rho); // 'initial guess' for phi boundary values, before applying sheath boundary conditions // to set the parallel current. diff --git a/examples/conduction-snb/conduction-snb.cxx b/examples/conduction-snb/conduction-snb.cxx index a5ff7fd804..bc036dede2 100644 --- a/examples/conduction-snb/conduction-snb.cxx +++ b/examples/conduction-snb/conduction-snb.cxx @@ -27,7 +27,7 @@ int main(int argc, char** argv) { Options::root()["Div_Q"] = Div_Q; Options::root()["Div_Q_SH"] = Div_Q_SH; - bout::writeDefaultOutputFile(); + bout::writeDefaultOutputFile(opt); BoutFinalise(); return 0; diff --git a/examples/dalf3/dalf3.cxx b/examples/dalf3/dalf3.cxx index 246cda7b74..493e8f5e45 100644 --- a/examples/dalf3/dalf3.cxx +++ b/examples/dalf3/dalf3.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -76,11 +77,11 @@ class DALF3 : public PhysicsModel { std::unique_ptr phiSolver{nullptr}; // Laplacian solver in X-Z std::unique_ptr aparSolver{nullptr}; // Laplacian solver in X-Z for Apar - LaplaceXY* laplacexy; // Laplacian solver in X-Y (n=0) + std::unique_ptr laplacexy{nullptr}; // Laplacian solver in X-Y (n=0) Field2D phi2D; // Axisymmetric potential, used when split_n0=true protected: - int init(bool UNUSED(restarting)) { + int init(bool UNUSED(restarting)) override { ///////////////////////////////////////////////////// // Load data from the grid @@ -115,16 +116,11 @@ class DALF3 : public PhysicsModel { mesh->get(hthe, "hthe"); // m mesh->get(I, "sinty"); // m^-2 T^-1 - // Set locations of staggered variables - jpar.setLocation(CELL_YLOW); - Ajpar.setLocation(CELL_YLOW); - apar.setLocation(CELL_YLOW); - ////////////////////////////////////////////////////////////// // Options - auto globalOptions = Options::root(); - auto options = globalOptions["dalf3"]; + auto& globalOptions = Options::root(); + auto& options = globalOptions["dalf3"]; split_n0 = options["split_n0"].withDefault(false); estatic = options["estatic"].withDefault(false); @@ -143,8 +139,7 @@ class DALF3 : public PhysicsModel { parallel_lc = options["parallel_lc"].withDefault(true); nonlinear = options["nonlinear"].withDefault(true); - int bracket_method; - bracket_method = options["bracket_method"].withDefault(0); + const int bracket_method = options["bracket_method"].withDefault(0); switch (bracket_method) { case 0: { bm = BRACKET_STD; @@ -305,7 +300,7 @@ class DALF3 : public PhysicsModel { // LaplaceXY for n=0 solve if (split_n0) { // Create an XY solver for n=0 component - laplacexy = new LaplaceXY(mesh); + laplacexy = std::make_unique(mesh); phi2D = 0.0; // Starting guess } @@ -319,7 +314,7 @@ class DALF3 : public PhysicsModel { } // Curvature operator - const Field3D Kappa(const Field3D& f) { + Field3D Kappa(const Field3D& f) { if (curv_kappa) { // Use the b0xcv vector from grid file return -2. * b0xcv * Grad(f) / B0; @@ -328,25 +323,14 @@ class DALF3 : public PhysicsModel { return 2. * bracket(log(B0), f, bm); } - const Field3D Grad_parP(const Field3D& f, CELL_LOC loc) { - Field3D result; - if (mesh->StaggerGrids) { - result = Grad_par(f, loc); - if (nonlinear) { - result -= - beta_hat * bracket(interp_to(apar, loc), interp_to(f, loc), BRACKET_ARAKAWA); - } - } else { - if (nonlinear) { - result = ::Grad_parP(apar * beta_hat, f); - } else { - result = Grad_par(f, loc); - } + Field3D Grad_parP(const Field3D& f) { + if (nonlinear) { + return ::Grad_parP(apar * beta_hat, f); } - return result; + return Grad_par(f); } - int rhs(BoutReal UNUSED(time)) { + int rhs(BoutReal UNUSED(time)) override { // Invert vorticity to get electrostatic potential if (split_n0) { @@ -367,7 +351,7 @@ class DALF3 : public PhysicsModel { apar = 0.; if (ZeroElMass) { // Not evolving Ajpar - jpar = Grad_par(Pe - phi, CELL_YLOW) / eta; + jpar = Grad_par(Pe - phi) / eta; jpar.applyBoundary(); } else { jpar = Ajpar / mu_hat; @@ -427,8 +411,7 @@ class DALF3 : public PhysicsModel { } // Vorticity equation - ddt(Vort) = B0 * B0 * Grad_parP(jpar / interp_to(B0, CELL_YLOW), CELL_CENTRE) - - B0 * Kappa(Pe); + ddt(Vort) = B0 * B0 * Grad_parP(jpar / B0) - B0 * Kappa(Pe); if (nonlinear) { ddt(Vort) -= bracket(phi, Vort, bm); // ExB advection @@ -452,8 +435,8 @@ class DALF3 : public PhysicsModel { // Parallel Ohm's law if (!(estatic && ZeroElMass)) { // beta_hat*apar + mu_hat*jpar - ddt(Ajpar) = Grad_parP(Pe - phi, CELL_YLOW) - - beta_hat * bracket(apar, Pe0, BRACKET_ARAKAWA) - eta * jpar; + ddt(Ajpar) = Grad_parP(Pe - phi) - beta_hat * bracket(apar, Pe0, BRACKET_ARAKAWA) + - eta * jpar; if (nonlinear) { ddt(Ajpar) -= mu_hat * bracket(phi, jpar, bm); @@ -465,8 +448,7 @@ class DALF3 : public PhysicsModel { } // Parallel velocity - ddt(Vpar) = -Grad_parP(Pe, CELL_YLOW) - + beta_hat * bracket(apar, interp_to(Pe0, CELL_YLOW), BRACKET_ARAKAWA); + ddt(Vpar) = -Grad_parP(Pe) + beta_hat * bracket(apar, Pe0); if (nonlinear) { ddt(Vpar) -= bracket(phi, Vpar, bm); @@ -481,11 +463,8 @@ class DALF3 : public PhysicsModel { } // Electron pressure - ddt(Pe) = - -bracket(phi, Pet, bm) - + Pet - * (Kappa(phi - Pe) - + B0 * Grad_parP((jpar - Vpar) / interp_to(B0, CELL_YLOW), CELL_YLOW)); + ddt(Pe) = -bracket(phi, Pet, bm) + + Pet * (Kappa(phi - Pe) + B0 * Grad_parP(jpar - Vpar) / B0); if (smooth_separatrix) { // Experimental smoothing across separatrix diff --git a/examples/em-drift/.gitignore b/examples/em-drift/.gitignore deleted file mode 100644 index d837f17cae..0000000000 --- a/examples/em-drift/.gitignore +++ /dev/null @@ -1 +0,0 @@ -2fluid \ No newline at end of file diff --git a/examples/em-drift/2fluid.cxx b/examples/em-drift/2fluid.cxx deleted file mode 100644 index 00bd7e206c..0000000000 --- a/examples/em-drift/2fluid.cxx +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * 2-fluid equations for drift-wave tests - * - * Settings: - * - ZeroElMass - * - AparInEpar - *******************************************************************************/ - -#include - -#include -#include -#include - -class EMdrift : public PhysicsModel { -private: - // 2D initial profiles - Field2D Ni0, Ti0, Te0; - - // 3D evolving fields - Field3D rho, Ni, Ajpar; - - // Derived 3D variables - Field3D phi, Apar, Ve, jpar; - - // Non-linear coefficients - Field3D nu, mu_i; - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - - // parameters - BoutReal Te_x, Ti_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; - BoutReal lambda_ei, lambda_ii; - BoutReal nu_hat, mui_hat, wci, nueix, nuiix; - BoutReal beta_p; - - // settings - bool estatic, ZeroElMass; // Switch for electrostatic operation (true = no Apar) - bool AparInEpar; - BoutReal zeff, nu_perp; - bool evolve_ajpar; - BoutReal ShearFactor; - BoutReal nu_factor; - - // Communication object - FieldGroup comms; - - // Inverts a Laplacian to get potential - std::unique_ptr phiSolver; - - // Solves the electromagnetic potential - std::unique_ptr aparSolver; - Field2D acoef; // Coefficient in the Helmholtz equation - - int init(bool UNUSED(restarting)) override { - Field2D I; // Shear factor - - output.write("Solving 6-variable 2-fluid equations\n"); - - /************* LOAD DATA FROM GRID FILE ****************/ - - Coordinates* coord = mesh->getCoordinates(); - - // Load 2D profiles (set to zero if not found) - mesh->get(Ni0, "Ni0"); - mesh->get(Ti0, "Ti0"); - mesh->get(Te0, "Te0"); - - // Load metrics - mesh->get(Rxy, "Rxy"); - mesh->get(Bpxy, "Bpxy"); - mesh->get(Btxy, "Btxy"); - mesh->get(hthe, "hthe"); - mesh->get(coord->dx, "dpsi"); - mesh->get(I, "sinty"); - - // Load normalisation values - mesh->get(Te_x, "Te_x"); - mesh->get(Ti_x, "Ti_x"); - mesh->get(Ni_x, "Ni_x"); - mesh->get(bmag, "bmag"); - - Ni_x *= 1.0e14; - bmag *= 1.0e4; - - /*************** READ OPTIONS *************************/ - - auto& globalOptions = Options::root(); - auto& options = globalOptions["2fluid"]; - - AA = options["AA"].withDefault(2.0); - ZZ = options["ZZ"].withDefault(1.0); - - estatic = options["estatic"].withDefault(false); - ZeroElMass = options["ZeroElMass"].withDefault(false); - AparInEpar = options["AparInEpar"].withDefault(true); - - zeff = options["Zeff"].withDefault(1.0); - nu_perp = options["nu_perp"].withDefault(0.0); - ShearFactor = options["ShearFactor"].withDefault(1.0); - nu_factor = options["nu_factor"].withDefault(1.0); - - evolve_ajpar = globalOptions["Ajpar"]["evolve"].withDefault(true); - - if (ZeroElMass) { - evolve_ajpar = 0; // Don't need ajpar - calculated from ohm's law - } - - /************* SHIFTED RADIAL COORDINATES ************/ - - // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault( - "identity"); - - if (lowercase(ptstr) == "shifted") { - ShearFactor = 0.0; // I disappears from metric - } - - /************** CALCULATE PARAMETERS *****************/ - - rho_s = 1.02 * sqrt(AA * Te_x) / ZZ / bmag; - fmei = 1. / 1836.2 / AA; - - lambda_ei = 24. - log(sqrt(Ni_x) / Te_x); - lambda_ii = 23. - log(ZZ * ZZ * ZZ * sqrt(2. * Ni_x) / pow(Ti_x, 1.5)); - wci = 9.58e3 * ZZ * bmag / AA; - nueix = 2.91e-6 * Ni_x * lambda_ei / pow(Te_x, 1.5); - nuiix = 4.78e-8 * pow(ZZ, 4.) * Ni_x * lambda_ii / pow(Ti_x, 1.5) / sqrt(AA); - nu_hat = nu_factor * zeff * nueix / wci; - - if (nu_perp < 1.e-10) { - mui_hat = (3. / 10.) * nuiix / wci; - } else { - mui_hat = nu_perp; - } - - if (estatic) { - beta_p = 1.e-29; - } else { - beta_p = 4.03e-11 * Ni_x * Te_x / bmag / bmag; - } - - Vi_x = wci * rho_s; - - output.write("Normalisation: rho_s = {:e} wci = {:e} beta_p = {:e}\n", rho_s, wci, - beta_p); - - /************** PRINT Z INFORMATION ******************/ - - BoutReal hthe0; - if (mesh->get(hthe0, "hthe0") == 0) { - output.write( - " ****NOTE: input from BOUT, Z length needs to be divided by {:e}\n", - hthe0 / rho_s); - } - - /************** NORMALISE QUANTITIES *****************/ - - output.write("\tNormalising to rho_s = {:e}\n", rho_s); - - // Normalise profiles - Ni0 /= Ni_x / 1.0e14; - Ti0 /= Te_x; - Te0 /= Te_x; - - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - I *= rho_s * rho_s * (bmag / 1e4) * ShearFactor; - coord->dx /= rho_s * rho_s * (bmag / 1e4); - - // Normalise magnetic field - Bpxy /= (bmag / 1.e4); - Btxy /= (bmag / 1.e4); - coord->Bxy /= (bmag / 1.e4); - - /**************** CALCULATE METRICS ******************/ - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - /**************** SET EVOLVING VARIABLES *************/ - - // Tell BOUT++ which variables to evolve - // add evolving variables to the communication object - SOLVE_FOR(rho); - comms.add(rho); - - SOLVE_FOR(Ni); - comms.add(Ni); - - if (evolve_ajpar) { - SOLVE_FOR(Ajpar); - comms.add(Ajpar); - output.write("=> Evolving ajpar\n"); - } else { - output.write("=> Not evolving Apar\n"); - initial_profile("Ajpar", Ajpar); - if (ZeroElMass) { - dump.add(Ajpar, "Ajpar", 1); // output calculated Ajpar - } - } - - jpar.setBoundary("jpar"); - - /************** SETUP COMMUNICATIONS **************/ - - // add extra variables to communication - comms.add(phi, Apar); - - // Add any other variables to be dumped to file - SAVE_REPEAT(phi, Apar, jpar); - - SAVE_ONCE(Ni0, Te0, Ti0); - SAVE_ONCE(Te_x, Ti_x, Ni_x, rho_s, wci, zeff, AA); - - // Create a solver for the Laplacian - phiSolver = Laplacian::create(&globalOptions["phiSolver"]); - - if (!(estatic || ZeroElMass)) { - // Create a solver for the electromagnetic potential - aparSolver = Laplacian::create(&globalOptions["aparSolver"]); - acoef = (-0.5 * beta_p / fmei) * Ni0; - aparSolver->setCoefA(acoef); - } else { - globalOptions["aparSolver"].setConditionallyUsed(); - } - - return 0; - } - - // just define a macro for V_E dot Grad -#define vE_Grad(f, p) (b0xGrad_dot_Grad(p, f) / coord->Bxy) - - int rhs(BoutReal UNUSED(t)) override { - - Coordinates* coord = mesh->getCoordinates(); - - // Solve EM fields - phi = phiSolver->solve(rho / Ni0); - - if (estatic || ZeroElMass) { - // Electrostatic operation - - Apar = 0.0; - } else { - Apar = aparSolver->solve(-acoef * Ajpar); - } - - // Communicate variables - mesh->communicate(comms); - - // Update non-linear coefficients on the mesh - nu = nu_hat * Ni0 / pow(Te0, 1.5); - mu_i = mui_hat * Ni0 / sqrt(Ti0); - - if (ZeroElMass) { - // Set jpar,Ve,Ajpar neglecting the electron inertia term - - jpar = ((Te0 * Grad_par(Ni)) - (Ni0 * Grad_par(phi))) / (fmei * 0.51 * nu); - - // Set boundary conditions on jpar - jpar.applyBoundary(); - - // Need to communicate jpar - mesh->communicate(jpar); - - Ve = -jpar / Ni0; - Ajpar = Ve; - } else { - // Evolving electron parallel velocity - - if (AparInEpar) { - // Include Apar term in Eparallel - Ve = Ajpar + Apar; - } else { - Ve = Ajpar; - } - jpar = -Ni0 * Ve; - } - - // DENSITY EQUATION - - ddt(Ni) = -vE_Grad(Ni0, phi); - - // VORTICITY - - ddt(rho) = SQ(coord->Bxy) * Div_par(jpar); - - // AJPAR - - ddt(Ajpar) = 0.0; - if (evolve_ajpar) { - ddt(Ajpar) += (1. / fmei) * Grad_par(phi); - ddt(Ajpar) -= (1. / fmei) * (Te0 / Ni0) * Grad_par(Ni); - ddt(Ajpar) += 0.51 * nu * jpar / Ni0; - } - - return 0; - } -}; - -BOUTMAIN(EMdrift); diff --git a/examples/em-drift/CMakeLists.txt b/examples/em-drift/CMakeLists.txt deleted file mode 100644 index 5a5fc8fe51..0000000000 --- a/examples/em-drift/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(em-drift LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(em-drift - SOURCES 2fluid.cxx - EXTRA_FILES uedge.grd_beta.nc) diff --git a/examples/em-drift/bout_resdrift_em.pdf b/examples/em-drift/bout_resdrift_em.pdf deleted file mode 100644 index 6ebe9cd88e..0000000000 Binary files a/examples/em-drift/bout_resdrift_em.pdf and /dev/null differ diff --git a/examples/em-drift/complexRoots.pro b/examples/em-drift/complexRoots.pro deleted file mode 100644 index fca2218f71..0000000000 --- a/examples/em-drift/complexRoots.pro +++ /dev/null @@ -1,49 +0,0 @@ -function complexRoots, s, t, pr, pi, order=order -; -; -; s is a parameter, s>0 -;---------------------- - - t=( sqrt(s^4 + 16*s^2) - s^2 )/2. - - pr=sqrt(t) - pi=2*s/pr - - - if not keyword_set(ORDER) then order=1 - - case order of - 1: begin - w=complex(pr,pi-s)/2 - end - - 2: begin - w=complex(-pr,-pi-s)/2 - end - - endcase - -; -; -return,w -end - -pro getComplexRoots, s, w1, w2, plot=plot, linear=linear - - if keyword_set(LINEAR) then begin - s=1e-3 + 1e2*findgen(1001)/1000. - endif else begin - s=1e-3*10^(6*findgen(100)/101) - endelse - - w1=complexRoots(s, order=1) - w2=complexRoots(s, order=2) - - if keyword_set(PLOT) then begin - plot, s, float(w1), yr=[-2,2], /xst, tit='Complex roots' - oplot, s, float(w2) - oplot, s, imaginary(w1), lin=2 - oplot, s, imaginary(w2), lin=2 & oplot, s, s*0 - endif - -end diff --git a/examples/em-drift/data/BOUT.inp b/examples/em-drift/data/BOUT.inp deleted file mode 100644 index 44853ca8b4..0000000000 --- a/examples/em-drift/data/BOUT.inp +++ /dev/null @@ -1,94 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -nout = 30 # number of time-steps -timestep = 10.0 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 33 # number of points in z direction (2^n + 1) -ZMIN = 0.0 -ZMAX = 1.53566e-05 - -MXG = 2 -MYG = 2 - -grid = "uedge.grd_beta.nc" - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 -second = C2 -upwind = W3 - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-12 # absolute tolerance -rtol = 1e-07 # relative tolerance - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 2.0 -ZZ = 1.0 - -estatic = false # if true, electrostatic (Apar = 0) -ZeroElMass = true # Use Ohms law without electron inertia -AparInEpar = false -Zeff = 128.0 # Z effective -nu_perp = 1e-20 - -ShearFactor = 0.0 - -nu_factor = 0.000518718 -#nu_factor = 1e-3 - -[phiSolver] -inner_boundary_flags = 0 -outer_boundary_flags = 0 - -[aparSolver] -inner_boundary_flags = 0 -outer_boundary_flags = 0 - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -bndry_all = neumann # Zero gradient - -[Ni] -scale = 1e-08 # only perturbing Ni - -function = sin(y) * sin(z) - -[jpar] -bndry_all = neumann # Zero gradient diff --git a/examples/em-drift/dispersion.pro b/examples/em-drift/dispersion.pro deleted file mode 100644 index ed35c04f2d..0000000000 --- a/examples/em-drift/dispersion.pro +++ /dev/null @@ -1,83 +0,0 @@ -;; Calculates dispersion relation using FZ_ROOTS -;; Adapted from complexRoots - -;; Result depends on mu = (c * kperp / wpe)^2 and sparsperp = wci*wce*(kpar*c/wpe)^2 - -FUNCTION calc_cubic, x, c - RETURN, c[0] + c[1]*x + c[2]*x*x + c[3]*x*x*x -END - -FUNCTION cubic_root, coef - a = coef[2] / coef[3] - b = coef[1] / coef[3] - c = coef[0] / coef[3] - - p = b - a*a/3. - q = c + (2.*a*a*a - 9.*a*b) / 27. - - u1 = (-q/2. + SQRT(q*q/4. + p*p*p/27.))^(1./3.) - - u2 = COMPLEX(-0.5, SQRT(3.)/2.) * u1 - u3 = COMPLEX(-0.5, -SQRT(3.)/2.) * u1 - - x1 = -p/(3.*u1) + u1 - a/3. - x2 = -p/(3.*u2) + u2 - a/3. - x3 = -p/(3.*u3) + u3 - a/3. - - return, [x1,x2,x3] -END - -FUNCTION dispersion, mu, sparsperp, linear=linear, epar=epar, gradp=gradp - - if keyword_set(LINEAR) then begin - s=1e-3 + 1e2*findgen(1001)/1000. - endif else begin - s=1e-3*10^(6*findgen(100)/101) - endelse - - N = N_ELEMENTS(s) - - cubic = 0 - IF KEYWORD_SET(epar) OR KEYWORD_SET(gradp) THEN BEGIN - C = COMPLEXARR(4) - cubic = 1 - ENDIF ELSE C = COMPLEXARR(3) - - w1 = COMPLEXARR(N) - w2 = w1 - w3 = w1 - - FOR i=0, N-1 DO BEGIN - C[0] = COMPLEX(0.0, -1.*s[i]) - C[1] = COMPLEX(0.0, s[i]) - - C[2] = COMPLEX(1.0) - IF KEYWORD_SET(gradp) THEN C[2] = C[2] + COMPLEX(0.0, s[i]/sparsperp) - - IF cubic THEN BEGIN - ; problem becomes cubic - C[3] = COMPLEX(0.0, -1.*mu*s[i] / sparsperp) - IF KEYWORD_SET(epar) THEN C[3] = C[3] - COMPLEX(0.0, s[i]/sparsperp) - - result = FZ_ROOTS(C, EPS=1e-6) - - IF imaginary(result[2]) GT imaginary(result[1]) THEN BEGIN - tmp = result[2] - result[2] = result[1] - result[1] = tmp - ENDIF - - ;result = cubic_root(c) - - ;PRINT, s[i], c[0], c[1], c[2], c[3] - - ;PRINT, "-> ", calc_cubic(result[0], c), calc_cubic(result[1], c), calc_cubic(result[2], c) - ENDIF ELSE result = FZ_ROOTS(C) - - w1[i] = result[0] - w2[i] = result[1] - IF KEYWORD_SET(epar) OR KEYWORD_SET(gradp) THEN w3[i] = result[2] - ENDFOR - - RETURN, {mu:mu, sparsperp:sparsperp, s:s, w1:w1, w2:w2, w3:w3} -END diff --git a/examples/em-drift/make_d.pro b/examples/em-drift/make_d.pro deleted file mode 100644 index c7944e718f..0000000000 --- a/examples/em-drift/make_d.pro +++ /dev/null @@ -1,26 +0,0 @@ -function make_d, path=path - -if not keyword_set(PATH) then path='' - -ni=collect(path=path, var="Ni") -phi=collect(path=path, var="phi") -ni=ni[2,*,*,*] -phi=phi[2,*,*,*] - - -du=file_import("uedge.grd_beta.nc") -new_zmax=collect(path=path, var="ZMAX");-fraction of 2PI -rho_s = collect(path=path, var="rho_s") -wci = collect(path=path, var="wci") -t_array = collect(path=path, var="t_array") - -zeff = collect(path=path, var="Zeff") -AA = collect(path=path, var="AA") - -old_zmax=new_zmax/(rho_s/du.hthe0) -print, 'new_zmax=', new_zmax, "; old_zmax=", old_zmax - -d={ni_xyzt:ni, phi_xyzt:phi, rho_s:rho_s, zmax:old_zmax, Zeff:zeff, AA:AA, t_array:t_array, wci:wci} - -return,d -end diff --git a/examples/em-drift/res_pproc.pro b/examples/em-drift/res_pproc.pro deleted file mode 100644 index 6292be1a33..0000000000 --- a/examples/em-drift/res_pproc.pro +++ /dev/null @@ -1,165 +0,0 @@ -pro res_pproc, d, du, omega=omega, gamma=gamma, spar, wstar, MANUAL=MANUAL, DEBUG=DEBUG, skip=skip, $ - sparsperp=sparsperp, mu=mu -; -; Postprocessing of resisitive instability test data -; -;-------------------------------------------------------------; - -IF NOT KEYWORD_SET(skip) THEN skip = 15 ; skip first part of the curve - -;tek_color -safe_colors, /first - - nstep=1 - nt=n_elements(d.ni_xyzt[0,0,0,*]) - nx=n_elements(d.ni_xyzt[*,0,0,0]) - ny=n_elements(d.ni_xyzt[0,*,0,0]) - nz=n_elements(d.ni_xyzt[0,0,*,0]) - - - ;;-first calculate geometric and physical quantities - - lZeta=d.zmax*(d.rho_s*1e2)*2*!PI*(du.R0/du.hthe0) ;-toroidal range [cm] - lbNorm=lZeta*(du.BPXY[0,ny/2]/du.BXY[0,ny/2]) ;-binormal coord range [cm] - zPerp=lbNorm*findgen(nz)/(nz-1) ;-binormal coordinate [cm] - - cLight=3e10 ;-speed of light [cm/s] - vTe=4.2e7*sqrt(du.Te_x) ;-electron thermal speed [cm/s] - kperp=2*!PI/max(zPerp) ;-binormal wavenumber, [cm-1] - wce=1.76e7*1e4*du.Bmag ;-electron cyclotron frequency, [rad/s] - - Ln=MEAN(ABS(du.ni0[*,ny/2]/DERIV(du.Rxy[*,ny/2]*1e2,du.ni0[*,ny/2]))) ;-Ni scale length [cm] - vPe=(vTe)^2/(wce*Ln) ;-electron diamagnetic drift speed [cm/s] - wstar=vPe*kPerp - print, "wstar=", wstar, " [rad/s]" - - logLam=24. - alog(sqrt(du.ni_x*1e14)/du.te_x) - nuei=d.zeff*2.91e-6*(du.ni_x*1e14)*logLam/(du.te_x)^1.5 - wci=9.58e3*(1./d.AA)*1e4*du.Bmag ;-ion cyclotron frequency for Mi/mp=d.AA, [rad/s] - - lpar=total((du.bxy/du.bpxy)*du.dlthe)/du.nx ;-[m], average over flux surfaces - kpar=2*!pi/(1e2*lpar) ;cm-1 - spar=(kpar/kperp)^2 * wci * wce / (0.51 * nuei) ;[1/s] - - - wpe=5.64e4*sqrt(1e14*du.ni_x) ;-electron plasma frequency, [rad/s] - mu=(cLight*kperp/wpe)^2 - sperp=(0.51 * nuei) * mu ;[1/s] - print, 'sPerp/wstar=', sperp/wstar - PRINT, "sPar /wstar=", spar / wstar - - sparsperp = spar*sperp / (wstar*wstar) - PRINT, "spar * sperp / wstar^2= ", sparsperp - - print, 'mu=', mu - ;;------------------------------------------------------------------;; - - -!p.title='Resistive drift instability in BOUT' -!p.title=!p.title+', Zeff=' + strtrim(string(d.zeff,f='(f5.1)'),2) - -yscale=2*max([max(d.phi_xyzt[*,20,*,*]), max(d.ni_xyzt[*,20,*,*])]) - -!p.multi=[0,1,2,0,0] - xtit='binormal coord' - ytit='phi' - plot, d.phi_xyzt[0,20,*,nt-1],/xst, xtit=xtit, ytit=ytit, yr=[-1,1]*yscale,/yst,/nod, chars=1.5 - for i=0,nt-1 do oplot, d.phi_xyzt[0,20,*,i], col=1+(i mod 4) - oplot, d.phi_xyzt[0,20,*,nt-1]*0 - - xtit='binormal coord' - ytit='ni' - plot, d.ni_xyzt[0,20,*,nt-1],/xst, xtit=xtit, ytit=ytit, yr=[-1,1]*yscale,/yst,/nod, chars=1.5 - for i=0,nt-1,nStep do oplot, d.ni_xyzt[0,20,*,i], col=1+(i mod 4) - oplot, d.ni_xyzt[0,20,*,nt-1]*0 -!p.multi=0 - - - -WAIT,3 - nt0=skip ;-skip initial part of the curve - maxVal=fltarr(nt-nt0) - for i=nt0,nt-1 do maxVal[i-nt0]=max(d.ni_xyzt[0,20,*,i]) - plot, d.t_array[nt0:*]/d.wci, alog(maxVal), psym=4, syms=3, xtit='time, s', ytit='ln',/yst, chars=1.5 - - if keyword_set(MANUAL) then begin - print, "Mark 2 points on straight line to measure the exponential growth rate" - print, "Click point 1" & mark, x=x1, y=y1 - print, "Click point 2" & mark,x=x2,y=y2 - oplot, [x1,x2], [y1,y2], col=2 - gamma=(y2-y1)/(x2-x1) - endif else begin - xx=d.t_array[nt0:*]/d.wci & yy=ALOG(maxVal) - res=Poly_Fit(xx,yy,1) - oplot, xx, res[0] + res[1]*xx, col=2 - gamma=res[1] - endelse - - print, "gamma=", gamma, " s-1" - ;STOP - -WAIT,3 - xtit="Binormal coordinate, cm" - ytit="Normalized perturbation" - - plot, zPerp, d.ni_xyzt[0,20,*,nt-1]/maxVal[nt-1-nt0],/xst, yr=[-2,2], xtit=xtit, ytit=ytit, chars=1.5 - for i=nt0,nt-1,nStep do begin - oplot, zPerp, d.ni_xyzt[0,20,*,i]/maxVal[i-nt0], col=1+(i mod 4) - wait,0.1 - endfor - - -WAIT,3 -;-track the motion of the peak to infer phase velocity - - xPeak=fltarr(nt-nt0) - - for i=nt0,nt-1 do begin - sig=d.ni_xyzt[0,20,*,i]/maxVal[i-nt0] - zPerp2=min(zPerp) + (max(zPerp)-min(zPerp))*findgen(1001)/1000. - sig2=spline(zPerp,sig,zPerp2) - - iMax=where(sig2 eq max(sig2)) - xPeak[i-nt0]=zPerp2[iMax[0]] - endfor - - - ;-truncate the set to avoid periodic recurrence - if (xPeak[1] lt xPEak[0]) then begin - iValid=where(xPeak ge min(zPerp) and xPeak le xPeak[0]) - endif else begin - iValid=where(xPeak le max(zPerp) and xPeak ge xPeak[0]) - endelse - - xPeak=xPeak(iValid) - tt=d.t_array(iValid)/d.wci - - plot, tt, xPeak, psym=4, syms=3, chars=1.5, xtit='time, s', ytit='Binormal coordinate of wave peak' - - - if keyword_set(MANUAL) then begin - print, "Marking 2 points on the line to measure the phase velocity" - print, "Click point 1" & mark, x=x1, y=y1 - print, "Click point 2" & mark,x=x2,y=y2 - Vphase=abs((y2-y1)/(x2-x1)) - oplot, [x1,x2], [y1,y2], col=3 - endif else begin - xx=tt & yy=xPeak - res=Poly_Fit(xx,yy,1) - oplot, xx, res[0] + res[1]*xx, col=2 - Vphase=abs(res[1]) - endelse - - print, "Vphase=", Vphase, " cm/s" - - - ;-calculate normalized quantities- - omega=Vphase*kperp/wstar ;-normalized real frequency - gamma=gamma/wstar ;-normalized growth rate - print, "Normalized omega=", omega - print, "Normalized gamma=", gamma - wait,3 - -!p.title='' -if keyword_set(DEBUG) then STOP -end diff --git a/examples/em-drift/runcase.sh b/examples/em-drift/runcase.sh deleted file mode 100755 index 73540ba0be..0000000000 --- a/examples/em-drift/runcase.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -MPIEXEC=mpirun -NP=2 - -#-compile/build local executable -make - -#-run the case -echo Running with NP = $NP - -rm -rf data* - -zlist=( 1 2 4 8 16 32 64 128 256 ) - -for zval in ${zlist[@]} -do - mkdir data_${zval} - ln -s data_${zval} data - sed "s/Zeff = 128.0/Zeff = ${zval}.0/g" BOUT.inp > data/BOUT.inp - - if [ $zval -lt 128 ] - then - # reduce time-step. At large times these cases produce noise - sed "s/TIMESTEP = 5e3/TIMESTEP = 1e3/g" data/BOUT.inp > data/tmp - mv data/tmp data/BOUT.inp - fi - - $MPIEXEC -np $NP ./2fluid - rm -f data -done - -#-check the result -#idl runidl.pro diff --git a/examples/em-drift/runidl.pro b/examples/em-drift/runidl.pro deleted file mode 100644 index 8e50b18a6c..0000000000 --- a/examples/em-drift/runidl.pro +++ /dev/null @@ -1,120 +0,0 @@ -;pathnow=getenv('PWD') -;cd,getenv('BOUT_DA') -;.run PDB2IDL/pdb2idl.pro -;.run Plots2D/moment_xyzt.pro -;.run Plots2D/allrms.pro -;cd,pathnow - -.run res_pproc -.run complexRoots -.run make_d - - -WINDOW, 0, XSIZE=500, YSIZE=800 - -du=file_import("uedge.grd_beta.nc") - - -data={zeff:fltarr(9), AA:fltarr(9), gam:fltarr(9), omega:fltarr(9), sparn:fltarr(9)} - - - i=0 - d=make_d(path="data_1") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - - i=1 - d=make_d(path="data_2") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=2 - d=make_d(path="data_4") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=3 - d=make_d(path="data_8") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=4 - d=make_d(path="data_16") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=5 - d=make_d(path="data_32") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=6 - d=make_d(path="data_64") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=7 - d=make_d(path="data_128") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - i=8 - d=make_d(path="data_256") & data.zeff[i]=d.zeff & data.AA[i]=d.AA - res_pproc, d, du, omega=omega, gamma=gamma, manual=manual, spar, wstar, sparsperp=sparsperp, mu=mu - data.omega[i]=omega & data.gam[i]=gamma & data.sparn[i]=spar/wstar - - getComplexRoots, s, w1 ;-calculate analytic dispersion relation - - d0 = dispersion(mu, sparsperp) - d1 = dispersion(mu, sparsperp, /e) - - ;STOP - - !p.multi=[0,1,2,0,0] - tit="Resistive drift instability in BOUT" - xtit="!7r!3!I||!N/!7x!3!I*!N" - ytit="Im(!7x/x!I*!N!3)" - plot, data.sparn, data.gam,/xl, psym=4, syms=3, yr=[0,0.5], $ - xtit=xtit, ytit=ytit, tit=tit, chars=1.5 - oplot, s, imaginary(w1), lin=2, col=3 - - tit="Resistive drift instability in BOUT" - xtit="!7r!3!I||!N/!7x!3!I*!N" - ytit="Re(!7x/x!I*!N!3)" - plot, data.sparn, data.omega,/xl, psym=4, syms=3, yr=[0,1.5], $ - xtit=xtit, ytit=ytit, tit=tit, chars=1.5 - oplot, s, float(w1), lin=2, col=3 - !p.multi=0 - - -;-save the picture - ;image=TVRD(/true) - ;file='drift_inst_test.jpg' - ;print, "Saving in file ", file - ;write_jpeg, file, image,/true - - -;-compare with original test results (grendel, 5-feb-2007) - ;RESTORE, 'orig_test2.idl.dat' - ;error1=max(abs(data.gam-gam_orig)/gam_orig) + max(abs(data.omega-omega_orig)/omega_orig) - ;print, "Deviation from original test result is" , error1*1e2, " %" - - -;-compare results with analytic answer - arg=data.sparn - gval=INTERPOL(imaginary(w1),s,arg) - oval=INTERPOL(float(w1),s,arg) - error2=MAX(abs(gval-data.gam)/gval) + MAX(abs(oval-data.omega)/oval) - print, "Deviation from analytic result is" , error2*1e2, " %" - - - - for i=10,0,-1 do begin print, "exiting in ", i, " seconds" & wait,1 - - if (error1 gt 1e-4) then status=1 else status=0 - ;status=0 - print, 'status=', status - -STOP -exit, status=status diff --git a/examples/em-drift/uedge.grd_beta.nc b/examples/em-drift/uedge.grd_beta.nc deleted file mode 100644 index 5809045dc8..0000000000 Binary files a/examples/em-drift/uedge.grd_beta.nc and /dev/null differ diff --git a/examples/em-drift/uedge.grd_beta.pdb b/examples/em-drift/uedge.grd_beta.pdb deleted file mode 100644 index f7c588946b..0000000000 Binary files a/examples/em-drift/uedge.grd_beta.pdb and /dev/null differ diff --git a/examples/fci-wave-logn/.gitignore b/examples/fci-wave-logn/.gitignore deleted file mode 100644 index a7303d2660..0000000000 --- a/examples/fci-wave-logn/.gitignore +++ /dev/null @@ -1 +0,0 @@ -fci-wave \ No newline at end of file diff --git a/examples/fci-wave-logn/CMakeLists.txt b/examples/fci-wave-logn/CMakeLists.txt deleted file mode 100644 index b49a070427..0000000000 --- a/examples/fci-wave-logn/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(fci-wave-logn LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(fci-wave-logn - SOURCES fci-wave.cxx - DATA_DIRS boundary div-integrate expanded) diff --git a/examples/fci-wave-logn/README.md b/examples/fci-wave-logn/README.md deleted file mode 100644 index 0775d0c058..0000000000 --- a/examples/fci-wave-logn/README.md +++ /dev/null @@ -1,54 +0,0 @@ -Wave equation in tokamak geometry using FCI scheme -================================================== - -The input file for this test can be generated using Zoidberg, -by running `tokamak.py` in the `examples/zoidberg` directory. -It is a MAST double-null equilibrium. - -Two equations are evolved, the density and the momentum: - - dn/dt = -Div(n*v) - - d/dt(v) = -v * Grad_par(v) - Grad_par(n)/n + Grad2_par2(v) - -The logarithm of the density is evolved, allowing the `Grad_par(n)/n` -term to be written as `Grad_par(logn)`. - -There are switches to control: - -* Whether the density equation is solved by integrating the flux - or by expanding the expression and using `logn` directly. - - -Some alternative models are implemented in the `fci-wave` -example, which is formulated as a momentum equation rather than a -velocity equation. - -Zero-flux boundaries --------------------- - -These cases set the velocity to zero at the boundaries, and so should -conserve total mass. - -Expanded form of density equation *This is expected to fail*: - - - mpirun -np 2 ./fci-wave -d expanded - - -Area integration calculation of divergence: - - mpirun -np 2 ./fci-wave -d div-integrate - -There is an analysis script in the `fci-wave` directory -which will plot the total mass as a function of time. - -Outgoing flow boundaries ------------------------- - -These set the parallel flow speed to +/- 1 on the boundaries. - -Area integration: - - mpirun -np 2 ./fci-wave -d boundary - diff --git a/examples/fci-wave-logn/boundary/BOUT.inp b/examples/fci-wave-logn/boundary/BOUT.inp deleted file mode 100644 index 0632aa949b..0000000000 --- a/examples/fci-wave-logn/boundary/BOUT.inp +++ /dev/null @@ -1,44 +0,0 @@ -# -# - -nout = 100 -timestep = 0.1 - -grid = "tokamak.fci.nc" - -MYG = 1 -NXPE = 1 - -[mesh:paralleltransform] - -type = fci - -[fciwave] - -expand_divergence = false - -background = 1e-06 # Background density - -[all] -bndry_par_all = parallel_neumann_o2 -bndry_all = neumann - -[n] - -zl = z / (2*pi) -function = fciwave:background + 1e-3*exp(-((x-0.7)/0.1)^2 - ((zl-0.3)/0.1)^2) - -bndry_par_yup = parallel_neumann_o2 -bndry_par_ydown = parallel_neumann_o2 - -[logn] - -function = log(n:function) - -bndry_par_yup = parallel_neumann_o2 -bndry_par_ydown = parallel_neumann_o2 - -[v] - -bndry_par_yup = parallel_dirichlet(+1.0) -bndry_par_ydown = parallel_dirichlet(-1.0) diff --git a/examples/fci-wave-logn/div-integrate/BOUT.inp b/examples/fci-wave-logn/div-integrate/BOUT.inp deleted file mode 100644 index 66bdbce5f2..0000000000 --- a/examples/fci-wave-logn/div-integrate/BOUT.inp +++ /dev/null @@ -1,43 +0,0 @@ -# -# - -nout = 100 -timestep = 0.1 - -grid = "tokamak.fci.nc" - -MYG = 1 -NXPE = 1 - -[mesh:paralleltransform] - -type = fci - -[fciwave] - -expand_divergence = false - -background = 1e-06 # Background density - -[all] -bndry_par_all = parallel_neumann_o2 -bndry_all = neumann - -[n] - -zl = z / (2*pi) -function = fciwave:background + 1e-3*exp(-((x-0.7)/0.1)^2 - ((zl-0.3)/0.1)^2) - -bndry_par_yup = parallel_neumann_o2 -bndry_par_ydown = parallel_neumann_o2 - -[logn] - -function = log(n:function) - -bndry_par_yup = parallel_neumann_o2 -bndry_par_ydown = parallel_neumann_o2 - -[v] - -bndry_par_all = parallel_dirichlet diff --git a/examples/fci-wave-logn/expanded/BOUT.inp b/examples/fci-wave-logn/expanded/BOUT.inp deleted file mode 100644 index e084511d24..0000000000 --- a/examples/fci-wave-logn/expanded/BOUT.inp +++ /dev/null @@ -1,43 +0,0 @@ -# -# - -nout = 100 -timestep = 0.1 - -grid = "tokamak.fci.nc" - -MYG = 1 -NXPE = 1 - -[mesh:paralleltransform] - -type = fci - -[fciwave] - -expand_divergence = true - -background = 1e-06 # Background density - -[all] -bndry_par_all = parallel_neumann_o2 -bndry_all = neumann - -[n] - -zl = z / (2*pi) -function = fciwave:background + 1e-3*exp(-((x-0.7)/0.1)^2 - ((zl-0.3)/0.1)^2) - -bndry_par_yup = parallel_neumann_o2 -bndry_par_ydown = parallel_neumann_o2 - -[logn] - -function = log(n:function) - -bndry_par_yup = parallel_neumann_o2 -bndry_par_ydown = parallel_neumann_o2 - -[v] - -bndry_par_all = parallel_dirichlet diff --git a/examples/fci-wave-logn/fci-wave.cxx b/examples/fci-wave-logn/fci-wave.cxx deleted file mode 100644 index 2ea9048421..0000000000 --- a/examples/fci-wave-logn/fci-wave.cxx +++ /dev/null @@ -1,139 +0,0 @@ - -#include "bout/physicsmodel.hxx" - -class FCIwave : public PhysicsModel { -private: - Field3D logn, v; //< Evolving density, momentum - Field3D n; - - Field3D Bxyz; ///< Total magnetic field - - bool expand_divergence; - BoutReal background; ///< background density floor - BoutReal log_background; // Log(background) - - /// Parallel divergence, using integration over projected cells - Field3D Div_par_integrate(const Field3D& f) { - Field3D f_B = f / Bxyz; - - f_B.splitParallelSlices(); - mesh->getCoordinates()->getParallelTransform().integrateParallelSlices(f_B); - - // integrateParallelSlices replaces all yup/down points, so the boundary conditions - // now need to be applied. If Bxyz has neumann parallel boundary conditions - // then the boundary condition is simpler since f = 0 gives f_B=0 boundary condition. - - /// Loop over the mesh boundary regions - for (const auto& reg : mesh->getBoundariesPar()) { - Field3D& f_B_next = f_B.ynext(reg->dir); - const Field3D& f_next = f.ynext(reg->dir); - const Field3D& B_next = Bxyz.ynext(reg->dir); - - for (reg->first(); !reg->isDone(); reg->next()) { - f_B_next(reg->x, reg->y + reg->dir, reg->z) = - f_next(reg->x, reg->y + reg->dir, reg->z) - / B_next(reg->x, reg->y + reg->dir, reg->z); - } - } - - Field3D result; - result.allocate(); - - Coordinates* coord = mesh->getCoordinates(); - - for (auto i : result.getRegion(RGN_NOBNDRY)) { - result[i] = Bxyz[i] * (f_B.yup()[i.yp()] - f_B.ydown()[i.ym()]) - / (2. * coord->dy[i] * sqrt(coord->g_22[i])); - - if (!finite(result[i])) { - output.write("[{:d},{:d},{:d}]: {:e}, {:e} -> {:e}\n", i.x(), i.y(), i.z(), - f_B.yup()[i.yp()], f_B.ydown()[i.ym()], result[i]); - } - } - - return result; - } - -protected: - int init(bool UNUSED(restarting)) override { - - // Get the magnetic field - mesh->get(Bxyz, "B"); - - // Neumann boundaries simplifies parallel derivatives - Bxyz.applyBoundary("neumann"); - Bxyz.applyParallelBoundary("parallel_neumann_o2"); - SAVE_ONCE(Bxyz); - - Options::getRoot()->getSection("fciwave")->get("expand_divergence", expand_divergence, - true); - Options::getRoot()->getSection("fciwave")->get("background", background, 1e-6); - log_background = log(background); - - SOLVE_FOR2(logn, v); - - SAVE_REPEAT(n); - - SAVE_REPEAT2(ddt(logn), ddt(v)); - - return 0; - } - - int rhs(BoutReal UNUSED(t)) override { - mesh->communicate(logn, v); - - // Boundary condition applied to log(n) to prevent negative densities - logn.applyParallelBoundary(); - v.applyParallelBoundary(); - - n = exp(logn); - - // Momentum - ddt(v) = -v * Grad_par(v) - Grad_par(logn) + Grad2_par2(v); - - if (expand_divergence) { - // Split the divergence of flux into two terms - ddt(logn) = -v * Grad_par(logn) - Div_par(v); - - } else { - // Calculate the flux divergence using Div_par_integrate - - Field3D nv = n * v; - nv.splitParallelSlices(); - for (const auto& reg : mesh->getBoundariesPar()) { - Field3D& nv_next = nv.ynext(reg->dir); - nv_next.allocate(); - - const Field3D& logn_next = logn.ynext(reg->dir); - const Field3D& v_next = v.ynext(reg->dir); - - for (reg->first(); !reg->isDone(); reg->next()) { - BoutReal n_b = exp(0.5 - * (logn_next(reg->x, reg->y + reg->dir, reg->z) - + logn(reg->x, reg->y, reg->z))); - BoutReal v_b = - 0.5 - * (v_next(reg->x, reg->y + reg->dir, reg->z) + v(reg->x, reg->y, reg->z)); - - nv_next(reg->x, reg->y + reg->dir, reg->z) = - 2. * n_b * v_b - nv(reg->x, reg->y, reg->z); - } - } - - // Logarithm of density - ddt(logn) = -Div_par_integrate(nv) / floor(n, background); - - // Apply a soft floor to the density - // Hard floors (setting ddt = 0) can slow convergence of solver - for (auto i : logn.getRegion(RGN_NOBNDRY)) { - if (ddt(logn)[i] < 0.0) { - ddt(logn)[i] *= (1. - exp(log_background - logn[i])); - } - } - } - - return 0; - } -}; - -BOUTMAIN(FCIwave); diff --git a/examples/fci-wave/fci-wave.cxx b/examples/fci-wave/fci-wave.cxx index 2fd383ed3f..9f8bb18b8f 100644 --- a/examples/fci-wave/fci-wave.cxx +++ b/examples/fci-wave/fci-wave.cxx @@ -1,4 +1,5 @@ +#include "bout/parallel_boundary_region.hxx" #include "bout/physicsmodel.hxx" class FCIwave : public PhysicsModel { @@ -31,9 +32,9 @@ class FCIwave : public PhysicsModel { const Field3D& B_next = Bxyz.ynext(reg->dir); for (reg->first(); !reg->isDone(); reg->next()) { - f_B_next(reg->x, reg->y + reg->dir, reg->z) = - f_next(reg->x, reg->y + reg->dir, reg->z) - / B_next(reg->x, reg->y + reg->dir, reg->z); + f_B_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) = + f_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) + / B_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()); } } @@ -131,16 +132,21 @@ class FCIwave : public PhysicsModel { // Note: If evolving density, this should interpolate logn // but neumann boundaries are used here anyway. BoutReal n_b = - 0.5 * (n_next(reg->x, reg->y + reg->dir, reg->z) + n(reg->x, reg->y, reg->z)); + 0.5 + * (n_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) + + n(reg->ind().x(), reg->ind().y(), reg->ind().z())); // Velocity at the boundary BoutReal v_b = - 0.5 * (v_next(reg->x, reg->y + reg->dir, reg->z) + v(reg->x, reg->y, reg->z)); + 0.5 + * (v_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) + + v(reg->ind().x(), reg->ind().y(), reg->ind().z())); - nv_next(reg->x, reg->y + reg->dir, reg->z) = - 2. * n_b * v_b - nv(reg->x, reg->y, reg->z); + nv_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) = + 2. * n_b * v_b - nv(reg->ind().x(), reg->ind().y(), reg->ind().z()); - momflux_next(reg->x, reg->y + reg->dir, reg->z) = - 2. * n_b * v_b * v_b - momflux(reg->x, reg->y, reg->z); + momflux_next(reg->ind().x(), reg->ind().y() + reg->dir, reg->ind().z()) = + 2. * n_b * v_b * v_b + - momflux(reg->ind().x(), reg->ind().y(), reg->ind().z()); } } diff --git a/examples/gas-compress/gas_compress.cxx b/examples/gas-compress/gas_compress.cxx index 812f17b4c0..e9483e30aa 100644 --- a/examples/gas-compress/gas_compress.cxx +++ b/examples/gas-compress/gas_compress.cxx @@ -25,8 +25,6 @@ int GasCompress::init(bool restarting) { sub_initial = options["sub_initial"].withDefault(false); - V.y.setLocation(CELL_YLOW); // Stagger - // Set evolving variables solver->add(N, "density", "description"); @@ -55,9 +53,9 @@ int GasCompress::rhs(BoutReal UNUSED(time)) { if (sub_initial) { // Subtract force balance of initial profiles - ddt(V) = -V_dot_Grad(V, V) - Grad(P - P0, CELL_VSHIFT) / N; + ddt(V) = -V_dot_Grad(V, V) - Grad(P - P0) / N; } else { - ddt(V) = -V_dot_Grad(V, V) - Grad(P, CELL_VSHIFT) / N + g; + ddt(V) = -V_dot_Grad(V, V) - Grad(P) / N + g; } if (include_viscosity) { diff --git a/examples/gas-compress/gas_compress.hxx b/examples/gas-compress/gas_compress.hxx index 05b5823f29..86393ac0e0 100644 --- a/examples/gas-compress/gas_compress.hxx +++ b/examples/gas-compress/gas_compress.hxx @@ -2,8 +2,8 @@ class GasCompress : public PhysicsModel { protected: - int init(bool restarting); - int rhs(BoutReal t); + int init(bool restarting) override; + int rhs(BoutReal time) override; private: // Evolving variables diff --git a/examples/gas-compress/rayleigh-taylor/BOUT.inp b/examples/gas-compress/rayleigh-taylor/BOUT.inp index b56e0ca51f..3da8fe9326 100644 --- a/examples/gas-compress/rayleigh-taylor/BOUT.inp +++ b/examples/gas-compress/rayleigh-taylor/BOUT.inp @@ -9,11 +9,11 @@ timestep = 0.1 # time between outputs twistshift = false # use twist-shift condition? -MZ = 129 # number of points in z direction +MZ = 128 # number of points in z direction ZMIN = 0.0 ZMAX = 0.031831 # 0.2 NOTE: Length of y is 1 and this *2pi is Z length -MXG = 0 +MXG = 2 MYG = 2 grid = "rt.grd.nc" @@ -66,12 +66,12 @@ scale = 0.0 # default size of initial perturbations # neumann = zero gradient # most variables free at boundaries +bndry_xin = neumann +bndry_xout = neumann bndry_all = free_o3 [v] -bndry_all = dirichlet - [vy] # evolving contravariant components scale = 0.001 # initial velocity perturbation diff --git a/examples/gas-compress/sod-shock/BOUT.inp b/examples/gas-compress/sod-shock/BOUT.inp index 678db6416c..c7bd89fd6d 100644 --- a/examples/gas-compress/sod-shock/BOUT.inp +++ b/examples/gas-compress/sod-shock/BOUT.inp @@ -16,8 +16,6 @@ MYG = 2 grid = "sod.grd.nc" # Grid file -StaggerGrids = false - ################################################## # derivative methods @@ -63,4 +61,3 @@ v0_multiply = -1.0 scale = 0.0 # default size of initial perturbations function = gauss(y - pi, 0.1*pi) * sin(z) bndry_all = neumann # Set all boundaries to Neumann -bndry_target = neumann_2ndorder diff --git a/examples/gravity_reduced/.gitignore b/examples/gravity_reduced/.gitignore deleted file mode 100644 index 99931b2c71..0000000000 --- a/examples/gravity_reduced/.gitignore +++ /dev/null @@ -1 +0,0 @@ -gravity_reduced \ No newline at end of file diff --git a/examples/gravity_reduced/CMakeLists.txt b/examples/gravity_reduced/CMakeLists.txt deleted file mode 100644 index 967472d4e6..0000000000 --- a/examples/gravity_reduced/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(gravity_reduced LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(gravity_reduced - SOURCES gravity_reduced.cxx - EXTRA_FILES slab_grid.nc) diff --git a/examples/gravity_reduced/README.md b/examples/gravity_reduced/README.md deleted file mode 100644 index 53c1a322b1..0000000000 --- a/examples/gravity_reduced/README.md +++ /dev/null @@ -1,8 +0,0 @@ -Flute-Reduced with Gravity -========================== - -Flute-Reduced MHD - including gravity term instead of curvature. Basically the -same as Hazeltine-Meiss but different normalisations and have gravity intead of -curvature. Evolving Vorticity U, Parallel electric field Psi, Parallel velocity -Vpar, Pressure p, and density rho. Have included compressional terms in Vpar and -in pressure and density evolution equations. diff --git a/examples/gravity_reduced/data/BOUT.inp b/examples/gravity_reduced/data/BOUT.inp deleted file mode 100644 index 7c83db2126..0000000000 --- a/examples/gravity_reduced/data/BOUT.inp +++ /dev/null @@ -1,141 +0,0 @@ -# settings file for BOUT++ -# -# Gravity driven ballooning mode (reduced MHD) -# -# By default everything in NetCDF. -# To change to PDB format, change the settings to -# grid="data/slab.6b5.r1.pdb" -# dump_format = "pdb" - -################################################## -# settings used by the core code - -nout = 200 # number of time-steps -timestep = 0.1 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 32 # number of points in z direction (2^n) - - -zperiod = 1 -ZMIN = -0.5 -ZMAX = 0.5 - - -MXG = 2 -MYG = 2 - -grid = "slab_grid.nc" - -non_uniform = false - -[mesh] -staggergrids = false # Use staggered grids (EXPERIMENTAL) - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 -second = C2 -upwind = W3 - -[mesh:ddy] - -first = C2 -second = C2 -upwind = W3 - -[mesh:ddz] - -first = FFT -second = FFT -upwind = W3 - -################################################## -# Solver settings - -[solver] - -#mudq = 42 -#mldq = 42 -#mukeep = 6 -#mlkeep = 6 -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance - -#type=splitrk -#timestep = 1e-3 - -################################################## -# settings for gravity reduced MHD model - -[gravity] - -nonlinear = false # include non-linear terms? - -Lz = 0.06 # Length of the box in Z - -gamma = 1.666667 - -mu_0 = 1.0 - - - -## Viscosity - -viscos_par = 0.1 # Parallel viscosity (< 0 = none) #(try 0.1) -viscos_perp = -1.0 # Perpendicular - - -[laplace] -inner_boundary_flags = 0 -outer_boundary_flags = 0 - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -bndry_all = neumann # Zero-gradient on all boundaries - -[U] -bndry_yup = relax(dirichlet) -bndry_ydown = relax(dirichlet) - -[Vpar] -bndry_yup = dirichlet -bndry_ydown = dirichlet - -[phi] -bndry_xin = none -bndry_xout = none -bndry_yup = dirichlet -bndry_ydown = dirichlet - - -[psi] -bndry_xin = constlaplace -bndry_xout = constlaplace - -[jpar] -bndry_xin = neumann -bndry_xout = neumann -bndry_yup = neumann -bndry_ydown = neumann diff --git a/examples/gravity_reduced/generate.pro b/examples/gravity_reduced/generate.pro deleted file mode 100644 index 73466276ab..0000000000 --- a/examples/gravity_reduced/generate.pro +++ /dev/null @@ -1,538 +0,0 @@ -; SLAB GRID GENERATOR. EVERYTHING IN SI UNITS -; -; NX - number of points in radial direction. -; For radial need nx = m * nproc + 4 -; -; NY - Number of points along field-line -; -; NZ - Number of points in symmetry direction. -; Set in options file, not grid -; -; LX - Height of box [m] -; LY - Length of box along field-line [m] -; LZ - Length of box in symmetry direction [m] -; -; p0 - Maximum pressure [Pa] -; pedge - Minimum pressure [Pa] -; pwidth - Width of pedestal [m] -; -; density - Constant density everywhere [m^-3] -; B0 - Constant B field (must be non-zero) [T] - -PRO generate - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; SETTINGS - - nx = 32 ;64 - ny = 32 ;64 - nz = 33 - output = "slab_grid.nc" - - Lx = 0.6 ;0.6 is standard, have increased it to move edges of box away from interesting region - Ly = 5.4 - Lz = 0.06 - - xmin=0.3-Lx/2.0 - - ; Grid spacing - dx = FLTARR(nx, ny) + Lx / FLOAT(nx-1) - dy = FLTARR(nx, ny) + Ly / FLOAT(ny-1) - - ; pedge = p0 / 100. ; Just need to prevent negatives - ; pwidth = Lx / 10. - - ; density = 1e20 ; NOTE: SHOULD BE SAME AS IN BOUT.inp FILE - ; B0 = 0.01 - - ; gravity_sin = 2e4;1e4 ; sin component of gravity [m/s^2] - ; gravity_cos = 0.0;1e4 ; cos component of gravity [m/s^2] - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - MU0 = 1.0 ;4.e-7*!PI - - ; rho = density * 2.0*1.6726e-27 ; Deuterium mass density - - F2D = FLTARR(nx, ny) - F3D = FLTARR(nx,ny,nz) - - - rho_a = 2.3 - l_rho0 = 2.5 - rho_b = 0.5 - x_rho0 = 0.6 - l_rho1 = 0.4 - p0 = 0.3 - p_b = 0.8 - x_p0 = 0.15 - l_p1 = 0.2 - gravity = 0.25 ;0.21 - - s = 0.0 ;shear -; Ls = 1.0/s ;inverse shear - xs0 = 0.32 ;position of straight field line - - ; Set pressure profile. Function of x only - x = Lx * FINDGEN(nx) / FLOAT(nx-1) + xmin ; Distance [m] - y = Ly * FINDGEN(ny) / FLOAT(ny-1) -Ly/2; - z = Lz * FINDGEN(nz) / FLOAT(nz-1) -Lz/2; -; z = Lz * FINDGEN(nz) / FLOAT(nz-1); - - B=FLTARR(nx) - Bz_prof=FLTARR(nx) - By_prof=FLTARR(nx) - Bx_prof=FLTARR(nx) - -;--------initialise fields------------------------------------------------------------------- - - p = p0*1 + p0*p_b*exp(-(x-x_p0)*(x-x_p0)/(l_p1*l_p1)) - - rho = rho_a*exp(-x/l_rho0) + rho_b*exp(-(x-x_rho0)*(x-x_rho0)/(l_rho1*l_rho1)) - - - ; Put into 2D function - pressure = F2D - FOR i=0, nx-1 DO pressure[i,*] = p[i] - - density = F2D - for i=0, nx-1 DO density[i,*] = rho[i] - - - ;magnetic field - - for i =0,nx-1 do B[i] =sqrt(mu0*(1+2*p[0] - 2*p[i] -2*gravity*(-rho_a*l_rho0*(exp(-x[i]/l_rho0) -1) + rho_b*l_rho1*(sqrt(!PI))*0.5*(erf((x[i]-x_rho0)/l_rho1) - erf(-x_rho0/l_rho1))))) - - - modB=F2D - for i = 0, nx-1 DO modB[i,*] = B[i] - - - zmag = fltarr(nx) - norm = fltarr(nx) - - FOR i =0, nx-1 DO BEGIN - - zmag[i] = (x[i]-xs0)*s - norm[i] = sqrt(1+zmag[i]*zmag[i]) - - Bx_prof[i] = 0.0 - By_prof[i] = B[i]/norm[i] - Bz_prof[i] = B[i]*zmag[i]/norm[i] - ENDFOR - - - Bx=F2D - By=F2D - Bz=F2D - - for i=0, nx-1 DO By[i,*] = By_prof[i] - for i=0, nx-1 DO Bx[i,*] = Bx_prof[i] - for i=0, nx-1 DO Bz[i,*] = Bz_prof[i] - - - - Jpar0=F2D - jpar=fltarr(nx) - - for i=0, nx-1 DO jpar[i] = s*B[i]/(MU0*(1+s*s*x[i]*x[i])) - - for i=0, nx-1 DO Jpar0[i,*] = jpar[i] -;-------------------------------------------------------------------------------------------------- - - - -;------------initialise velocities------------------------------------------------------------------ - Vx0 = 1.0E-3 - Vy0 = 1.0E-3 - Vz0 = 1.0E-3 - Vpar0= 1.0E-3 - x0 = .3112 - ax1 = 138.66885708 - kz = 104.7197551196597 - ky = 0.7265193360796418 - beta = 0.59089827 - delta = 1.861762821403754 - - - - Vx=F3D - Vy=F3D - Vz=F3D - - V0x=0 - V0y=0 - V0z=0 - - - for i=0,nx-1 do begin - for j=0,ny-1 do begin - for k=0,nz-1 do begin - Vx(i,j,k) = Vx0 * exp(-ax1*(x[i]-x0)*(x[i]-x0)) * cos(kz*(z[k]-s*(x[i]-xs0)*y[j])) * (1-cos(ky*y[j])/cos(ky*ly/2))/(1-1/cos(ky*ly/2)) - endfor - endfor - endfor - - - - - for i=0,nx-1 do begin - for j=0,ny-1 do begin - for k=0,nz-1 do begin - Vz(i,j,k) = Vz0 * exp(-ax1*(x[i]-x0)*(x[i]-x0))*( 2.0* ax1*(x[i]-x0) * sin(kz*(z[k]-s*(x[i]-xs0)*y[j])) *(1/ky) +s*y[j]*cos(kz*(z[k]-s*(x[i]-xs0)*y[j])))* (1-cos(ky*y(j))/cos(ky*ly/2))/(1-1/cos(ky*ly/2)) - endfor - endfor - endfor - - for i=0,nx-1 do begin - for j=0,ny-1 do begin - for k=0,nz-1 do begin - - Vy(i,j,k) = Vy0*(-(s*(x[i]-xs0)/Vz0)*Vz(i,j,k) + sqrt(1+s*s*(x[i]-xs0)*(x[i]-xs0))* exp(- ax1 * (x[i] - x0) * (x[i] - x0)) * cos(kz*(z[k]-s*(x[i]-xs0)*y[j])) *2* delta / ly * ( tan(ky * (ly/2)) / (ky * (ly/2)) * (y[j] + (ly/2)) - (sin(ky * y[j]) + sin(ky * (ly/2))) / (ky * cos(ky * (ly/2)) )) )/ (1. - 1. / cos(ky * (ly/2))) -; Vy(i,j,k) = Vy0 * exp(- ax1 * (x[i] - x0) * (x[i] - x0)) * cos(kz * z[k]) *2* delta / ly * ( tan(ky * (ly/2)) / (ky * (ly/2)) * (y[j] + (ly/2)) - (sin(ky * y[j]) + sin(ky * (ly/2))) / (ky * cos(ky * (ly/2)) )) / (1. - 1. / cos(ky * (ly/2))) - endfor - endfor - endfor - - - Vpar=F3D - - for i=0,nx-1 do begin - for j=0,ny-1 do begin - for k=0,nz-1 do begin - - Vpar(i,j,k) = Vpar0*(exp(- ax1 * (x[i] - x0) * (x[i] - x0)) * cos(kz*(z[k]-s*(x[i]-xs0)*y[j])) *2* delta / ly * ( tan(ky * (ly/2)) / (ky * (ly/2)) * (y[j] + (ly/2)) - (sin(ky * y[j]) + sin(ky * (ly/2))) / (ky * cos(ky * (ly/2)) )) )/ (1. - 1. / cos(ky * (ly/2))) - - endfor - endfor - endfor - - - phi=F3D - - for i=0,nx-1 do begin - for j=0,ny-1 do begin - for k=0,nz-1 do begin - phi(i,j,k) = -Vx0 * exp(-ax1*(x[i]-x0)*(x[i]-x0)) *(1.0/kz) *sin(kz*(z[k]-s*(x[i]-xs0)*y[j])) * (1-cos(ky*y[j])/cos(ky*ly/2))/(1-1/cos(ky*ly/2)) - endfor - endfor - endfor - -;----------------------------------------------------------------------------------------------------------------------- - -;------------Funk around with FFTs so that bout knows z variations properly--------------------------------------------- - - nf=fix(nz/2) - - IF nf mod 2 NE 1 then nf=nf-1 - - vfx=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fx = FFT(reform(Vx[i,j,*])) - - Vfx[i,j,0] = real_part(fx[0]) - for k=0,(nf-1)/2 - 1 do begin - Vfx[i,j,2*k+1] = real_part(fx[k+1]) - Vfx[i,j,2*k+2] = imaginary(fx[k+1]) - endfor - endfor - endfor - - - vfy=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fy = FFT(reform(Vy[i,j,*])) - - Vfy[i,j,0] = real_part(fy[0]) - for k=0,(nf-1)/2 - 1 do begin - Vfy[i,j,2*k+1] = real_part(fy[k+1]) - Vfy[i,j,2*k+2] = imaginary(fy[k+1]) - endfor - endfor - endfor - - - vfz=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fz = FFT(reform(Vz[i,j,*])) - - Vfz[i,j,0] = real_part(fz[0]) - for k=0,(nf-1)/2 - 1 do begin - Vfz[i,j,2*k+1] = real_part(fz[k+1]) - Vfz[i,j,2*k+2] = imaginary(fz[k+1]) - endfor - endfor - endfor - - - - vfpar=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - for k=0,nf-1 do begin - vpar[i,j,k]= 0 - - endfor - endfor - endfor - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fpar = FFT(reform(Vpar[i,j,*])) - - Vfpar[i,j,0] = real_part(fpar[0]) - k=0 - ;for k=0,(nf-1)/2 - 1 do begin - Vfpar[i,j,2*k+1] = real_part(fpar[k+1]) - Vfpar[i,j,2*k+2] = imaginary(fpar[k+1]) - ;endfor - endfor - endfor - - phif=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - for k=0,nf-1 do begin - phif[i,j,k]= 0 - - endfor - endfor - endfor - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fphi = FFT(reform(phi[i,j,*])) - - phif[i,j,0] = real_part(fphi[0]) - k=0 - ;for k=0,(nf-1)/2 - 1 do begin - phif[i,j,2*k+1] = real_part(fphi[k+1]) - phif[i,j,2*k+2] = imaginary(fphi[k+1]) - ;endfor - endfor - endfor - -;------------------------------------------------------------------------------------------------------------------------ -;-----------gravity---------------------------------------------------------------------------------------------------- - G = fltarr(nx) - G = -gravity*x - - Garr=F2D - FOR i=0, nx-1 DO Garr[i,*] = G[i] - - -;--------------------------initialise vorticity-------------------------------------------------------- - - U0=F3D - fst=F3D - sec=F3D - thd=F3D - fth=F3D - fvt=F3D - - - for i=0,nx-1 do begin - for j=0,ny-1 do begin - for k=0,nz-1 do begin - fst[i,j,k] = 2*ax1*x[i]*x[i]*s*Vy[i,j,k] - 2*s*ax1*x[i]*Vz[i,j,k] + kz*Vx[i,j,k]*tan(kz*(z[k]-s*(x[i]-xs0)*y[j])) - sec[i,j,k] = (-(1/kz)*4*ax1*x[i]*x[i]*s*s + kz*s*s*s*s*x[i]*x[i]*y[j]*y[j] + s*s*kz*(x[i]*x[i] + y[j]*y[j]) * 2*ax1/kz)*sin(kz*(z[k]-s*(x[i]-xs0)*y[j])) - thd[i,j,k] = (-2*ax1*s*x[i]*y[j]*(1+s*s*x[i]*x[i]) +s*s*s*x[i]*y[j] ) * cos(kz*(z[k]-s*(x[i]-xs0)*y[j])) - fth[i,j,k] = sqrt(1+s*s*x[i]*x[i])*s*s*x[i]*y[j]*delta*(2*kz/(ky*ly))*sin(kz*(z[k]-s*(x[i]-xs0)*y[j])) + s*s*s*x[i]*x[i]*(2*delta/(ky*ly*sqrt(1+s*s*x[i]*x[i])))*cos(kz*(z[k]-s*(x[i]-xs0)*y[j])) - fvt[i,j,k] = s*x[i]*cos(kz*(z[k]-s*(x[i]-xs0)*y[j])) - endfor - endfor - endfor - - - - for i=0, nx-1 do begin - for j=0, ny-1 do begin - for k=0, nz-1 do begin - - U0[i,j,k]= ( fst[i,j,k] + exp(-ax1*(x[i]-x0)*(x[i]-x0))*((sec[i,j,k]+thd[i,j,k])*(1 - cos(ky*y[j])/cos(ky*ly/2)) + fth[i,j,k]*((2*y[j]/ly)*tan(ky*ly/2) - sin(ky*y[j])/cos(ky*ly/2)) + fvt[i,j,k]*(ky*sin(ky*y[j])/cos(ky*ly/2)))*(1/(1-1/(cos(ky*ly/2)))) ) / (sqrt(1+s*s*x[i]*x[i])) - - endfor - endfor - endfor - - - Uf=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fu = FFT(reform(U0[i,j,*])) - - Uf[i,j,0] = real_part(fu[0]) - for k=0,(nf-1)/2 - 1 do begin - Uf[i,j,2*k+1] = real_part(fu[k+1]) - Uf[i,j,2*k+2] = imaginary(fu[k+1]) - endfor - endfor - endfor - - -;---------------------------------------------------------------------------------------------------------- -;---------------------------------------------------------------------------------------------------------- -;------------------------------------ Analytical initial perturbations for density, pressure and Psi------ - - -;-----Pressure - - P1 = F3D - - for i =0, nx-1 do begin - for j = 0, ny-1 do begin - for k = 0, nz-1 do begin - P1[i,j,k] = ((1./kz)*(-p0)*p_b*2.0*(1/(l_p1*l_p1))*(x[i]- x_p0)*exp(-(x[i]-x_p0)*(x[i]-x_p0)/(l_p1*l_p1)) * exp(-ax1*x[i]*x[i])*kz*sin(kz*z[k])*(1-cos(ky*y[j])/cos(ky*ly/2)) - (5./3.)*(p[i]/(1+(5./3.)*p[i]*mu0/(B[i]*B[i])))*( (-(1./kz)*rho[i]*mu0*gravity*(1/(B[i]*B[i]))*exp(-ax1*x[i]*x[i])*sin(kz*z[k])*(1-cos(ky*y[j])/cos(ky*ly/2))) +exp(-ax1*x[i]*x[i])*cos(kz*z[k])*delta*(2./(ky*ly))*(tan(ky*ly/2.)-ky*cos(ky*y[j])/(cos(ky*ly/2.0)))) )/ (1. - 1. / cos(ky * (ly/2))) - endfor - endfor - endfor - - - Pf=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fp = FFT(reform(P1[i,j,*])) - - Pf[i,j,0] = real_part(fp[0]) - for k=0,(nf-1)/2 - 1 do begin - Pf[i,j,2*k+1] = real_part(fp[k+1]) - Pf[i,j,2*k+2] = imaginary(fp[k+1]) - endfor - endfor - endfor - - - -;-----Density - - D1 = F3D - - for i =0, nx-1 do begin - for j = 0, ny-1 do begin - for k = 0, nz-1 do begin - D1[i,j,k] = ((1./kz)*((-rho_a/l_rho0)*exp(-x[i]/l_rho0) - 2.0*rho_b*(1/(l_rho1*l_rho1)))*(x[i]-x_rho0)*exp(-(x[i]-x_rho0)*(x[i]-x_rho0)/(l_rho1*l_rho1)) * exp(-ax1*x[i]*x[i])* kz*sin(kz*z[k])*(1-cos(ky*y[j])/cos(ky*ly/2)) - (rho[i]/(1+(5./3.)*p[i]*mu0/(B[i]*B[i])))*( (-(1./kz)*rho[i]*mu0*gravity*(1/(B[i]*B[i]))*exp(-ax1*x[i]*x[i])*sin(kz*z[k])*(1-cos(ky*y[j])/cos(ky*ly/2))) +exp(-ax1*x[i]*x[i])*cos(kz*z[k])*delta*(2./(ky*ly))*(tan(ky*ly/2.)-ky*cos(ky*y[j])/(cos(ky*ly/2.0)))) )/ (1. - 1. / cos(ky * (ly/2))) - endfor - endfor - endfor - - - Df=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fd = FFT(reform(D1[i,j,*])) - - Df[i,j,0] = real_part(fd[0]) - for k=0,(nf-1)/2 - 1 do begin - Df[i,j,2*k+1] = real_part(fd[k+1]) - Df[i,j,2*k+2] = imaginary(fd[k+1]) - endfor - endfor - endfor - - - - -;-----Psi - - psi1 = F3D - - for i =0, nx-1 do begin - for j = 0, ny-1 do begin - for k = 0, nz-1 do begin - psi1[i,j,k] = -(1./kz)* exp(-ax1*x[i]*x[i])* sin(kz*z[k])*(sin(ky*y[j])/cos(ky*ly/2))/ (1. - 1. / cos(ky * (ly/2))) - endfor - endfor - endfor - - - Psif=fltarr(nx,ny,nf) - - for i=0, nx-1 do begin - for j=0,ny-1 do begin - fpsi = FFT(reform(psi1[i,j,*])) - - psif[i,j,0] = real_part(fpsi[0]) - for k=0,(nf-1)/2 - 1 do begin - psif[i,j,2*k+1] = real_part(fpsi[k+1]) - psif[i,j,2*k+2] = imaginary(fpsi[k+1]) - endfor - endfor - endfor -;------------------------------------------------------------------------------------------------------------------------- - -;---- TOPOLOGY - -; ixseps= -1 ; Domain outside core -> NOT periodic - - ;Ben says define xmesh such that B = grad_z cross grad_x - this basically involves multiplying our xmesh by B. - - - xmeshB = fltarr(nx); - - for i = 0,nx-1 do begin - xmeshB[i] = x[i]*B[i]; - endfor - -;--------------------------- Write to file--------------------------------------------------------------------------- - fp = file_open(output, /create) - - status = file_write(fp, "nx", nx) - status = file_write(fp, "ny", ny) -; status = file_write(fp, "nz", nz) ; Don't write nz if using FFT in Z - - status = file_write(fp, "dx", dx) - status = file_write(fp, "dy", dy) -; status = file_write(fp, "ixseps1", ixseps) -; status = file_write(fp, "ixseps2", ixseps) - - status = file_write(fp, "p0", pressure) - status = file_write(fp, "rho0", density) - status = file_write(fp, "x", xmeshB) - status = file_write(fp, "y", y) - status = file_write(fp, "z", z) - status = file_write(fp, "B0_vec_x", Bx) - status = file_write(fp, "B0_vec_y", By) - status = file_write(fp, "B0_vec_z", Bz) - status = file_write(fp, "v0xtest", Vx) - status = file_write(fp, "v0ytest", Vy) - status = file_write(fp, "v0ztest", Vz) -; status = file_write(fp, "gravity_x", gravityx) - status = file_write(fp, "v0_x", Vfx) - status = file_write(fp, "v0_y", Vfy) ;if want covariant - status = file_write(fp, "v0_z", Vfz) - status = file_write(fp, "G", Garr) - status = file_write(fp, "Jpar0", Jpar0) - status = file_write(fp, "U0_test", U0) - status = file_write(fp, "U0", Uf) - status = file_write(fp, "B0", modB) - status = file_write(fp, "Vpar0", Vfpar) - status = file_write(fp, "psi1", psif) - status = file_write(fp, "rho1", Df) ;if want covariant - status = file_write(fp, "p1", Pf) - status = file_write(fp, "p1test", P1) - status = file_write(fp, "Vpar0test", Vpar) - status = file_write(fp, "psi1test", psi1) - status = file_write(fp, "rho1test", D1) ;if want covariant - status = file_write(fp, "U0test", U0) - status = file_write(fp, "phi0", phif) -; status = file_write(fp, "v0x", Vfx) -; status = file_write(fp, "v0y", Vfy) ;if want contravariant -; status = file_write(fp, "v0z", Vfz) -; status = file_write(fp, "gravity_x", gfx) -; status = file_write(fp, "gravity_x", gravity) - - ; I is integrated shear, and zero here - - file_close, fp -;------------------------------------------------------------------------------------------------------------------------- -END diff --git a/examples/gravity_reduced/gravity_reduced.cxx b/examples/gravity_reduced/gravity_reduced.cxx deleted file mode 100644 index 2d4fb7ec94..0000000000 --- a/examples/gravity_reduced/gravity_reduced.cxx +++ /dev/null @@ -1,259 +0,0 @@ -/******************************************************************************* - * Flute-Reduced MHD - including gravity term instead of curvature - * Basically the same as Hazeltine-Meiss but different normalisations and have gravity intead of curvature. - * Evolving Vorticity U, Parallel electric field Psi, Parallel velocity Vpar, Pressure p, and density rho. - * Have included compressional terms in Vpar and in pressure and density evolution equations. - *******************************************************************************/ - -#include - -#include -#include -#include -#include - -const BoutReal PI = 3.14159265; - -class GravityReduced : public PhysicsModel { -private: - // 2D initial profiles - - Field2D rho0, p0; - Field2D Jpar0; //calculated from equilibrium B field used in bbmhd Jpar0=b.curlB0 - Vector2D B0_vec; - Field2D B0; - Field2D G; //grad G will give us the gravity paramater. - - // Initial perturbations - // Field3D U0; //calculated from intial velocity perturbation used in bbmhd. - Field3D Vpar0; //parallel component of intial velocity perturbation. - Field3D phi0; - - //3D evolving fields - Field3D U, rho, p, Vpar, Psi; - - //Derived variables - Field3D Jpar, phi; - - // Group of fields for communication - FieldGroup comms; - - bool nonlinear; - - // metric coeffictients - Coordinates* coord; - - // parameters - BoutReal mu_0, Gamma; - - BoutReal viscos_par; // Parallel viscosity - BoutReal viscos_perp; // Perpendicular viscosity - BoutReal hyperviscos; // Hyper-viscosity (radial) - - BRACKET_METHOD bm = BRACKET_ARAKAWA; - - /// Solver for inverting Laplacian - std::unique_ptr phiSolver{nullptr}; - - int init(bool restarting) override { - - output << "Solving flute reduced MHD in a slab with gravity\n"; - - //*************** LOAD DATE FROM GRID FILE ******************** - - // GRID_LOAD(U0); - // output << "Loaded U0\n"; - GRID_LOAD(Vpar0); - output << "Loaded Vpar0\n"; - GRID_LOAD(rho0); - output << "Loaded rho0\n"; - GRID_LOAD(p0); - output << "Loaded p0\n"; - GRID_LOAD(Jpar0); - output << "Loaded Jpar0\n"; - GRID_LOAD(G); - G *= 1000.; - output << "Loaded Gravity\n"; - GRID_LOAD(B0_vec); - output << "Loaded B0_vec\n"; - GRID_LOAD(B0); - output << "Loaded B0\n"; - - GRID_LOAD(phi0); - output << "Loaded phi0\n"; - - // Set locations of staggered fields - Psi.setLocation(CELL_YLOW); - Vpar.setLocation(CELL_YLOW); - - // options stuff - - auto globalOptions = Options::root(); - auto options = globalOptions["gravity"]; - - nonlinear = options["nonlinear"].withDefault(false); - - if (nonlinear) { - output << "Solving WITH nonlinear terms\n"; - } else { - output << "Solving WITHOUT nonlinear terms\n"; - } - - phi.setBoundary("phi"); - - viscos_par = options["viscos_par"].withDefault(0.); - viscos_perp = options["viscos_perp"].withDefault(0.); - mu_0 = options["mu_0"].withDefault(1.); - Gamma = options["Gamma"].withDefault(5. / 3.); - - // load metric tensor components - - coord = mesh->getCoordinates(); - - BoutReal Lz; // Size of the Z box - - Lz = options["Lz"].withDefault(1.); - - // Set the metric tensor components to get Lz - coord->g33 = SQ(2. * PI / Lz); - coord->g_33 = 1. / coord->g33; - - /**************** SET EVOLVING VARIABLES *************/ - - // Tell BOUT++ which variables to evolve - // add evolving variables to the communication object - - SOLVE_FOR(rho, p, U, Psi, Vpar); - - if (!restarting) { - // Set initial perturbation - // U = U0; - // U = Delp2(phi0); - U = coord->g11 * D2DX2(phi0) + coord->g33 * D2DZ2(phi0); - Vpar = Vpar0; - } - - //******************Set up comms*************** - - comms.add(rho, p, U, Psi, Vpar); - - // extra variables - comms.add(phi); - - Jpar.setBoundary("jpar"); - - // Add variables to output file - SAVE_REPEAT(phi, Jpar); // Save every output - SAVE_ONCE(G, p0, rho0); - - // Save time derivatives - SAVE_REPEAT(ddt(Psi)); - SAVE_REPEAT(ddt(U)); - SAVE_REPEAT(ddt(rho)); - - // Create a solver for the Laplacian - phiSolver = Laplacian::create(); - - return 0; - } - - int rhs(BoutReal UNUSED(t)) override { - // U = Delp2(phi); - phi = phiSolver->solve(U); // Invert Laplacian - phi.applyBoundary(); // Apply boundary condition in Y - - mesh->communicate(comms); - - Jpar = -(B0 / mu_0) * Delp2(Psi); - Jpar.applyBoundary(); - - mesh->communicate(Jpar); - - //Parallel electric field - ddt(Psi) = -(1 / B0) * Grad_par(B0 * phi, CELL_YLOW); // + 1e-2*Jpar; - - if (nonlinear) { - ddt(Psi) += (1 / B0) * bracket(Psi, B0 * phi, bm) * coord->Bxy; - } - - //Parallel vorticity - - ddt(U) = (SQ(B0) / rho0) * (Grad_par(Jpar / interp_to(B0, CELL_YLOW), CELL_CENTRE)); - - ddt(U) -= (1 / rho0) * bracket(G, rho, bm) * coord->Bxy; - - ddt(U) -= (SQ(B0) / rho0) * bracket(Psi, Jpar0 / B0, bm) * coord->Bxy; - - if (nonlinear) { - ddt(U) -= bracket(phi, U, bm) * coord->Bxy; - - ddt(U) -= (SQ(B0) / rho0) * bracket(Psi, Jpar / B0, bm) * coord->Bxy; - } - - // Viscosity terms - if (viscos_par > 0.0) { - ddt(U) += viscos_par * Grad2_par2(U); // Parallel viscosity - } - - if (viscos_perp > 0.0) { - ddt(U) += viscos_perp * Delp2(U); // Perpendicular viscosity - } - - // Parallel velocity - ddt(Vpar) = bracket(Psi, p0, bm) * coord->Bxy / rho0; - - ddt(Vpar) += -(Grad_par(p, CELL_YLOW)) / rho0; - - ddt(Vpar) += bracket(G, Psi, bm) * coord->Bxy; - - if (nonlinear) { - ddt(Vpar) -= bracket(phi, Vpar, bm) * coord->Bxy; - - ddt(Vpar) += bracket(Psi, p, bm) * coord->Bxy / rho0; - } - - //Pressure - ddt(p) = -bracket(phi, p0, bm); - - ddt(p) += -((Gamma * p0) / (1 + Gamma * p0 * mu_0 / SQ(B0))) - * ((rho0 * mu_0 / SQ(B0)) * bracket(G, phi, bm) * coord->Bxy - + Grad_par(Vpar, CELL_CENTRE) - (Vpar / B0) * Grad_par(B0)); - - if (nonlinear) { - ddt(p) -= bracket(phi, p, bm) * coord->Bxy; - ddt(p) += ((Gamma * p0) / (1 + Gamma * p0 * mu_0 / SQ(B0))) * bracket(Psi, Vpar, bm) - * coord->Bxy; - } - - //Density - ddt(rho) = -bracket(phi, rho0, bm) * coord->Bxy; - - ddt(rho) -= (rho0 / (1 + Gamma * p0 * mu_0 / SQ(B0))) - * ((rho0 * mu_0 / SQ(B0)) * bracket(G, phi, bm) * coord->Bxy - + Grad_par(Vpar, CELL_CENTRE) - bracket(Psi, Vpar, bm) * coord->Bxy - - (Vpar / B0) * Grad_par(B0)); - - if (nonlinear) { - ddt(rho) -= bracket(phi, rho, bm) * coord->Bxy; - ddt(rho) += ((rho0) / (1 + Gamma * p0 * mu_0 / SQ(B0))) * bracket(Psi, Vpar, bm) - * coord->Bxy; - } - - // Iterate over the lower Y boundary - RangeIterator rlow = mesh->iterateBndryLowerY(); - for (rlow.first(); !rlow.isDone(); rlow.next()) { - int x = rlow.ind; - for (int y = 2; y >= 0; y--) { - for (int z = 0; z < mesh->LocalNz; z++) { - ddt(rho)(x, y, z) = ddt(rho)(x, y + 1, z); - ddt(p)(x, y, z) = ddt(p)(x, y + 1, z); - ddt(Psi)(x, y, z) = ddt(Psi)(x, y + 1, z); - } - } - } - - return 0; - } -}; - -BOUTMAIN(GravityReduced); diff --git a/examples/gravity_reduced/slab_grid.nc b/examples/gravity_reduced/slab_grid.nc deleted file mode 100644 index 2c5829b6c6..0000000000 Binary files a/examples/gravity_reduced/slab_grid.nc and /dev/null differ diff --git a/examples/hasegawa-wakatani/hw.cxx b/examples/hasegawa-wakatani/hw.cxx index 23f93d5eb7..c3f8717597 100644 --- a/examples/hasegawa-wakatani/hw.cxx +++ b/examples/hasegawa-wakatani/hw.cxx @@ -28,12 +28,10 @@ class HW : public PhysicsModel { mesh->communicate(tmp); tmp.applyBoundary("neumann"); return Delp2(tmp); - - //return Delp2(var); } protected: - int init(bool UNUSED(restart)) { + int init(bool UNUSED(restart)) override { auto& options = Options::root()["hw"]; alpha = options["alpha"].withDefault(1.0); @@ -44,7 +42,6 @@ class HW : public PhysicsModel { modified = options["modified"].withDefault(false); SOLVE_FOR(n, vort); - SAVE_REPEAT(phi); // Split into convective and diffusive parts setSplitOperator(); @@ -84,7 +81,17 @@ class HW : public PhysicsModel { return 0; } - int convective(BoutReal UNUSED(time)) { + /// Add variables to the output. This can be used to calculate + /// diagnostics + /// + /// @param[inout] state A nested dictionary that can be added to + void outputVars(Options& state) override { + // Set time-varying quantity (assignRepeat) + state["phi"].assignRepeat(phi).setAttributes( + {{"standard_name", "potential"}, {"long_name", "Plasma potential"}}); + } + + int convective(BoutReal UNUSED(time)) override { // Non-stiff, convective part of the problem // Solve for potential @@ -110,7 +117,7 @@ class HW : public PhysicsModel { return 0; } - int diffusive(BoutReal UNUSED(time)) { + int diffusive(BoutReal UNUSED(time)) override { // Diffusive terms mesh->communicate(n, vort); ddt(n) = -Dn * Delp4(n); diff --git a/examples/jorek-compare/CMakeLists.txt b/examples/jorek-compare/CMakeLists.txt deleted file mode 100644 index fb9112a7a0..0000000000 --- a/examples/jorek-compare/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(jorek-compare LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(jorek-compare - SOURCES jorek_compare.cxx - EXTRA_FILES d3d_119919.nc) diff --git a/examples/jorek-compare/README.md b/examples/jorek-compare/README.md deleted file mode 100644 index 2866f4536f..0000000000 --- a/examples/jorek-compare/README.md +++ /dev/null @@ -1,4 +0,0 @@ -JOREK Comparison -================ - -Implements a similar set of equations to [JOREK](https://www.jorek.eu) diff --git a/examples/jorek-compare/d3d_119919.nc b/examples/jorek-compare/d3d_119919.nc deleted file mode 120000 index fb006192b3..0000000000 --- a/examples/jorek-compare/d3d_119919.nc +++ /dev/null @@ -1 +0,0 @@ -../tokamak-grids/d3d_119919.nc \ No newline at end of file diff --git a/examples/jorek-compare/data/BOUT.inp b/examples/jorek-compare/data/BOUT.inp deleted file mode 100644 index 287a2f49de..0000000000 --- a/examples/jorek-compare/data/BOUT.inp +++ /dev/null @@ -1,153 +0,0 @@ -# Settings for JOREK comparison model - -################################################## -# settings used by the core code - -nout = 100 # number of time-steps -timestep = 0.001 # time between outputs - -twistshift = true # use twist-shift condition? - -MZ = 64 # number of points in z direction (2^n) - -zperiod = 10 # Fraction of a torus - -MXG = 2 -MYG = 2 - -grid = "d3d_119919.nc" - -[mesh] -staggergrids = false # Use staggered grids (EXPERIMENTAL) - -[mesh:paralleltransform] -type = shifted # Use shifted metric method - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 -second = C4 -upwind = W3 -flux = U1 - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 -flux = U1 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 -flux = U1 - -################################################## -# Laplacian inversion settings -[laplace] -all_terms = false -nonuniform = false -filter = 0.2 # Remove the top 20% of modes (BOUT-06 zwindow=0.4) -inner_boundary_flags = 1 + 4 # INVERT_DC_GRAD + INVERT_AC_LAP -outer_boundary_flags = 1 + 4 # INVERT_DC_GRAD + INVERT_AC_LAP - -################################################## -# Solver settings - -[solver] -type = petsc - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -#type=splitrk -#timestep=5e-5 - -################################################## -# settings for JOREK comparison model - -[jorek] - -D_perp = 10 # Density perpendicular diffusion [m^2/s] - -chi_eperp = 1e-07 -chi_iperp = 2.5e-06 - -chi_epar = 30 # Electron parallel diffusion -chi_ipar = 5 # Ion parallel diffusion - -eta = 1.0 # Resistivity relative to Spitzer. -# Comment-out to use value from grid file - -hyperresist = 0.01 - -Wei = 0.0 # Electron-ion energy exchange relative to collisional - -ohmic_heating = false # Include Ohmic heating in Te equation - -viscos_perp = 1e-05 # Perpendicular viscosity -viscos_coll = 0.0 # Collisional viscosity -viscos_par = 1e-05 # Parallel viscosity - -jpar_bndry_width = 4 # Decaying jpar in boundary region - -full_bfield = false -flux_method = false # Use flux methods for fluid quantities - -nonlinear = true - -electron_density = true # Evolve electron density. Adds a jpar term to density - -vorticity_momentum = true - -include_profiles = false - -parallel_lc = true # Use LtoC and CtoL differencing - -bracket_method = 2 # 0 = std, 1=simplified, 2 = arakawa, 3 = ctu - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -bndry_all = neumann # Default zero value - -[rho] - -scale = 0.001 - -function = exp(-((x - 0.4) / 0.25)^2) * exp(-((y/(2*pi) - 0.5)/0.6)^2) * sin(z) - -[Vpar] - -bndry_pf = dirichlet -bndry_sol = dirichlet - - - - -[phi] -# X boundaries set by flags -bndry_xin = none -bndry_xout = none diff --git a/examples/jorek-compare/doc/.gitignore b/examples/jorek-compare/doc/.gitignore deleted file mode 100644 index 878c7d9dac..0000000000 --- a/examples/jorek-compare/doc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -jorek_compare.pdf \ No newline at end of file diff --git a/examples/jorek-compare/doc/jorek_compare.tex b/examples/jorek-compare/doc/jorek_compare.tex deleted file mode 100644 index 0ecf0be23a..0000000000 --- a/examples/jorek-compare/doc/jorek_compare.tex +++ /dev/null @@ -1,241 +0,0 @@ -%% Manual / derivations for preconditioning in BOUT++ - -\documentclass[12pt]{article} -\usepackage[nofoot]{geometry} -\usepackage{graphicx} -\usepackage{fancyhdr} -\usepackage{amsfonts} - -\usepackage{listings} -\usepackage{color} -\usepackage{textcomp} -\definecolor{listinggray}{gray}{0.9} -\definecolor{lbcolor}{rgb}{0.95,0.95,0.95} -\lstset{ - backgroundcolor=\color{lbcolor}, - language=C++, - keywordstyle=\bfseries\ttfamily\color[rgb]{0,0,1}, - identifierstyle=\ttfamily, - commentstyle=\color[rgb]{0.133,0.545,0.133}, - stringstyle=\ttfamily\color[rgb]{0.627,0.126,0.941}, - showstringspaces=false, - basicstyle=\small, - numberstyle=\footnotesize, - numbers=left, - stepnumber=1, - numbersep=10pt, - tabsize=2, - breaklines=true, - prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}}, - breakatwhitespace=false, - aboveskip={1.5\baselineskip}, - columns=fixed, - upquote=true, - extendedchars=true, - morekeywords={Field2D,Field3D,Vector2D,Vector3D,real,FieldGroup}, -} - -%% Modify margins -\addtolength{\oddsidemargin}{-.25in} -\addtolength{\evensidemargin}{-.25in} -\addtolength{\textwidth}{0.5in} -\addtolength{\textheight}{0.25in} -%% SET HEADERS AND FOOTERS - -\pagestyle{fancy} -\fancyfoot{} -\renewcommand{\sectionmark}[1]{ % Lower case Section marker style - \markright{\thesection.\ #1}} -\fancyhead[LE,RO]{\bfseries\thepage} % Page number (boldface) in left on even - % pages and right on odd pages -\renewcommand{\headrulewidth}{0.3pt} - -\newcommand{\code}[1]{\texttt{#1}} -\newcommand{\file}[1]{\texttt{\bf #1}} - -%% commands for boxes with important notes -\newlength{\notewidth} -\addtolength{\notewidth}{\textwidth} -\addtolength{\notewidth}{-3.\parindent} -\newcommand{\note}[1]{ -\fbox{ -\begin{minipage}{\notewidth} -{\bf NOTE}: #1 -\end{minipage} -}} - -\newcommand{\pow}{\ensuremath{\wedge} } - -\newcommand{\deriv}[2]{\ensuremath{\frac{\partial #1}{\partial #2}}} -\newcommand{\dderiv}[2]{\ensuremath{\frac{\partial^2 #1}{\partial {#2}^2}}} -\newcommand{\Vec}[1]{\ensuremath{\mathbf{#1}}} -\newcommand{\Div}[1]{\ensuremath{\nabla\cdot #1 }} -\newcommand{\Curl}[1]{\ensuremath{\nabla\times #1 }} -\newcommand{\Bvec}{\ensuremath{\underline{B}}} -\newcommand{\bvec}{\ensuremath{\underline{b}}} -\newcommand{\kvec}{\ensuremath{\underline{\kappa}}} -\newcommand{\apar}{\ensuremath{A_{||}}} - -\begin{document} - -\title{JOREK-like reduced MHD equations} - -\maketitle - -\section{Overview} - -Implementation of G.Huysmanns' equations used in JOREK for ELM simulations - -\section{Starting equations} - -From PPCF {\bf 51} (2009) 124012, the {\bf normalised} equations are: -\begin{eqnarray*} - \deriv{\rho}{t} &=& -\nabla\left(\rho\underline{v}\right) + \nabla\left(D_\perp\nabla_\perp\rho\right) + S_\rho \\ - \rho\deriv{T}{t} &=& -\rho\underline{v}\cdot\nabla T - \left(\gamma - 1\right)\rho T\nabla\cdot\underline{v} + \nabla\cdot\left(\chi_\perp\nabla_\perp T + \chi_{||}\nabla_{||}T\right) + S_T \\ - \underline{e}_\phi\cdot\nabla\times\left(\rho\deriv{\underline{v}}{t}\right) &=& \underline{e}_\phi\cdot\nabla\times\left(-\rho\left(\underline{v}\cdot\nabla\right)\underline{v} - \nabla\left(\rho T\right) + \underline{J}\times\underline{B} + \mu\nabla^2\underline{v}\right) \\ - \underline{B}\cdot\left(\rho\deriv{\underline{v}}{t}\right) &=& \underline{B}\cdot\left(-\rho\left(\underline{v}\cdot\nabla\right)\underline{v} - \nabla\left(\rho T\right) + \underline{J}\times\underline{B} + \mu\nabla^2\underline{v}\right) \\ - \frac{1}{R^2}\deriv{\psi}{t} &=& \eta\left(T\right)\nabla\cdot\left(\frac{1}{R^2}\nabla_\perp\psi\right) - \underline{B}\cdot\nabla \phi -\end{eqnarray*} -where the velocity $\underline{v} = -R\nabla\phi\times\underline{e}_\phi + v_{||}\underline{B}$ - -\subsection{Normalisation} - -The normalisation used in the above equations uses $\mu_0$ and -a typical mass density $\rho_n$. Here normalised quantities are given hats -(which were omitted in the above equations). Time is normalised as: -\[ -\hat{t} = \frac{t}{\sqrt{\mu_0\rho_n}} -\] -and so velocity is normalised to -\[ -\hat{v} = v\sqrt{\mu_0\rho_n} -\] - -Pressure and current are normalised to $\mu_0$ -\[ -\hat{p} = \mu_0 p \qquad \hat{j} = \mu_0 j -\] -The normalised pressure here is given by $\hat{p} = \hat{\rho}\hat{T}$. -Since the pressure in Pascals is given by $p = enT$ where $n$ is the number -density and $T$ is in eV, this gives -\[ -\frac{1}{\mu_0}\hat{p} = e\frac{\rho_n\hat{\rho}}{m_i} T_0\hat{T} -\] -where $m_i$ is the ion mass. The temperature must therefore be normalised to -\[ -T_n = \frac{m_i}{\mu_0 e \rho_n} -\] -which for $n_n=10^{20}$ gives $T_n\simeq 5\times 10^4$. - -The diffusion coefficients are normalised to: -\begin{eqnarray*} -\hat{\eta} &=& \eta\sqrt{\rho_n / \mu_0} \\ -\hat{\mu} &=& \mu\sqrt{\mu_0/\rho_n} \\ -\hat{D_\perp} &=& D_\perp\sqrt{\mu_0\rho_n} \\ -\hat{\chi_\perp} &=& \chi_\perp\sqrt{\mu_0/\rho_n} -\end{eqnarray*} -In addition, energy density is normalised as $\hat{\epsilon} = \mu_0\epsilon$ so -power density $w$ (Watts / m$^3$) is normalised as -$\hat{w} = \mu_0\sqrt{\mu_0\rho_n} w$ - -For $n_n=10^{20}$m$^{-3}$, these factors are $\sqrt{\rho_n / \mu_0} = 0.52$, $\sqrt{\mu_0/\rho_n}=1.94$ and $\sqrt{\mu_0\rho_n} = 6.48\times 10^{-7}$. - -\section{Equations solved in BOUT++ model} - -The total magnetic field is given by: -\[ -\Bvec = \Bvec_0 + \nabla\times\left(\bvec_0\apar\right) \simeq \Bvec_0 + \nabla\apar \times\bvec_0 -\] -Either of these expressions can be used, depending on the value of the \texttt{full\_bfield} option. The parallel current is given by -\[ -j_{||} = j_{||0} - \frac{1}{\mu_0}\nabla_\perp^2\apar -\] -which since $j_{||}$ is normalised to $\mu_0$, and $\apar$ is not normalised gives -\[ -\hat{j_{||}} = \hat{j_{||0}} - \nabla_\perp^2\hat{\apar} -\] -The $E\times B$ velocity is given by: -\[ -\Vec{v}_{E\times B} = \frac{1}{B^2}\Bvec\times\nabla\phi -\] -Vorticity $U$ is defined as -\begin{eqnarray*} -U \equiv \Curl{\Vec{v}_{E\times B}} &=& \frac{\bvec}{B}\Div{\nabla\phi} - \nabla\phi\left(\Div{\frac{\bvec}{B}}\right) + \left(\nabla\phi\cdot\nabla\right)\frac{\bvec}{B} - \left(\frac{\bvec}{B}\cdot\nabla\right)\nabla\phi \\ -&\simeq& \frac{\bvec}{B}\nabla_\perp^2\phi -\end{eqnarray*} -where only the first term has been kept, and parallel derivatives neglected (flute assumption). Electrostatic potential can therefore be related to -vorticity by: -\[ -U \simeq \frac{1}{B_0}\nabla_\perp^2\phi -\] - -The normalised evolution equations solved are: - -\begin{eqnarray*} - \deriv{\rho}{t} &=& -\Vec{v}_{E\times B}\cdot\nabla\left(\rho + \rho_0\right) + \left(\nabla\cdot\Vec{v}_{E\times B}\right)\left(\rho + \rho_0\right) + D_\perp\nabla_\perp^2\rho \\ - \deriv{T_s}{t} &=& -\Vec{v}_{E\times B}\cdot\nabla\left(T_s + T_{s0}\right) - \frac{2}{3}\left(\nabla\cdot\Vec{v}_{E\times B}\right)\left(T_s + T_{s0}\right) \\ - &&+ \frac{1}{\rho + \rho_0}\left[ \nabla_{||}\cdot\left(\chi_{s||}\partial_{||}T_s\right) + \chi_\perp\nabla_\perp^2T_s\right] + \frac{2}{3\left(\rho+\rho_0\right)}W_s \\ - \deriv{U}{t} &=& -\Vec{v}_{E\times B}\cdot\nabla U + \frac{1}{\rho+\rho_0}\left[ B_0^2\nabla_{||}\left(\frac{J_{||}+J_{||0}}{B_0}\right) + 2\bvec_0\times\kvec_0\cdot\nabla P + \nu_{||}\partial_{||}^2u + \nu_\perp\nabla_\perp^2u\right] \\ -\deriv{v_{||}}{t} &=& -\Vec{v}_{E\times B}\cdot\nabla v_{||} - \nabla_{||} P \\ -\deriv{\apar}{t} &=& -\nabla_{||}\phi - \eta J_{||} \\ -P &=& \rho\left(T_e + T_i\right) -\end{eqnarray*} -where there is a separate equation for electron and ion temperatures which -differ only in conductivity coefficients. All quantities with subscript '0' -are (constant) equilibrium quantites, everything else is evolving. - -$W_s$ is the rate of exchange between thermal energy and other forms. For -ions this is due to collisions with the electrons. The standard Chapman-Enskog -collisional expression ($T$ in eV, $W$ in Watts/m$^3$) is -\[ -W_i = 3\frac{m_e}{m_i}\frac{en}{\tau_e}\left(T_e - T_i\right) -\] -whilst the electron expression is -\[ -W_e = -W_i + \eta J_{||}^2 -\] -and so the normalised expressions are: -\begin{eqnarray*} - \hat{W}_i &=& 3\frac{m_e}{m_i} \frac{\hat{\rho}}{\hat{\tau}_e}\left(\hat{T}_e - \hat{T}_i\right) \\ - \hat{W}_e &=& -\hat{W}_i + \hat{\eta}_{||}\hat{J}_{||}^2 -\end{eqnarray*} -The Spitzer resistivity is used: -\[ -\eta_{||} = \frac{m_e}{1.96ne^2\tau_e} \qquad \Rightarrow \hat{\eta}_{||} = \frac{m_em_i}{1.96\mu_0\rho_ne^2}\frac{1}{\hat{\tau}_e\hat{\rho}} -\] -whilst the electron-ion collision time in seconds is -\[ -\tau_e = 3.44\times 10^{11}\frac{T_e^{3/2}}{n}\frac{1}{Z_i\ln\Lambda} -\] -The Coulomb logarithm is only calculated once at the start based on the maximum density and temperature in the domain. Typical values for normalised $\tau_e$ are $10 - 10^3$. Due to the factor of $m_e/m_i$, the $W_i$ term will only become important for long very long simulations. - -Both $W_i$ and $\eta_{||}$ are multiplied by factors read from the input file (\texttt{wei} and \texttt{eta} respectively) to scale up or down relative to these collisional estimates. Set \texttt{wei} $\le 0$ to switch off this term. - -\subsection{Divergence of $E\times B$ flow} - -\[ -\nabla\cdot\Vec{v}_{E\times B} = \nabla\cdot\left(\frac{1}{B_0}\bvec_0\times\nabla\phi\right) -\] - -Using $\nabla\cdot\left(\Vec{F}\times\Vec{G}\right) = \left(\nabla\times\Vec{F}\right)\cdot\Vec{G} - \Vec{F}\cdot\left(\nabla\times\Vec{G}\right)$, this becomes -\[ -\nabla\cdot\Vec{v}_{E\times B} = \left[\nabla\times\left(\frac{1}{B_0}\bvec_0\right)\right]\cdot\nabla\phi - \frac{1}{B_0}\bvec_0\times\nabla\times\nabla\phi -\] -The second term is identically zero (curl of gradient), and the first term becomes: -\[ -\nabla\cdot\Vec{v}_{E\times B} = \left[\nabla\left(\frac{1}{B_0}\right)\times\bvec_0 + \frac{1}{B_0}\nabla\times\bvec_0\right]\cdot\nabla\phi -\] -The second term can be written in terms of the curvature $\kvec_0$ using: -\[ -\bvec_0\times\kvec_0 = \bvec\times\left[\left(\nabla\times\bvec\right)\times\bvec\right] = \nabla\times\bvec_0 - \bvec_0\left[\bvec_0\cdot\left(\nabla\times\bvec_0\right)\right] -\] -Hence the divergence of $E\times B$ flow can be written as -\[ -\nabla\cdot\Vec{v}_{E\times B} = -\bvec_0\times\nabla\left(\frac{1}{B_0}\right)\cdot\nabla\phi + \frac{1}{B_0}\bvec_0\times\kvec_0\cdot\nabla\phi + \left[\bvec_0\cdot\left(\nabla\times\bvec_0\right)\right]\bvec_0\cdot\nabla\phi -\] -Currently the code includes the first two terms, but drops the last parallel -derivative. This is on the grounds that parallel gradients of $\phi$ should -be small relative to perpendicular gradients (the first two terms). - -\end{document} - diff --git a/examples/jorek-compare/jorek_compare.cxx b/examples/jorek-compare/jorek_compare.cxx deleted file mode 100644 index 5963fbd7ca..0000000000 --- a/examples/jorek-compare/jorek_compare.cxx +++ /dev/null @@ -1,695 +0,0 @@ -/************************************************************************** - * Similar set of equations to JOREK - * - **************************************************************************/ - -#include - -#include -#include - -class Jorek : public PhysicsModel { -private: - // Evolving quantities - Field3D rho, Te, Ti, U, Vpar, Apar; - // Derived quantities - Field3D Jpar, phi; // Parallel current, electric potential - - // Equilibrium quantities - Field2D rho0, Te0, Ti0; // Equilibrium mass density, electron and ion temperature - Field2D B0, J0, P0; - Vector2D b0xcv; // Curvature term - Vector2D B0vec; // B0 field vector - - // Dissipation coefficients - Field2D D_perp; // Particle diffusion coefficient - Field2D chi_eperp, chi_epar; // Electron heat diffusion coefficients - Field2D chi_iperp, chi_ipar; // Ion heat diffusion coefficients - - // Collisional terms - BoutReal tau_enorm; - Field3D tau_e; // electron collision time - - Field2D eta0; // Resistivity - Field3D eta; - - BoutReal viscos_par, viscos_perp, viscos_coll; // Viscosity coefficients - BoutReal hyperresist; // Hyper-resistivity coefficient - - // Constants - const BoutReal MU0 = 4.0e-7 * PI; - const BoutReal Charge = 1.60217646e-19; // electron charge e (C) - const BoutReal Mi = 2.0 * 1.67262158e-27; // Ion mass - const BoutReal Me = 9.1093816e-31; // Electron mass - const BoutReal Me_Mi = Me / Mi; // Electron mass / Ion mass - - // Normalisation factors - BoutReal Tnorm, rhonorm; // Partial normalisation to rho and MU0. Temperature normalised - - // options - - bool nonlinear; - bool full_bfield; // If true, use divergence-free expression for B - bool flux_method; // Use flux methods in rho and T equations - int jpar_bndry_width; // Set jpar = 0 in a boundary region - - bool electron_density; // Solve Ne rather than Ni (adds Jpar term to density) - - bool vorticity_momentum; // Vorticity is curl of momentum, rather than velocity - - bool include_profiles; // Include zero-order equilibrium terms - - int low_pass_z; // Toroidal (Z) filtering of all variables - - Vector3D vExB, vD; // Velocities - Field3D divExB; // Divergence of ExB flow - - BoutReal Wei; // Factor for the electron-ion collision term - bool ohmic_heating; - - // Poisson brackets: b0 x Grad(f) dot Grad(g) / B = [f, g] - // Method to use: BRACKET_ARAKAWA, BRACKET_STD or BRACKET_SIMPLE - BRACKET_METHOD bm; // Bracket method for advection terms - - // Communication objects - FieldGroup comms; - - // Coordinate system - Coordinates* coord; - - // Inverts a Laplacian to get potential - std::unique_ptr phiSolver{nullptr}; - - int init(bool UNUSED(restarting)) override { - - output.write("Solving JOREK-like reduced MHD equations\n"); - output.write("\tFile : {:s}\n", __FILE__); - output.write("\tCompiled: {:s} at {:s}\n", __DATE__, __TIME__); - - auto globalOptions = Options::root(); - auto options = globalOptions["jorek"]; - - ////////////////////////////////////////////////////////////// - // Load data from the grid - - // Load 2D profiles - mesh->get(J0, "Jpar0"); // A / m^2 - - if (mesh->get(rho0, "Ni0")) { - output << "Warning: No density profile available\n"; - rho0 = options["density"].withDefault(1.0); - } - rho0 *= 1e20; // Convert to m^[-3] - - // Read temperature - mesh->get(Te0, "Te0"); - mesh->get(Ti0, "Ti0"); - - // Try reading pressure profile (in Pascals) - if (mesh->get(P0, "pressure")) { - // Just calculate from Temp and density - P0 = Charge * (Ti0 + Te0) * rho0; - } else { - // Make sure that density and temperature are consistent with pressure - - Field2D factor = P0 / (Charge * (Ti0 + Te0) * rho0); - - output.write("\tPressure factor {:e} -> {:e}\n", min(factor, true), - max(factor, true)); - - // Multiply temperatures by this factor - Te0 *= factor; - Ti0 *= factor; - } - rho0 *= Mi; // Convert density to mass density [kg / m^3] - - // Load dissipation coefficients, override in options file - if (options["D_perp"].isSet()) { - D_perp = options["D_perp"].withDefault(0.0); - } else { - mesh->get(D_perp, "D_perp"); - } - - if (options["chi_eperp"].isSet()) { - chi_eperp = options["chi_eperp"].withDefault(0.0); - } else { - mesh->get(chi_eperp, "chi_eperp"); - } - - if (options["chi_iperp"].isSet()) { - chi_iperp = options["chi_iperp"].withDefault(0.0); - } else { - mesh->get(chi_iperp, "chi_iperp"); - } - - if (options["chi_epar"].isSet()) { - chi_epar = options["chi_epar"].withDefault(0.0); - } else { - mesh->get(chi_epar, "chi_epar"); - } - - if (options["chi_ipar"].isSet()) { - chi_ipar = options["chi_ipar"].withDefault(0.0); - } else { - mesh->get(chi_ipar, "chi_ipar"); - } - - if (options["viscos_perp"].isSet()) { - viscos_perp = options["viscos_perp"].withDefault(-1.0); - } else { - mesh->get(viscos_perp, "viscos_perp"); - } - - if (options["viscos_par"].isSet()) { - viscos_par = options["viscos_par"].withDefault(-1.0); - } else { - mesh->get(viscos_par, "viscos_par"); - } - - viscos_coll = options["viscos_coll"].withDefault(-1.0); - - // Load curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // mixed units x: T y: m^-2 z: m^-2 - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - Field2D I; // Shear factor - - coord = mesh->getCoordinates(); - - if (mesh->get(Rxy, "Rxy")) { // m - output_error.write("Error: Cannot read Rxy from grid\n"); - return 1; - } - if (mesh->get(Bpxy, "Bpxy")) { // T - output_error.write("Error: Cannot read Bpxy from grid\n"); - return 1; - } - mesh->get(Btxy, "Btxy"); // T - mesh->get(B0, "Bxy"); // T - mesh->get(hthe, "hthe"); // m - mesh->get(I, "sinty"); // m^-2 T^-1 - - nonlinear = options["nonlinear"].withDefault(false); - full_bfield = options["full_bfield"].withDefault(false); - flux_method = options["flux_method"].withDefault(false); - - jpar_bndry_width = options["jpar_bndry_width"].withDefault(-1); - - hyperresist = options["hyperresist"].withDefault(-1); - - electron_density = options["electron_density"].withDefault(false); - vorticity_momentum = options["vorticity_momentum"].withDefault(false); - include_profiles = options["include_profiles"].withDefault(false); - - low_pass_z = options["low_pass_z"].withDefault(-1); // Default is no filtering - - Wei = options["Wei"].withDefault(1.0); - - ohmic_heating = options["ohmic_heating"].withDefault(true); - - switch (options["bracket_method"].withDefault(0)) { - case 0: { - bm = BRACKET_STD; - output << "\tBrackets: default differencing\n"; - break; - } - case 1: { - bm = BRACKET_SIMPLE; - output << "\tBrackets: simplified operator\n"; - break; - } - case 2: { - bm = BRACKET_ARAKAWA; - output << "\tBrackets: Arakawa scheme\n"; - break; - } - case 3: { - bm = BRACKET_CTU; - output << "\tBrackets: Corner Transport Upwind method\n"; - break; - } - default: - output << "ERROR: Invalid choice of bracket method. Must be 0 - 3\n"; - return 1; - } - - ////////////////////////////////////////////////////////////// - // SHIFTED RADIAL COORDINATES - - // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault( - "identity"); - - if (lowercase(ptstr) == "shifted") { - // Dimits style, using local coordinate system - b0xcv.z += I * b0xcv.x; - I = 0.0; // I disappears from metric - } - - ////////////////////////////////////////////////////////////// - // NORMALISE QUANTITIES - - rhonorm = max(rho0, true); // Maximum over all grid - BoutReal Temax = max(Te0, true); // Maximum Te value - Tnorm = Mi / (MU0 * Charge * rhonorm); // Temperature normalisation - - SAVE_ONCE(rhonorm, Tnorm); // Save normalisation factors to file - - // Normalise quantities - - P0 *= MU0; - J0 *= MU0; - rho0 /= rhonorm; - Te0 /= Tnorm; - Ti0 /= Tnorm; - - viscos_perp *= sqrt(MU0 / rhonorm); - viscos_par *= sqrt(MU0 / rhonorm); - D_perp *= sqrt(MU0 * rhonorm); - chi_eperp *= sqrt(MU0 / rhonorm); - chi_epar *= sqrt(MU0 / rhonorm); - chi_iperp *= sqrt(MU0 / rhonorm); - chi_ipar *= sqrt(MU0 / rhonorm); - - // Coulomb logarithm - BoutReal CoulombLog = 6.6 - 0.5 * log(rhonorm / (Mi * 1e20)) + 1.5 * log(Temax); - output << "\tCoulomb logarithm = " << CoulombLog << endl; - - // Factor in front of tau_e expression - // tau_e = tau_enorm * Tet^1.5 / rhot - tau_enorm = 3.44e11 * (Mi / rhonorm) * Tnorm * sqrt(Tnorm) / CoulombLog; - output << "\ttau_enorm = " << tau_enorm; - tau_enorm /= sqrt(MU0 * rhonorm); // Normalise - output << "\tNormalised tau_enorm = " << tau_enorm << endl; - - // Calculate or read in the resistivity - if (options["eta"].isSet()) { - BoutReal etafactor = options["eta"].withDefault(0.0); - // Calculate in normalised units - eta0 = etafactor * Me * Mi - / (1.96 * MU0 * rhonorm * Charge * Charge * tau_enorm * rho0); - } else { - mesh->get(eta0, "eta0"); // Read in SI units - eta0 *= sqrt(rhonorm / MU0); // Normalise - } - - ////////////////////////////////////////////////////////////// - // CALCULATE METRICS - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(B0) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - coord->Bxy = B0; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(B0 * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); // Calculate quantities from metric tensor - - // Set B field vector - B0vec.covariant = false; - B0vec.x = 0.; - B0vec.y = Bpxy / hthe; - B0vec.z = 0.; - - vExB.setBoundary("v"); - vD.setBoundary("v"); - - Jpar.setBoundary("Jpar"); - - phi.setBoundary("phi"); - - // Set starting dissipation terms - eta = eta0; - tau_e = tau_enorm * pow(Te0, 1.5) / rho0; - - output.write("\tNormalised tau_e = {:e} -> {:e}\n", min(tau_e, true), - max(tau_e, true)); - - // Set locations for staggered grids - vD.setLocation(CELL_VSHIFT); - - // SET EVOLVING VARIABLES - - SOLVE_FOR(rho, Te, Ti, U, Vpar, Apar); - - comms.add(rho, Te, Ti, U, Vpar, Apar); - comms.add(phi); - - SAVE_ONCE(P0, J0, rho0, Te0, Ti0); // Save normalised profiles - - if (nonlinear) { - SAVE_REPEAT(eta); - } else { - SAVE_ONCE(eta); - } - - SAVE_REPEAT(phi, Jpar); // Save each timestep - SAVE_REPEAT(divExB); - - // Create a solver for the Laplacian - phiSolver = Laplacian::create(); - if (vorticity_momentum) { - phiSolver->setCoefC(rho0); - } - return 0; - } - - // Parallel gradient along perturbed field-line - const Field3D Grad_parP(const Field3D& f, CELL_LOC loc = CELL_DEFAULT) { - // Derivative along equilibrium field-line - Field3D result; - - result = Grad_par(f, loc); - - if (nonlinear) { - if (full_bfield) { - // Use full expression for perturbed B - Vector3D Btilde = Curl(B0vec * Apar / B0); - result += Btilde * Grad(f) / B0; - } else { - // Simplified expression - result -= bracket(Apar, f, BRACKET_ARAKAWA); - } - } - return result; - } - - const Field3D Div_parP(const Field3D& f, CELL_LOC loc = CELL_DEFAULT) { - return B0 * Grad_parP(f / B0, loc); - } - - int rhs(BoutReal t) override { - TRACE("Started Jorek::rhs({:e})", t); - - // Invert laplacian for phi - if (vorticity_momentum) { - // Vorticity is b dot curl(rho * v) - Field2D rprof = rho0; - if (nonlinear) { - rprof += DC(rho); // Axisymmetric rho only - phiSolver->setCoefC(rprof); - } - phi = phiSolver->solve(B0 * U / rprof); - } else { - // Vorticity is b dot curl(v) - phi = phiSolver->solve(B0 * U); - } - // Apply a boundary condition on phi for target plates - phi.applyBoundary(); - - // Communicate variables - mesh->communicate(comms); - - // Get J from Psi - Jpar = -Delp2(Apar); - Jpar.applyBoundary(); - - if (jpar_bndry_width > 0) { - // Boundary in jpar - if (mesh->firstX()) { - for (int i = jpar_bndry_width; i >= 0; i--) { - for (int j = 0; j < mesh->LocalNy; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - Jpar(i, j, k) = 0.5 * Jpar(i + 1, j, k); - } - } - } - } - if (mesh->lastX()) { - for (int i = mesh->LocalNx - jpar_bndry_width - 1; i < mesh->LocalNx; i++) { - for (int j = 0; j < mesh->LocalNy; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - Jpar(i, j, k) = 0.5 * Jpar(i - 1, j, k); - } - } - } - } - } - - mesh->communicate(Jpar); - - // Jpar = smooth_x(Jpar); // Smooth in x direction - - Field3D rhot = rho0; - Field3D Tet = Te0; - Field3D Tit = Ti0; - Field3D P = rho * (Te0 + Ti0) + (Te + Ti) * rho0; // Perturbed pressure - - if (nonlinear) { - rhot += rho; - Tet += Te; - Tit += Ti; - P += rho * (Te + Ti); - - eta = eta0 * pow(Tet / Te0, -1.5); // Update resistivity based on Te - - tau_e = tau_enorm * pow(Tet, 1.5) / rhot; // Update electron collision rate - } - - if (flux_method) { - { - TRACE("Flux vExB"); - // ExB velocity - vExB = (cross(B0vec, Grad_perp(phi))) / (B0 * B0); - vExB.applyBoundary(); - } - - ////////// Density equation //////////////// - - { - TRACE("Flux Density"); - - // Diffusive flux (perpendicular) - vD = -D_perp * Grad_perp(rho); - vD.applyBoundary(); - - ddt(rho) = -Div(vExB + vD, rhot); - } - - ////////// Temperature equations //////////// - - { - TRACE("Flux Te"); - - vD = -chi_eperp * Grad_perp(Te) - Grad_par(Te, CELL_YLOW) * chi_epar * B0vec; - vD.applyBoundary(); - - ddt(Te) = -b0xGrad_dot_Grad(phi, Tet) / B0 - (2. / 3.) * Tet * Div(vExB) - - Div(vD, Te) / rhot; - } - - { - TRACE("Flux Ti"); - - vD = -chi_iperp * Grad_perp(Ti) - Grad_par(Ti, CELL_YLOW) * chi_ipar * B0vec; - vD.applyBoundary(); - - ddt(Ti) = -b0xGrad_dot_Grad(phi, Tit) / B0 - (2. / 3.) * Tit * Div(vExB) - - Div(vD, Ti) / rhot; - } - } else { - // Use analytic expressions, expand terms - - // Divergence of ExB velocity (neglecting parallel term) - { - TRACE("divExB"); - divExB = b0xcv * Grad(phi) / B0 - b0xGrad_dot_Grad(1. / B0, phi); - } - - { - TRACE("density"); - ddt(rho) = -bracket(phi, rhot, bm) // ExB advection - - divExB * rhot // Divergence of ExB (compression) - - Vpar_Grad_par(Vpar, rho) // Parallel advection - - rhot * Div_parP(Vpar, CELL_CENTRE) // Parallel compression - + D_perp * Delp2(rho) // Perpendicular diffusion - ; - - if (electron_density) { - // Using electron parallel velocity rather than ion - ddt(rho) += (Mi / (Charge * sqrt(MU0 * rhonorm))) * Div_parP(Jpar, CELL_CENTRE); - } - - if (low_pass_z > 0) { - ddt(rho) = lowPass(ddt(rho), low_pass_z); - } - } - - { - TRACE("Te"); - ddt(Te) = -bracket(phi, Tet, bm) - Vpar_Grad_par(Vpar, Tet) // advection - - (2. / 3.) * Tet - * (divExB + Div_parP(Vpar, CELL_CENTRE)) // Divergence of flow - + Div_par_K_Grad_par(chi_epar, Te) / rhot // Parallel diffusion - + chi_eperp * Delp2(Te) / rhot // Perpendicular diffusion - ; - - if (ohmic_heating) { - ddt(Te) += (2. / 3) * eta * Jpar * Jpar / rhot; // Ohmic heating - } - } - - { - TRACE("Ti"); - ddt(Ti) = -bracket(phi, Tit, bm) - Vpar_Grad_par(Vpar, Tit) - - (2. / 3.) * Tit * (divExB + Div_parP(Vpar, CELL_CENTRE)) - + Div_par_K_Grad_par(chi_ipar, Ti) / rhot - + chi_iperp * Delp2(Ti) / rhot; - } - - if (Wei > 0.0) { - TRACE("Wei"); - // electron-ion collision term - // Calculate Wi * (2/3)/rho term. Wei is a scaling factor from options - Field3D Tei = Wei * 2. * Me_Mi * (Te - Ti) / tau_e; - - ddt(Ti) += Tei; - ddt(Te) -= Tei; - } - - if (low_pass_z > 0) { - ddt(Te) = lowPass(ddt(Te), low_pass_z); - ddt(Ti) = lowPass(ddt(Ti), low_pass_z); - } - } - - ////////// Vorticity equation //////////// - - if (vorticity_momentum) { - TRACE("vorticity_momentum"); - // Vorticity is b dot curl(rho * v) - - ddt(U) = SQ(B0) * Grad_parP(Jpar / B0, CELL_CENTRE) // b0 dot J - + 2. * b0xcv * Grad(P) - - rhot * (divExB + Div_parP(Vpar, CELL_CENTRE)) * Delp2(phi) - / B0 // drho/dt term - ; - - // b dot J0 - if (full_bfield) { - Vector3D Btilde = Curl(B0vec * Apar / B0); - ddt(U) += B0 * Btilde * Grad(J0 / B0); - } else { - ddt(U) -= SQ(B0) * bracket(Apar, J0 / B0, BRACKET_ARAKAWA); - } - - if (electron_density) { - // drho/dt jpar term - ddt(U) += (Mi / (Charge * sqrt(MU0 * rhonorm))) * rhot - * Div_parP(Jpar / rhot, CELL_CENTRE) * Delp2(phi) / B0; - } - - if (include_profiles) { - ddt(U) += SQ(B0) * Grad_par(J0 / B0) // b0 dot J0 - + 2. * b0xcv * Grad(P0); - } - - if (nonlinear) { - ddt(U) -= bracket(phi, U, bm); // Advection - ddt(U) -= Vpar_Grad_par(Vpar, U); // Parallel advection - } - - // Viscosity terms - if (viscos_par > 0.0) { - ddt(U) += viscos_par * Grad2_par2(U); // Parallel viscosity - } - - if (viscos_perp > 0.0) { - ddt(U) += viscos_perp * rhot * Delp2(U / rhot); // Perpendicular viscosity - } - - } else { - TRACE("vorticity"); - // Vorticity is b dot curl(v) - ddt(U) = (SQ(B0) * Grad_parP(Jpar / B0, CELL_CENTRE) - + 2. * b0xcv * Grad(P) // curvature term - ) - / rhot; - - // b dot J0 - if (full_bfield) { - Vector3D Btilde = Curl(B0vec * Apar / B0); - ddt(U) += B0 * Btilde * Grad(J0 / B0) / rhot; - } else { - ddt(U) -= SQ(B0) * bracket(Apar, J0 / B0, BRACKET_ARAKAWA) / rhot; - } - - if (include_profiles) { - ddt(U) += (SQ(B0) * Grad_par(J0 / B0) // b0 dot J0 - + 2. * b0xcv * Grad(P0)) - / rhot; - } - - if (nonlinear) { - ddt(U) -= bracket(phi, U); // Advection - ddt(U) -= Vpar_Grad_par(Vpar, U); // Parallel advection - } - - // Viscosity terms - if (viscos_par > 0.0) { - ddt(U) += viscos_par * Grad2_par2(U) / rhot; // Parallel viscosity - } - - if (viscos_perp > 0.0) { - ddt(U) += viscos_perp * Delp2(U) / rhot; // Perpendicular viscosity - } - - // Collisional viscosity - if (viscos_coll > 0.0) { - ddt(U) += viscos_coll / MU0 * eta * Delp2(U) / rhot; - } - } - - if (low_pass_z > 0) { - ddt(U) = lowPass(ddt(U), low_pass_z); - } - - ////////// Parallel velocity equation //////////// - - { - TRACE("Vpar"); - - ddt(Vpar) = -Grad_parP(P + P0, CELL_YLOW); - if (nonlinear) { - ddt(Vpar) -= bracket(phi, Vpar); // Advection - ddt(Vpar) -= Vpar_Grad_par(Vpar, Vpar); // Parallel advection - } - - if (low_pass_z > 0) { - ddt(Vpar) = lowPass(ddt(Vpar), low_pass_z); - } - } - - ////////// Magnetic potential equation //////////// - - { - TRACE("Apar"); - ddt(Apar) = -Grad_parP(phi, CELL_YLOW) - eta * Jpar; - - if (hyperresist > 0.0) { - ddt(Apar) += eta * hyperresist * Delp2(Jpar); - } - } - - if (low_pass_z > 0) { - ddt(Apar) = lowPass(ddt(Apar), low_pass_z); - } - - return 0; - } -}; - -BOUTMAIN(Jorek); diff --git a/examples/lapd-drift/BOUT.inp b/examples/lapd-drift/BOUT.inp deleted file mode 100644 index eb953c6b7d..0000000000 --- a/examples/lapd-drift/BOUT.inp +++ /dev/null @@ -1,214 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -nout = 400 # number of time-steps -timestep = 20.0 # time between outputs - -ShiftXderivs = false # use shifted radial derivatives? -twistshift = false # use twist-shift condition? - -MZ = 513 # number of points in z direction (2^n + 1) -zperiod = 1 # Number of periods - -#ZMIN=0.0 -#ZMAX=2.e-2 # Non-integer period for comparison with BOUT-06 - -MXG = 2 -MYG = 2 - -grid = "uedge.grd.pdb" - -#StaggerGrids = true - -non_uniform = true - -NXPE = 5 # Decompose in X direction - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 # C4 = 4th order central, C2 = 2nd order central -second = C4 -upwind = U1 # U1 = 1st order upwind, W3 = 3rd order WENO - -[mesh:ddy] - -first = C4 -second = C4 -upwind = U1 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = U1 - -################################################## -# Laplacian inversion settings - -[laplace] - -all_terms = true -nonuniform = true - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 4.0 -ZZ = 1.0 - -estatic = true # if true, electrostatic (Apar = 0) -ZeroElMass = false # Use Ohms law without electron inertia -zeff = 1.0 # Z effective -nu_perp = 1e-20 - -nuIonNeutral = 0.002 # Ion-neutral collision rate, normalised to wci - -ni_perpdiff = 0.002 -rho_perpdiff = 0.002 -te_perpdiff = 0.002 - -nonlinear = true - -ShearFactor = 0.0 - -arakawa = false # Use Arakawa scheme for ExB advection -bout_exb = true # Use the BOUT-06 subset of ExB terms - -remove_tor_av_ni = false -remove_tor_av_te = false - -evolve_source_ni = true -evolve_source_te = false - -filter_z = false # Filter in Z -filter_z_mode = 1 # Keep this Z harmonic - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) - - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# Form of initial profile -function = mixmode(x)*mixmode(y)*mixmode(z) - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -#bndry_core = relax(neumann) -#bndry_sol = relax(neumann) -#bndry_target = none -bndry_all = relax(neumann) - -# Section for only the Ni equation -# Contains switches for terms -[ni] -# Terms always present -evolve_ni = true -ni_jpar1 = true -ni_ni0_phi1 = true -ni_diff = true - -# Linear Terms with phi0 -ni_ni1_phi0 = false - -# Nonlinear Terms -ni_ni1_phi1 = true - -scale = 1e-08 # only perturbing Ni - -# Section for only the rho equation -# Contains switches for terms -[rho] -# Terms always present -evolve_rho = true -rho_jpar1 = true -rho_nuin_rho1 = true # Neutral Damping -rho_rho1 = false # Viscosity -rho_diff = true - -# Linear Terms with phi0 -rho_rho0_phi1 = false -rho_rho1_phi0 = false -rho_ve2lin = false - -# Nonlinear Terms -rho_rho1_phi1 = true -rho_ve2t = true - - -scale = -1e-08 - - -# Section for only the Ajpar equation -# Contains switches for terms -[ajpar] -# Terms always present -evolve_ajpar = true -ajpar_phi1 = true -ajpar_jpar1 = true -ajpar_te_ni = true -ajpar_te = false - -# Linear Terms with phi0 -ajpar_ajpar1_phi0 = false - -# Nonlinear terms -ajpar_ajpar1_phi1 = true -ajpar_ve1_ve1 = true - - -# Section for only the te equation -# Contains switches for terms -[te] -# Terms always present -evolve_te = false -te_te0_phi1 = false -te_te_ajpar = false -te_nu_te1 = false -te_jpar = false -te_diff = false - -# Linear Terms with phi0 -te_te1_phi0 = false - -# Nonlinear terms -te_te1_phi1 = false -te_ajpar_te = false -te_nu_tet = false diff --git a/examples/lapd-drift/BOUT.inp.nn b/examples/lapd-drift/BOUT.inp.nn deleted file mode 100644 index cb2fe1be31..0000000000 --- a/examples/lapd-drift/BOUT.inp.nn +++ /dev/null @@ -1,124 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -NOUT = 300 # number of time-steps -TIMESTEP = 10. # time between outputs - -archive = 20 - -ShiftXderivs = false # use shifted radial derivatives? -TwistShift = false # use twist-shift condition? - -MZ = 9 # number of points in z direction (2^n + 1) -#ZPERIOD = 7 # Number of periods - -ZMIN=0.0 -ZMAX=3.6198e-2 # Non-integer period for comparison with BOUT-06 - -MXG = 2 -MYG = 2 - -grid="uedge.grd.nc" - -dump_format = "nc" # Output format (PDB = "pdb", NetCDF="nc") - -#StaggerGrids = true - -NXPE = 1 # Decompose in X direction - -################################################## -# derivative methods - -[ddx] - -first = C4 # C4 = 4th order central, C2 = 2nd order central -second = C4 -upwind = C4 # U1 = 1st order upwind, W3 = 3rd order WENO - -[ddy] - -first = C4 -second = C4 -upwind = U1 - -[ddz] - -first = C4 -second = C4 -upwind = C4 - -################################################## -# Laplacian inversion settings - -[laplace] - -all_terms = true -laplace_nonuniform = true - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1.0e-12 # absolute tolerance -rtol = 1.0e-5 # relative tolerance -pvode_mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 4.0 -ZZ = 1.0 - -estatic = true # if true, electrostatic (Apar = 0) -ZeroElMass = false # Use Ohms law without electron inertia -Zeff = 1.0 # Z effective -nu_perp = 1.0e-20 - -nuIonNeutral = -1. # Ion-neutral collision rate, normalised to wci - -nonlinear = false - -ShearFactor = 0.0 - -relax_flat_bndry = true # Use BOUT-06 style relaxing boundaries -bout_exb = true # Use the BOUT-06 subset of ExB terms - -filter_z = true # Filter in Z -filter_z_mode = 1 # Keep this Z harmonic - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) - -phi_flags = 0 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[All] -scale = 0.0 # default size of initial perturbations -function = sin(2*pi*x) * sin(y) * sin(z) - -bndry_xin = neumann -bndry_xout = neumann - -[Ni] -scale = 1.0e-8 # only perturbing Ni - -[rho] -scale = -1.0e-8 diff --git a/examples/lapd-drift/BOUT.inp.nn_zem b/examples/lapd-drift/BOUT.inp.nn_zem deleted file mode 100644 index ad6baaee1c..0000000000 --- a/examples/lapd-drift/BOUT.inp.nn_zem +++ /dev/null @@ -1,124 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -NOUT = 300 # number of time-steps -TIMESTEP = 10. # time between outputs - -archive = 20 - -ShiftXderivs = false # use shifted radial derivatives? -TwistShift = false # use twist-shift condition? - -MZ = 9 # number of points in z direction (2^n + 1) -#ZPERIOD = 7 # Number of periods - -ZMIN=0.0 -ZMAX=3.6198e-2 # Non-integer period for comparison with BOUT-06 - -MXG = 2 -MYG = 2 - -grid="uedge.grd.nc" - -dump_format = "nc" # Output format (PDB = "pdb", NetCDF="nc") - -#StaggerGrids = true - -NXPE = 1 # Decompose in X direction - -################################################## -# derivative methods - -[ddx] - -first = C4 # C4 = 4th order central, C2 = 2nd order central -second = C4 -upwind = C4 # U1 = 1st order upwind, W3 = 3rd order WENO - -[ddy] - -first = C4 -second = C4 -upwind = U1 - -[ddz] - -first = C4 -second = C4 -upwind = C4 - -################################################## -# Laplacian inversion settings - -[laplace] - -all_terms = true -laplace_nonuniform = true - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1.0e-12 # absolute tolerance -rtol = 1.0e-5 # relative tolerance -pvode_mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 4.0 -ZZ = 1.0 - -estatic = true # if true, electrostatic (Apar = 0) -ZeroElMass = true # Use Ohms law without electron inertia -Zeff = 1.0 # Z effective -nu_perp = 1.0e-20 - -nuIonNeutral = -1. # Ion-neutral collision rate, normalised to wci - -nonlinear = false - -ShearFactor = 0.0 - -relax_flat_bndry = true # Use BOUT-06 style relaxing boundaries -bout_exb = true # Use the BOUT-06 subset of ExB terms - -filter_z = true # Filter in Z -filter_z_mode = 1 # Keep this Z harmonic - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) - -phi_flags = 0 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[All] -scale = 0.0 # default size of initial perturbations -function = sin(2*pi*x)*sin(y)*sin(z) - -bndry_xin = neumann -bndry_xout = neumann - -[Ni] -scale = 1.0e-8 # only perturbing Ni - -[rho] -scale = -1.0e-8 diff --git a/examples/lapd-drift/BOUT06.inp b/examples/lapd-drift/BOUT06.inp deleted file mode 100644 index 5ac4b195db..0000000000 --- a/examples/lapd-drift/BOUT06.inp +++ /dev/null @@ -1,108 +0,0 @@ ----------------Resistive drift instability test---------------- - -!!!----Note: with f77 compiler don't start at 1st column----!!! - &bout - - NVARS=6, - NOUT=300, - DUMP_PERIOD=1, - TWOHR=1.e1, - T0=0.0, - - ZMIN=0.0, - ZMAX=8.58816, - - NXPE=1, - MXSUB=50, - - NYPE=16, - MYSUB=2, - MZ=9, - - MYG=2, - MXG=2, - - iTe_dc=2, - NPVT=-1, - - C1_SCALE=1e-8 - C2_SCALE=1e-8 - - nu_para=1e-6 - nu_perp=1e-20 - - RTOL=1e-5, - FLOOR=1e-5, - lambda=-10., - bkgd=2, - - AA=4.0, - ZZ=1.0, - zeff=1., - esop=0, - - scaleTe=0.0 - scaleTi=0.0 - scaleVi=0.0 - scaleAjpar=0.0 - - ZeroElMass=0, - ShearFactor=0.0, - TwistShift=0, - RadDerSimple=1, - - SheathBC=0, - - phidcIn=0, - phidcOut=0, - phiacIn=0, - phiacOut=0, - apardcIn=0, - apardcOut=0, - aparacIn=0, - aparacOut=0, - - - zs_opt=2, - zs_mode=1. - - ys_opt=2, - ys_mode=1. - - xs_opt=2, - xs_mode=1. - - zwindow = 0. - - nuIonNeutral = 7.e-3 - - / - - - &eq_ni - Ni0_Phi1=1, ! #1 - Ni1_Phi0=1, ! #1 - Jpar1=1 ! #2 - / - - &eq_vi - / - - &eq_rho - Jpar1=1 ! #7 - Rho0_Phi1=1 ! #10 - Rho1_Phi0=1 ! #10 - nuIN_Rho1=1 - / - - &eq_ti - / - - &eq_te - / - - &eq_ajpar - Phi1=1, ! #5 - Te0_Ni1=1, ! #4 - Jpar1=1 ! #6 - / diff --git a/examples/lapd-drift/BOUT06.inp.nn b/examples/lapd-drift/BOUT06.inp.nn deleted file mode 100644 index eff3fd069c..0000000000 --- a/examples/lapd-drift/BOUT06.inp.nn +++ /dev/null @@ -1,106 +0,0 @@ ----------------Resistive drift instability test---------------- - -!!!----Note: with f77 compiler don't start at 1st column----!!! - &bout - - NVARS=6, - NOUT=300, - DUMP_PERIOD=1, - TWOHR=1.e1, - T0=0.0, - - ZMIN=0.0, - ZMAX=8.58816, - - NXPE=1, - MXSUB=50, - - NYPE=16, - MYSUB=2, - MZ=9, - - MYG=2, - MXG=2, - - iTe_dc=2, - NPVT=-1, - - C1_SCALE=1e-8 - C2_SCALE=1e-8 - - nu_para=1e-6 - nu_perp=1e-20 - - RTOL=1e-5, - FLOOR=1e-5, - lambda=-10., - bkgd=2, - - AA=4.0, - ZZ=1.0, - zeff=1., - esop=0, - - scaleTe=0.0 - scaleTi=0.0 - scaleVi=0.0 - scaleAjpar=0.0 - - ZeroElMass=0, - ShearFactor=0.0, - TwistShift=0, - RadDerSimple=1, - - SheathBC=0, - - phidcIn=0, - phidcOut=0, - phiacIn=0, - phiacOut=0, - apardcIn=0, - apardcOut=0, - aparacIn=0, - aparacOut=0, - - - zs_opt=2, - zs_mode=1. - - ys_opt=2, - ys_mode=1. - - xs_opt=2, - xs_mode=1. - - zwindow = 0. - - - / - - - &eq_ni - Ni0_Phi1=1, ! #1 - Ni1_Phi0=1, ! #1 - Jpar1=1 ! #2 - / - - &eq_vi - / - - &eq_rho - Jpar1=1 ! #7 - Rho0_Phi1=1 ! #10 - Rho1_Phi0=1 ! #10 - / - - &eq_ti - / - - &eq_te - / - - &eq_ajpar - Phi1=1, ! #5 - Te0_Ni1=1, ! #4 - Jpar1=1 ! #6 - / diff --git a/examples/lapd-drift/BOUT06.inp.nn_zem b/examples/lapd-drift/BOUT06.inp.nn_zem deleted file mode 100644 index 1bc113d920..0000000000 --- a/examples/lapd-drift/BOUT06.inp.nn_zem +++ /dev/null @@ -1,103 +0,0 @@ ----------------Resistive drift instability test---------------- - -!!!----Note: with f77 compiler don't start at 1st column----!!! - &bout - - NVARS=6, - NOUT=300, - DUMP_PERIOD=1, - TWOHR=1.e1, - T0=0.0, - - ZMIN=0.0, - ZMAX=8.58816, - - NXPE=1, - MXSUB=50, - - NYPE=16, - MYSUB=2, - MZ=9, - - MYG=2, - MXG=2, - - iTe_dc=2, - NPVT=-1, - - C1_SCALE=1e-8 - C2_SCALE=1e-8 - - nu_para=1e-6 - nu_perp=1e-20 - - RTOL=1e-5, - FLOOR=1e-5, - lambda=-10., - bkgd=2, - - AA=4.0, - ZZ=1.0, - zeff=1., - esop=0, - - scaleTe=0.0 - scaleTi=0.0 - scaleVi=0.0 - scaleAjpar=0.0 - - ZeroElMass=1, - ShearFactor=0.0, - TwistShift=0, - RadDerSimple=1, - - SheathBC=0, - - phidcIn=0, - phidcOut=0, - phiacIn=0, - phiacOut=0, - apardcIn=0, - apardcOut=0, - aparacIn=0, - aparacOut=0, - - - zs_opt=2, - zs_mode=1. - - ys_opt=2, - ys_mode=1. - - xs_opt=2, - xs_mode=1. - - zwindow = 0. - - - / - - - &eq_ni - Ni0_Phi1=1, ! #1 - Ni1_Phi0=1, ! #1 - Jpar1=1 ! #2 - / - - &eq_vi - / - - &eq_rho - Jpar1=1 ! #7 - Rho0_Phi1=1 ! #10 - Rho1_Phi0=1 ! #10 - / - - &eq_ti - / - - &eq_te - / - - &eq_ajpar - / diff --git a/examples/lapd-drift/CMakeLists.txt b/examples/lapd-drift/CMakeLists.txt deleted file mode 100644 index 250752303f..0000000000 --- a/examples/lapd-drift/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(lapd-drift LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(lapd-drift - SOURCES lapd_drift.cxx - DATA_DIRS lapd - data - pisces - EXTRA_FILES BOUT.inp - BOUT.inp.nn - BOUT.inp.nn_zem - uedge.grd.nc) diff --git a/examples/lapd-drift/README.md b/examples/lapd-drift/README.md deleted file mode 100644 index a29fcf1a63..0000000000 --- a/examples/lapd-drift/README.md +++ /dev/null @@ -1,71 +0,0 @@ -2-fluid Turbulence in a Linear device -===================================== - -Benchmark cases for comparisons of BOUT 06 vs BOUT++ results - -Electrostatic drift wave -LAPD plasma parameters/geometry - - -Analytic solution: independent solver for the eigenvalues for the -linear system of drift wave equations - -BOUT: running BOUT with only linear terms included. -Growth rate is calculated using RMS of Phi (averaged over volume). Phi -is then divided by the exponential (gamma t) and the frequency is -calculated in each point in space via matching the time series with a -sin(omega t) wave. (fit_time program) - -Everything except the first azimuthal harmonic is filtered out (zwindow = 0.) -These solutions are for axial (y) harmonic n=1 -Dominating radial mode in the solution: fundamental (~nx=0.5) - -Running the BOUT++ cases -======================== - -1. Compile the lapd_drift executable (just run make) - -2. Copy one of the BOUT.inp* input files into data/BOUT.inp - (see below for cases) e.g. "$ cp BOUT.inp_nn data/BOUT.inp" - -3. Run BOUT++ (e.g. mpirun -np 16 ./lapd_drift) - -4. run the analysis script ($ idl runidl.pro) - -Case 1 -====== -LAPD config, Ni0 profile from experiment, no phi0, no neutrals - -BOUT-06 input: BOUT06.inp.nn -BOUT++ input : BOUT.inp.nn - -Analytic solution: omega/OmCI =( 0.035565860, 0.010584464) -BOUT-06: omega/OmCI =( 0.0348090 , 0.010362237) -BOUT++: omega/OmCI =( 0.0349127 , 0.010270213) - -Case 2 -====== - -LAPD config, Ni profile from experiment, no phi0, no neutrals, me=0 -Same as 1), but with zero electrom mass - -BOUT-06 input: BOUT06.inp.nn_zem -BOUT++ input : BOUT.inp.nn_zem - -Analytic solution: omega/OmCI =( 0.035565860, 0.010584464) -BOUT-06: omega/OmCI =( 0.0364727 , 0.0095402879) -BOUT++: omega/OmCI =( 0.0350513 , 0.010112489) - -Case 3 -====== - -LAPD config with neutrals (nu_in = 7.e-3 OmCI), -Ni profile from experiment, no phi0 - -BOUT-06 input: BOUT06.inp -BOUT++ input : BOUT.inp - -Analytic solution: omega/OmCI =( 0.035850606, 0.0067657669) -BOUT-06: omega/OmCI =( 0.0350248 , 0.0065545603) -BOUT++: omega/OmCI =( 0.0350987 , 0.0064631935) - diff --git a/examples/lapd-drift/bpp_no_neutrals.jpg b/examples/lapd-drift/bpp_no_neutrals.jpg deleted file mode 100644 index a6320315bc..0000000000 Binary files a/examples/lapd-drift/bpp_no_neutrals.jpg and /dev/null differ diff --git a/examples/lapd-drift/bpp_no_neutrals_zem.jpg b/examples/lapd-drift/bpp_no_neutrals_zem.jpg deleted file mode 100644 index b8752807c5..0000000000 Binary files a/examples/lapd-drift/bpp_no_neutrals_zem.jpg and /dev/null differ diff --git a/examples/lapd-drift/bpp_with_neutrals.jpg b/examples/lapd-drift/bpp_with_neutrals.jpg deleted file mode 100644 index b71dbaf32d..0000000000 Binary files a/examples/lapd-drift/bpp_with_neutrals.jpg and /dev/null differ diff --git a/examples/lapd-drift/data/BOUT.inp b/examples/lapd-drift/data/BOUT.inp deleted file mode 100644 index d995ab17fc..0000000000 --- a/examples/lapd-drift/data/BOUT.inp +++ /dev/null @@ -1,201 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -nout = 400 # number of time-steps -timestep = 2.0 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 32 # number of points in z direction (2^n + 1) -zperiod = 5 # Number of periods - -non_uniform = true - -MXG = 2 -MYG = 2 - -grid = "uedge.grd.nc" - -[mesh] -staggergrids = true - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 # C4 = 4th order central, C2 = 2nd order central -second = C4 -upwind = W3 # U1 = 1st order upwind, W3 = 3rd order WENO - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Laplacian inversion settings - -[laplace] -inner_boundary_flags = 1 -outer_boundary_flags = 2 -all_terms = true -nonuniform = true - -################################################## -# Solver settings - -[solver] -type = pvode - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 4.0 -ZZ = 1.0 - -estatic = true # if true, electrostatic (Apar = 0) -ZeroElMass = false # Use Ohms law without electron inertia -zeff = 1.0 # Z effective -nu_perp = 1e-20 - -nuIonNeutral = 0.002 # Ion-neutral collision rate, normalised to wci - -ni_perpdiff = 0.002 -rho_perpdiff = 0.002 -te_perpdiff = 0.002 - -nonlinear = true - -ShearFactor = 0.0 - -arakawa = false # Use Arakawa scheme for ExB advection -bout_exb = true # Use the BOUT-06 subset of ExB terms - -remove_tor_av_ni = true -remove_tor_av_te = false - -evolve_source_ni = false -evolve_source_te = false - -filter_z = false # Filter in Z -filter_z_mode = 1 # Keep this Z harmonic - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# Form of initial perturbation -function = mixmode(x)*mixmode(y)*mixmode(z) - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -#bndry_core = relax(neumann) -#bndry_sol = relax(neumann) -#bndry_target = none -bndry_all = relax(neumann) - -# Section for only the Ni equation -# Contains switches for terms -[ni] -# Terms always present -evolve_ni = true -ni_jpar1 = true -ni_ni0_phi1 = true -ni_diff = true - -# Linear Terms with phi0 -ni_ni1_phi0 = false - -# Nonlinear Terms -ni_ni1_phi1 = true - -scale = 1e-08 # only perturbing Ni - -# Section for only the rho equation -# Contains switches for terms -[rho] -# Terms always present -evolve_rho = true -rho_jpar1 = true -rho_nuin_rho1 = true # Neutral Damping -rho_rho1 = false # Viscosity -rho_diff = true - -# Linear Terms with phi0 -rho_rho0_phi1 = false -rho_rho1_phi0 = false -rho_ve2lin = false - -# Nonlinear Terms -rho_rho1_phi1 = true -rho_ve2t = false - - -scale = -1e-08 - - -# Section for only the Ajpar equation -# Contains switches for terms -[ajpar] -# Terms always present -evolve_ajpar = true -ajpar_phi1 = true -ajpar_jpar1 = true -ajpar_te_ni = true -ajpar_te = false - -# Linear Terms with phi0 -ajpar_ajpar1_phi0 = false - -# Nonlinear terms -ajpar_ajpar1_phi1 = true -ajpar_ve1_ve1 = true - - -# Section for only the te equation -# Contains switches for terms -[te] -# Terms always present -evolve_te = false -te_te0_phi1 = false -te_te_ajpar = false -te_nu_te1 = false -te_jpar = false -te_diff = false - -# Linear Terms with phi0 -te_te1_phi0 = false - -# Nonlinear terms -te_te1_phi1 = false -te_ajpar_te = false -te_nu_tet = false diff --git a/examples/lapd-drift/fit_time.pro b/examples/lapd-drift/fit_time.pro deleted file mode 100644 index bec13a74ed..0000000000 --- a/examples/lapd-drift/fit_time.pro +++ /dev/null @@ -1,301 +0,0 @@ -; Fit the solution from BOUT with a sine wave and calculate gamma/omega -; Work in progress - -function RMS_XYZ, d -;Takes the rms over all space coordinates -;---------------------------------------------------------- - -;-find what tags are available in structure d -name=['APAR_XYZT','AJPAR_XYZT','JPAR_XYZT','NI_XYZT','PHI_XYZT','RHO_XYZT','TE_XYZT','TI_XYZT','VI_XYZT'] -name_count=N_ELEMENTS(name) -iname=intarr(name_count)-1 ;-index of given name in structure d - -dnames=TAG_NAMES(d) -nn=n_elements(dnames) - - for j=0,nn-1 do begin - for i=0,name_count-1 do begin - if (dnames[j] eq name[i]) then iname[i]=j - endfor - endfor - - - dum=dblarr(d.trange) - rms=dblarr(d.trange) - - -drms={APAR_T:dum,AJPAR_T:dum,JPAR_T:dum,NI_T:dum,PHI_T:dum,$ -RHO_T:dum,TE_T:dum,TI_T:dum,VI_T:dum} - - for i=0,name_count-1 do begin - - IF iname[i] ge 0 THEN BEGIN - for it=0, d.trange-1 do begin - rms[it] = SQRT(TOTAL(double(d.(iname(i))[*,*,*,it])^2)) - endfor - drms.(i)=rms - ENDIF else begin - drms.(i)=dum - ENDELSE - - if not(keyword_set(QUIET)) then print, name(i), '...done' - endfor - -if keyword_set(DEBUG) then STOP - -return, drms -end -;==================================================================================== -; Return function for LMFIT: -function fitFunc, X, A -; Fit the signal with -; f(x) = (a[0]*sin(a[1]+a[2]*x) - - vsin = a[0]*sin(a[1]+a[2]*x) - return,[ [vsin], $ ; f(x) - [vsin/a[0]], $ ; d f(x) / d a[0] - [a[0]*cos(a[1]+a[2]*x)], $ ; d f(x) / d a[1] - [x*a[0]*cos(a[1]+a[2]*x)] $ ; d f(x) / d a[2] - ] -end -;==================================================================================== -function lmfit_signal, X, Y, A - -;print, 'Initial fit parameters: ', A - -measure_errors = Y - -ffit = LMFIT(X, Y, A, /DOUBLE, CONVERGENCE=CONVERGENCE, MEASURE_ERRORS=measure_errors, $ - FUNCTION_NAME = 'fitFunc', TOL=1.e-12) - -;print, 'Convergence=', CONVERGENCE -;print, 'Fit parameters: ', A - -return, ffit - -end -;==================================================================================== -pro get_guess, X, Y, A - -nz=zero_cross(Y, pos=pos) - -if (nz > 0.) then begin -; Periodic data found, calculate the initial guess parameters - -;print, 'nz=',nz -;print, 'Number of zeros = ', nz -;print, 'Positions of zeros:', pos -NT = (X[pos(nz-1)]-X[pos(0)])*2./(nz-1) -;print, 'Period:', NT - -A = fltarr(3) -A[0] = max(Y) ; amplitude -A[2] = 2.*!PI/NT ; omega - -if (Y[0]<0.) then begin - A[1] = - A[2]*X[pos(0)] ; phase -endif else begin - A[1] = !PI - A[2]*X[pos(0)] ; phase -endelse - -;print, A, X[pos(0)] -; -;Ndata = n_elements(Y) -;guess = fltarr(Ndata) -;for i=0,Ndata-1 do begin -; afit=fitFunc(X[i],A) -; guess[i] = afit[0] -;endfor - -;plot, X, guess, title='Initial guess' - -endif else begin - -; No periodic data found (no zeros) -A = fltarr(3) -A[2] = -1. - -endelse - -end -;==================================================================================== -pro SmoothData, tdata - - nt = n_elements(tdata) - ; Assume several oscillation periods are present in 0..nt-1 time interval - ; Average out non-oscillating part if present - tdata = tdata - smooth(smooth(tdata, nt/10,/edge_truncate), nt/10,/edge_truncate) - -end -;==================================================================================== - -pro Fit_Time, d, du, MANUAL=MANUAL, NT0=NT0, NTMAX=NTMAX, omre=omre, omim=omim, $ - SILENT=SILENT, PSAVE=PSAVE, LABEL=LABEL, SMOOTH=SMOOTH - - nstep=1 - nt=n_elements(d.PHI_xyzt[0,0,0,*]) - nx=n_elements(d.PHI_xyzt[*,0,0,0]) - ny=n_elements(d.PHI_xyzt[0,*,0,0]) - nz=n_elements(d.PHI_xyzt[0,0,*,0]) - - if not keyword_set(LABEL) then LABEL='PLOT' ; label for the plot - print, 'LABEL: ' + LABEL - if not keyword_set(nt0) then nt0=nt/6 ;-skip initial part of the curve - if not keyword_set(ntmax) then ntmax=nt ; include all points to the last one - maxVal=dblarr(ntmax-nt0) - - rms=RMS_XYZ(d) - for i=nt0,ntmax-1 do maxVal[i-nt0]=rms.PHI_t[i] - - if keyword_set(MANUAL) then begin - plot, d.t_array[nt0:ntmax-1]/d.wci, alog(maxVal), psym=4, syms=3, xtit='time, s', ytit='ln',/yst, chars=1.5 - - print, "Mark 2 points on straight line to measure the exponential growth rate" - print, "Click point 1" & mark, x=x1, y=y1 - print, "Click point 2" & mark,x=x2,y=y2 - oplot, [x1,x2], [y1,y2], col=2 - gamma=(y2-y1)/(x2-x1) - endif else begin - xx=d.t_array[nt0:ntmax-1]/d.wci & yy=ALOG(maxVal) - res=Poly_Fit(xx,yy,1) - oplot, xx, res[0] + res[1]*xx, col=2 - gamma=res[1] - WAIT, 0.7 - endelse - - print, "gamma/OmCI=", gamma/d.wci - -!p.multi=[0,1,2,0,0] - WINDOW, RETAIN = 2 -WINDOW, 0, XSIZE=750, YSIZE=750 - - - PHI_norm=d.PHI_XYZT[*,*,*,nt0:ntmax-1] - PHI_fft=complexarr(nx,ny,nz,ntmax-nt0) - growth=fltarr(ntmax-nt0) - - - for i=nt0,ntmax-1 do growth[i-nt0]=exp(gamma/d.wci*d.T_ARRAY[i]) - for i=nt0,ntmax-1 do PHI_norm[*,*,*,i-nt0]=d.PHI_XYZT[*,*,*,i]/growth[i-nt0] - - jx=nx/3 ; choose some point away from the edges and not in the middle (avoid nodes of the wave) - jy=ny/3 - jz=nz/3 - - plot, d.t_array[nt0:ntmax-1]/d.wci, alog(maxVal), psym=4, syms=3, xtit='time, s', ytit='ln',/yst, chars=1.5 - - vd = PHI_norm[jx,jy,jz,*] - SmoothData, vd - - plot, d.T_ARRAY[nt0:ntmax-1], vd, title='Phi(t)/exp(t)' - - omega_3d = fltarr(nx,ny,nz) - - for jx=0, nx-1 do begin - - if not keyword_set(SILENT) then print, 'jx = ', jx, '/', nx-1 - - for jy=0, ny-1 do begin - for jz=0, nz-1 do begin - - if keyword_set(SMOOTH) then begin ; de-trend - vtmp = reform(PHI_norm[jx,jy,jz,*]) - SmoothData, vtmp - PHI_norm[jx,jy,jz,*] = vtmp[*] - endif - get_guess, d.T_ARRAY[nt0:ntmax-1], PHI_norm[jx,jy,jz,*], A - if (A[2] > 0) then ffit=lmfit_signal(d.T_ARRAY[nt0:ntmax-1],PHI_norm[jx,jy,jz,*], A) - omega_3d[jx,jy,jz] = A[2] - endfor - endfor - endfor - - jx=nx/3 - jy=ny/3 - jz=nz/3 - -; omega = A[2] -; print, 'omega/OmCI=',omega - - - hmax=2.* TOTAL(omega_3d[where(omega_3d gt 0.)])/(n_elements(where(omega_3d gt 0.))) - hbins = 200 - h=histogram(omega_3d,MIN=0.0, MAX=hmax, NBINS=hbins) - homega = findgen(hbins)*hmax/(hbins-1) - maxv = max(h,jmax) - h_dom = homega(jmax) - - - print, 'BOUT: omega/OmCI = (', h_dom, ' +', gamma/d.wci, ')' - - ; Return the values found - omre = h_dom - omim = gamma/d.wci - - -; plot, homega, h - -;--------------------------------------------------------------- - jx=nx/3 - jy=ny/3 - jz=nz/3 -jt=ntmax-1 - - -!p.multi=[0,3,2,0,0] - - -window, 0, XSIZE=750, YSIZE=750, RETAIN = 2, /Pixmap,/Free -pixID=!D.Window - - WSet, pixID - - - ; Plot the RMS of the signal (including the growth exp) - plot, d.t_array[nt0:ntmax-1]/d.wci, alog(maxVal), psym=4, syms=3, xtit='time, s', ytit='ln',/yst, chars=1.5, title=LABEL - - ; Plot Phi(t) (excluding the growth exp) - plot, d.T_ARRAY[nt0:ntmax-1], PHI_norm[jx,jy,jz,*], title='Phi(t)/exp(t)' - - - tit=string(format='(%"Omega 3d distribution, max @ om=%9.2e ")', h_dom) - xtit='omega/OmCI' - plot, homega, h, xtit=xtit, tit=tit - - tit='BOUT: Axial profile' - xtit="Z, m" - ytit="Ni" - yr = [ min( [d.PHI_XYZT[jx,*,jz,jt]*0.9, d.PHI_XYZT[jx,*,jz,jt]*1.1] ), $ - max( [d.PHI_XYZT[jx,*,jz,jt]*0.9, d.PHI_XYZT[jx,*,jz,jt]*1.1] ) ] - plot, du.ZXY[jx,*], d.PHI_XYZT[jx,*,jz,jt], $ - xtit=xtit, ytit=ytit, tit=tit, chars=1.5, yrange=yr - - tit='BOUT: Phi radial profile' - xtit="r/rho_s" - ytit="Phi" - plot, du.RXY[*,jy]/d.rho_s, d.PHI_XYZT[*,jy,jz,jt], $ - xtit=xtit, ytit=ytit, tit=tit, chars=1.5 - - tit='BOUT: Ni radial profile' - xtit="r/rho_s" - ytit="Ni" - plot, du.RXY[*,jy]/d.rho_s, d.PHI_XYZT[*,jy,jz,jt], $ - xtit=xtit, ytit=ytit, tit=tit, chars=1.5 - - !p.multi=0 - - - if keyword_set(PSAVE) then begin -;-save the picture - image=TVRD(/true) - file=LABEL+'.jpg' - write_jpeg, file, image,/true - endif - - WSet - Device, Copy=[0, 0, !D.X_Size, !D.Y_Size, 0, 0, pixID] - -;--------------------------------------------------------------- - - -end diff --git a/examples/lapd-drift/lapd/BOUT.inp b/examples/lapd-drift/lapd/BOUT.inp deleted file mode 100644 index 01e8c8e573..0000000000 --- a/examples/lapd-drift/lapd/BOUT.inp +++ /dev/null @@ -1,228 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -nout = 400 # number of time-steps -timestep = 2 # time between outputs - -MZ = 32 # number of points in z direction (2^n + 1) -zperiod = 5 # Number of periods - -non_uniform = true - -[mesh] -# Simple mesh for linear device - -staggergrids = true # Enable staggered grids - -nx = 54 # Number of radial grid points, including guards -ny = 32 # Number of parallel (Y) grid points - -Length = 17 # length of machine in meters -Rmin = 0.15 # minimum radius in meters -Rmax = 0.45 # maximum radius - -Bxy = 0.04 # magnetic field in Tesla - -Ni0 = 5e-3 + 2e-2*exp(-(x/0.4)^2) # Density in units of 10^20 m^-3 -Te0 = 5 # Electron temperature in eV -Ti0 = 0.1 # Ion temperature in eV - -Ni_x = 0.025 # Density normalisation in units of 10^20 m^-3 -Te_x = 5 # Electron normalisation in eV -Ti_x = Te_x # Ion normalisation in eV -bmag = 0.04 # Magnetic field normalisation in Tesla - -Bpxy = Bxy -Btxy = 0 -hthe = 1 -dy = length / ny - -Rxy = Rmin + (Rmax - Rmin) * x - -dr = (Rmax - Rmin) / (nx - 4) -dx = Bpxy * Rxy * dr -dpsi = dx - -# ixseps1 and ixseps2 set the radial (x) index of the separatrix -ixseps1 = 10000 # >= nx -> periodic in Y. -1 -> boundaries in Y -ixseps2 = 10000 - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 # C4 = 4th order central, C2 = 2nd order central -second = C4 -upwind = W3 # U1 = 1st order upwind, W3 = 3rd order WENO - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Laplacian inversion settings -[laplace] - -all_terms = true -nonuniform = true -inner_boundary_flags = 1 # INVERT_DC_GRAD -outer_boundary_flags = 2 # INVERT_AC_GRAD - -################################################## -# Solver settings - -[solver] -type = pvode - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 4.0 -ZZ = 1.0 - -estatic = true # if true, electrostatic (Apar = 0) -ZeroElMass = false # Use Ohms law without electron inertia -zeff = 1.0 # Z effective -nu_perp = 1e-20 - -nuIonNeutral = 0.002 # Ion-neutral collision rate, normalised to wci - -ni_perpdiff = 0.002 -rho_perpdiff = 0.002 -te_perpdiff = 0.002 - -nonlinear = true - -ShearFactor = 0.0 - -arakawa = false # Use Arakawa scheme for ExB advection -bout_exb = true # Use the BOUT-06 subset of ExB terms - -remove_tor_av_ni = true -remove_tor_av_te = false - -evolve_source_ni = false -evolve_source_te = false - -filter_z = false # Filter in Z -filter_z_mode = 1 # Keep this Z harmonic - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations -function = mixmode(x)*mixmode(y)*mixmode(z) - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -#bndry_core = relax(neumann) -#bndry_sol = relax(neumann) -#bndry_target = none -bndry_all = neumann - -# Section for only the Ni equation -# Contains switches for terms -[ni] -# Terms always present -evolve_ni = true -ni_jpar1 = true -ni_ni0_phi1 = true -ni_diff = true - -# Linear Terms with phi0 -ni_ni1_phi0 = false - -# Nonlinear Terms -ni_ni1_phi1 = true - -scale = 1e-08 # only perturbing Ni - -# Section for only the rho equation -# Contains switches for terms -[rho] -# Terms always present -evolve_rho = true -rho_jpar1 = true -rho_nuin_rho1 = true # Neutral Damping -rho_rho1 = false # Viscosity -rho_diff = true - -# Linear Terms with phi0 -rho_rho0_phi1 = false -rho_rho1_phi0 = false -rho_ve2lin = false - -# Nonlinear Terms -rho_rho1_phi1 = true -rho_ve2t = false - - -scale = -1e-08 - -bndry_all = neumann_o2 - -# Section for only the Ajpar equation -# Contains switches for terms -[ajpar] -# Terms always present -evolve_ajpar = true -ajpar_phi1 = true -ajpar_jpar1 = true -ajpar_te_ni = true -ajpar_te = false - -# Linear Terms with phi0 -ajpar_ajpar1_phi0 = false - -# Nonlinear terms -ajpar_ajpar1_phi1 = true -ajpar_ve1_ve1 = true - - -# Section for only the te equation -# Contains switches for terms -[te] -# Terms always present -evolve_te = false -te_te0_phi1 = false -te_te_ajpar = false -te_nu_te1 = false -te_jpar = false -te_diff = false - -# Linear Terms with phi0 -te_te1_phi0 = false - -# Nonlinear terms -te_te1_phi1 = false -te_ajpar_te = false -te_nu_tet = false diff --git a/examples/lapd-drift/lapd_drift.cxx b/examples/lapd-drift/lapd_drift.cxx deleted file mode 100644 index b7579dacb1..0000000000 --- a/examples/lapd-drift/lapd_drift.cxx +++ /dev/null @@ -1,874 +0,0 @@ -/******************************************************************************* - * 2-fluid equations - * Same as Maxim's version of BOUT - simplified 2-fluid for benchmarking - * LAPD standard case with simulation results published in PoP in Popovich et. al. 2010 - *******************************************************************************/ -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -/// Solves 2-fluid equations for turbulence in a linear device -/// -class LAPDdrift : public PhysicsModel { -private: - // 2D initial profiles - Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, Ajpar0, src_ni0; - Coordinates::FieldMetric rho0; - Vector2D b0xcv; // for curvature terms - - // 3D evolving fields - Field3D rho, ni, ajpar, te; - - // Derived 3D variables - Field3D phi, Apar, Ve, jpar; - - // Non-linear coefficients - Field3D nu, mu_i, kapa_Te, kapa_Ti; - - // 3D total values - Field3D Nit, Tit, Tet, Vit, phit, VEt, dphi_bc_ydown, dphi_bc_yup; - - // pressures - Field3D pei, pe; - Field2D pei0, pe0; - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe, Zxy; - - // parameters - BoutReal Te_x, Ti_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; - BoutReal lambda_ei, lambda_ii; - BoutReal nu_hat, mui_hat, wci, nueix, nuiix; - BoutReal ni_perpdiff, rho_perpdiff, te_perpdiff; - BoutReal beta_p; - BoutReal nuIonNeutral; // Ion-neutral collision rate (normalised by wci) - - // settings - bool estatic, ZeroElMass; // Switch for electrostatic operation (true = no Apar) - - bool arakawa; // Use Arakawa scheme for ExB advection - bool bout_exb; // Use BOUT-06 expression for ExB velocity - - BoutReal zeff, nu_perp; - bool evolve_rho, evolve_ni, evolve_ajpar, evolve_te; - BoutReal ShearFactor; - BoutReal time_step; - - bool nonlinear; - bool neg_fix; - - BoutReal ni_floor, minNit; - - bool filter_z; - int filter_z_mode; - - bool log_density; // Evolve logarithm of the density - - bool niprofile; - - bool evolve_source_ni, evolve_source_te; // If true, evolve a source/sink profile - BoutReal source_response; // Initial source response (inverse timescale) - BoutReal source_converge; // Timescale for convergence - Field2D Sn, St; // Density source (inverse timescale) - bool input_source; // Read Sn from the input file - bool remove_tor_av_ni, remove_tor_av_te; // Subtract the toroidal averages - - // Switches for terms in the ni equation - bool ni_jpar1, ni_ni0_phi1, ni_ni1_phi0, ni_ni1_phi1, ni_src_ni0, ni_diff; - - // Switches for terms in the rho equation - bool rho_jpar1, rho_nuin_rho1, rho_rho1, rho_rho1_phi1, rho_ve2t, rho_diff; - bool rho_rho0_phi1, rho_rho1_phi0, rho_ve2lin; - - // Switches for terms in the ajpar equation - bool ajpar_phi1, ajpar_jpar1, ajpar_te_ni, ajpar_te; - bool ajpar_ajpar1_phi1, ajpar_ajpar1_phi0, ajpar_ve1_ve1; - - // Switches for terms in the te equation - bool te_te1_phi0, te_te0_phi1, te_te1_phi1, te_ajpar_te; - bool te_te_ajpar, te_nu_te1, te_nu_tet, te_jpar, te_diff; - - // Coefficients for linear sheath problem - Field2D LAMBDA1, LAMBDA2; - - // My ixseps variables - int my_ixseps; - - // Communication object - FieldGroup comms; - - // Laplacian inversion object - std::unique_ptr phiSolver; - -protected: - /// Function called once at the start of the simulation - /// - /// @param[in] restarting True if simulation is restarting - int init(bool UNUSED(restarting)) { - Field2D I; // Shear factor - - output.write("Solving LAPD drift test case\n"); - - /************* LOAD DATA FROM GRID FILE ****************/ - - // Load 2D profiles (set to zero if not found) - mesh->get(Ni0, "Ni0"); - mesh->get(Ti0, "Ti0"); - mesh->get(Te0, "Te0"); - mesh->get(Vi0, "Vi0"); - mesh->get(Ve0, "Ve0"); - mesh->get(phi0, "phi0"); - mesh->get(rho0, "rho0"); - mesh->get(Ajpar0, "Ajpar0"); - mesh->get(src_ni0, "src_ni0"); - - // Load magnetic curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // b0xkappa terms - - Coordinates* coord = mesh->getCoordinates(); - - // Load metrics - mesh->get(Rxy, "Rxy"); - mesh->get(Zxy, "Zxy"); - mesh->get(Bpxy, "Bpxy"); - mesh->get(Btxy, "Btxy"); - mesh->get(hthe, "hthe"); - mesh->get(coord->dx, "dpsi"); - mesh->get(I, "sinty"); - - // Load normalisation values - mesh->get(Te_x, "Te_x"); - mesh->get(Ti_x, "Ti_x"); - mesh->get(Ni_x, "Ni_x"); - mesh->get(bmag, "bmag"); - - // Get separatrix location - mesh->get(my_ixseps, "ixseps1"); - - Ni_x *= 1.0e14; - bmag *= 1.0e4; - - /*************** READ OPTIONS *************************/ - // Read some parameters - - auto& globalOptions = Options::root(); - - time_step = globalOptions["TIMESTEP"].withDefault(1.0); - - auto& options = globalOptions["2fluid"]; - AA = options["AA"].withDefault(4.0); // <=> AA = options["AA"].withDefault(1.0); - ZZ = options["ZZ"].withDefault(1.0); - - estatic = options["estatic"].withDefault(false); - ZeroElMass = options["ZeroElMass"].withDefault(false); - zeff = options["zeff"].withDefault(1.0); - nu_perp = options["nu_perp"].withDefault(0.0); - ShearFactor = options["ShearFactor"].withDefault(1.0); - nuIonNeutral = options["nuIonNeutral"].withDefault(-1.); - arakawa = options["arakawa"].withDefault(false); - bout_exb = options["bout_exb"].withDefault(false); - - niprofile = options["niprofile"].withDefault(false); - evolve_source_ni = options["evolve_source_ni"].withDefault(false); - evolve_source_te = options["evolve_source_te"].withDefault(false); - source_response = options["source_response"].withDefault(1.0); - source_converge = options["source_converge"].withDefault(-1); - - ni_perpdiff = options["ni_perpdiff"].withDefault(0.0); - rho_perpdiff = options["rho_perpdiff"].withDefault(0.0); - te_perpdiff = options["te_perpdiff"].withDefault(0.0); - - input_source = options["input_source"].withDefault(false); - remove_tor_av_ni = options["remove_tor_av_ni"].withDefault(false); - remove_tor_av_te = options["remove_tor_av_te"].withDefault(false); - - nonlinear = options["nonlinear"].withDefault(true); - - // Toroidal filtering - filter_z = options["filter_z"].withDefault(false); // Filter a single n - filter_z_mode = options["filter_z_mode"].withDefault(1); - - // Set default values for terms in each equation - // Allows default to be overridden in BOUT.inp file - auto& option_rho = globalOptions["rho"]; - evolve_rho = option_rho["evolve_rho"].withDefault(true); - rho_jpar1 = option_rho["rho_jpar1"].withDefault(false); - rho_nuin_rho1 = option_rho["rho_nuin_rho1"].withDefault(false); - rho_rho1 = option_rho["rho_rho1"].withDefault(false); - rho_rho0_phi1 = option_rho["rho_rho0_phi1"].withDefault(false); - rho_rho1_phi0 = option_rho["rho_rho1_phi0"].withDefault(false); - rho_ve2lin = option_rho["rho_ve2lin"].withDefault(false); - rho_rho1_phi1 = option_rho["rho_rho1_phi1"].withDefault(false); - rho_ve2t = option_rho["rho_ve2t"].withDefault(false); - rho_diff = option_rho["rho_diff"].withDefault(false); - - auto& option_ni = globalOptions["ni"]; - evolve_ni = option_ni["evolve_ni"].withDefault(true); - ni_jpar1 = option_ni["ni_jpar1"].withDefault(false); - ni_ni0_phi1 = option_ni["ni_ni0_phi1"].withDefault(false); - ni_ni1_phi0 = option_ni["ni_ni1_phi0"].withDefault(false); - ni_ni1_phi1 = option_ni["ni_ni1_phi1"].withDefault(false); - ni_src_ni0 = option_ni["ni_src_ni0"].withDefault(false); - ni_diff = option_ni["ni_diff"].withDefault(false); - - auto& option_ajpar = globalOptions["ajpar"]; - evolve_ajpar = option_ajpar["evolve_ajpar"].withDefault(true); - ajpar_phi1 = option_ajpar["ajpar_phi1"].withDefault(false); - ajpar_jpar1 = option_ajpar["ajpar_jpar1"].withDefault(false); - ajpar_te_ni = option_ajpar["ajpar_te_ni"].withDefault(false); - ajpar_te = option_ajpar["ajpar_te"].withDefault(false); - ajpar_ajpar1_phi0 = option_ajpar["ajpar_ajpar1_phi0"].withDefault(false); - ajpar_ajpar1_phi1 = option_ajpar["ajpar_ajpar1_phi1"].withDefault(false); - ajpar_ve1_ve1 = option_ajpar["ajpar_ve1_ve1"].withDefault(false); - - auto& option_te = globalOptions["te"]; - evolve_te = option_te["evolve_te"].withDefault(true); - te_te1_phi0 = option_te["te_te1_phi0"].withDefault(false); - te_te0_phi1 = option_te["te_te0_phi1"].withDefault(false); - te_te1_phi1 = option_te["te_te1_phi1"].withDefault(false); - te_ajpar_te = option_te["te_ajpar_te"].withDefault(false); - te_te_ajpar = option_te["te_te_ajpar"].withDefault(false); - te_nu_te1 = option_te["te_nu_te1"].withDefault(false); - te_nu_tet = option_te["te_nu_tet"].withDefault(false); - te_jpar = option_te["te_jpar"].withDefault(false); - te_diff = option_te["te_diff"].withDefault(false); - - if (ZeroElMass) { - evolve_ajpar = false; // Don't need ajpar - calculated from ohm's law - } - - /************* SHIFTED RADIAL COORDINATES ************/ - - // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault( - "identity"); - - if (lowercase(ptstr) == "shifted") { - ShearFactor = 0.0; // I disappears from metric - b0xcv.z += I * b0xcv.x; - } - - /************** CALCULATE PARAMETERS *****************/ - - rho_s = 1.02 * sqrt(AA * Te_x) / ZZ / bmag; - fmei = 1. / 1836.2 / AA; - - lambda_ei = 24. - log(sqrt(Ni_x) / Te_x); - lambda_ii = 23. - log(ZZ * ZZ * ZZ * sqrt(2. * Ni_x) / pow(Ti_x, 1.5)); - wci = 9.58e3 * ZZ * bmag / AA; - nueix = 2.91e-6 * Ni_x * lambda_ei / pow(Te_x, 1.5); - nuiix = 4.78e-8 * pow(ZZ, 4.) * Ni_x * lambda_ii / pow(Ti_x, 1.5) / sqrt(AA); - nu_hat = zeff * nueix / wci; - mui_hat = 0.96 * wci / nuiix * pow(Ti_x / Te_x, -1.5); - - if (estatic) { - beta_p = 1.e-29; - } else { - beta_p = 4.03e-11 * Ni_x * Te_x / bmag / bmag; - } - - Vi_x = wci * rho_s; - - output.write("Collisions: nueix = {:e}, nu_hat = {:e}\n", nueix, nu_hat); - - /************** PRINT Z INFORMATION ******************/ - - BoutReal hthe0; - if (mesh->get(hthe0, "hthe0") == 0) { - output.write( - " ****NOTE: input from BOUT, Z length needs to be divided by {:e}\n", - hthe0 / rho_s); - } - - /************** SHIFTED GRIDS LOCATION ***************/ - - // Velocities defined on cell boundaries - ajpar.setLocation(CELL_YLOW); - - // Apar and jpar too - Apar.setLocation(CELL_YLOW); - jpar.setLocation(CELL_YLOW); - - /************** NORMALISE QUANTITIES *****************/ - - output.write("\tNormalising to rho_s = {:e}\n", rho_s); - - // Normalise profiles - Ni0 /= Ni_x / 1.0e14; - Ti0 /= Te_x; - Te0 /= Te_x; - phi0 /= Te_x; - Vi0 /= Vi_x; - - // Normalise curvature term - b0xcv.x /= (bmag / 1e4); - b0xcv.y *= rho_s * rho_s; - b0xcv.z *= rho_s * rho_s; - - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - I *= rho_s * rho_s * (bmag / 1e4) * ShearFactor; - coord->dx /= rho_s * rho_s * (bmag / 1e4); - - // Normalise magnetic field - Bpxy /= (bmag / 1.e4); - Btxy /= (bmag / 1.e4); - coord->Bxy /= (bmag / 1.e4); - - // calculate pressures - pei0 = (Ti0 + Te0) * Ni0; - pe0 = Te0 * Ni0; - - /**************** CALCULATE METRICS ******************/ - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); - - rho0 = Ni0 * Delp2(phi0) + Perp_Grad_dot_Grad(phi0, Ni0); - - /**************** SET EVOLVING VARIABLES *************/ - - // Tell BOUT++ which variables to evolve - // add evolving variables to the communication object - if (evolve_rho) { - SOLVE_FOR(rho); - comms.add(rho); - } else { - initial_profile("rho", rho); - } - - if (evolve_ni) { - SOLVE_FOR(ni); - comms.add(ni); - } else { - initial_profile("ni", ni); - } - - if (evolve_ajpar) { - SOLVE_FOR(ajpar); - comms.add(ajpar); - } else { - initial_profile("ajpar", ajpar); - if (ZeroElMass) { - dump.add(ajpar, "ajpar", 1); // output calculated Ajpar - } - } - - if (evolve_te) { - SOLVE_FOR(te); - comms.add(te); - } else { - initial_profile("te", te); - } - - // Set boundary conditions on jpar and VEt - jpar.setBoundary("jpar"); - VEt.setBoundary("VEt"); - - if (evolve_source_ni) { - SOLVE_FOR(Sn); - } - if (input_source) { - mesh->get(Sn, "Sn"); - dump.add(Sn, "Sn"); - } - - if (evolve_source_te) { - SOLVE_FOR(St); - } - - /************** SETUP COMMUNICATIONS **************/ - - // add extra variables to communication - comms.add(phi); - - /*************** DUMP VARIABLES TO OUTPUT**********/ - dump.add(phi, "phi", 1); - dump.add(jpar, "jpar", 1); - - SAVE_ONCE(Ni0, Te0, phi0, rho0); - SAVE_ONCE(Rxy, Bpxy, Btxy, Zxy, hthe); - dump.addOnce(coord->Bxy, "Bxy"); - dump.addOnce(my_ixseps, "ixseps"); - - SAVE_ONCE(Te_x, Ti_x, Ni_x); - SAVE_ONCE(AA, ZZ, zeff, rho_s, wci, bmag); - dump.addOnce(mesh->LocalNx, "ngx"); - dump.addOnce(mesh->LocalNy, "ngy"); - dump.addOnce(mesh->LocalNz, "ngz"); - SAVE_ONCE(mui_hat, nu_hat, nuIonNeutral, beta_p, time_step, hthe0); - SAVE_ONCE(ni_perpdiff, rho_perpdiff, te_perpdiff); - - // Laplacian inversion solver - phiSolver = Laplacian::create(); - phiSolver->setCoefC(Ni0); - - return 0; - } - - ////////////////////////////////////// - - ////////////////////////////////////// - /// Function called at each time step - /// Time derivatives calculated here - int rhs(BoutReal t) { - - Coordinates* coord = mesh->getCoordinates(); - - // Invert vorticity to get phi - - // Solves \nabla^2_\perp x + (1./c)*\nabla_perp c\cdot\nabla_\perp x + a x = b - // Arguments are: (b, bit-field, a, c) - // Passing NULL -> missing term - if (nonlinear) { - phi = phiSolver->solve(rho / (Ni0 + ni)); - } else { - phi = phiSolver->solve(rho / Ni0); - } - - // Communicate variables - mesh->communicate(comms); - - // Update profiles - if (nonlinear) { - Nit = Ni0 + ni; - phit = phi0 + phi; - Tit = Ti0; - Tet = Te0 + te; - } else { - Nit = Ni0; - phit = phi0; - Tit = Ti0; - Tet = Te0; - } - - BoutReal source_alpha; - - // Calculate source response - if (source_converge > 0.) { - source_alpha = source_response * exp(-1. * t / source_converge); - } else { - source_alpha = source_response; - } - - // Exit if the density goes negative - if (nonlinear && min(Nit) < 0.0) { - output.enable(); // Use stdout for the next line - throw BoutException("Unphysical negative density encountered. Exiting...\n"); - } - - // Exit if the temperature goes negative or make negatives zero - if (nonlinear && evolve_te && min(Tet) < 0.0) { - output.enable(); // Use stdout for the next line - throw BoutException("Unphysical negative temperature encountered. Exiting...\n"); - } - - // Update non-linear coefficients - nu = nu_hat * Nit / pow(Tet, 1.5); - mu_i = mui_hat * pow(Tit, 2.5) / Nit; - //kapa_Te = 3.2*(1./fmei)*(wci/nueix)*pow(Tet,2.5); - //kapa_Ti = 3.9*(wci/nuiix)*(Tit^2.5); - - // Calculate pressures - //pei = (Tet+Tit)*Nit; - //pe = Tet*Nit; - - // Calculate E cross B velocity - if (nonlinear) { - VEt = sqrt(coord->g11 * DDX(phit) * DDX(phit) + coord->g33 * DDZ(phit) * DDZ(phit)); - - // Set boundary condition on VEt - VEt.applyBoundary(); - - // Communicate VEt - mesh->communicate(VEt); - } - - if (ZeroElMass) { - // Set jpar,Ve,Ajpar neglecting the electron inertia term - jpar = (interp_to(Tet, CELL_YLOW) * Grad_par(ni, CELL_YLOW) - - interp_to(Nit, CELL_YLOW) * Grad_par(phi, CELL_YLOW)) - / (fmei * 0.51 * nu); - - // Set boundary condition on jpar - jpar.applyBoundary(); - - // Need to communicate jpar - mesh->communicate(jpar); - - Ve = -jpar / interp_to(Nit, CELL_YLOW); - ajpar = Ve; - } else { - - Ve = ajpar; - jpar = -interp_to(Nit, CELL_YLOW) * Ve; - //jpar = -Ni0*Ve; //Linearize as in BOUT06 - } - ////////////////////////////////////////////////////////////////////////////////////////// - // DENSITY EQUATION - - ddt(ni) = 0.0; - if (evolve_ni) { - - if (ni_ni0_phi1) { - ddt(ni) -= DDX(Ni0) * DDZ(phi); - } - - if (ni_ni1_phi0) { - ddt(ni) -= vE_Grad(ni, phi0); - } - - if (ni_ni1_phi1) { - ddt(ni) -= vE_Grad(ni, phi); - } - - if (ni_jpar1) { - ddt(ni) += Grad_par(jpar, CELL_CENTRE); // Left hand differencing - } - - if (ni_src_ni0) { - ddt(ni) += src_ni0; - } - - if (ni_diff) { - ddt(ni) += ni_perpdiff * Delp2(ni); - } - - if (evolve_source_ni) { - ddt(Sn) = averageY(-1. * source_alpha * DC(ni) / Ni0); - - // Add density source/sink - ddt(ni) += Sn * where(Sn, Ni0, Nit); // Sn*Ni0 if Sn > 0, Sn*Nit if Sn < 0 - } - - if (remove_tor_av_ni) { - ddt(ni) -= DC(ddt(ni)); // REMOVE TOROIDAL AVERAGE DENSITY - } - } - /////////////////////////////////////////////////////////////////////////////////////////// - // VORTICITY - - ddt(rho) = 0.0; - if (evolve_rho) { - - if (rho_jpar1) { - ddt(rho) += Grad_par(jpar, CELL_CENTRE); // Left hand differencing - } - - if (rho_nuin_rho1) { - ddt(rho) -= nuIonNeutral * rho; - } - - if (rho_rho1) { - ddt(rho) += mu_i * Delp2(rho); - } - - if (rho_diff) { - ddt(rho) += rho_perpdiff * Delp2(rho); - } - - if (rho_rho1_phi1) { - ddt(rho) -= vE_Grad(rho, phi); - } - - if (rho_rho0_phi1) { - ddt(rho) -= vE_Grad(rho0, phi); - } - - if (rho_rho1_phi0) { - ddt(rho) -= vE_Grad(rho, phi0); - } - - if (rho_ve2lin) { - ddt(rho) -= coord->g11 * coord->g33 * DDX(phi0) - * (DDX(Ni0) * D2DXDZ(phi) - D2DX2(phi0) * DDZ(ni)); - } - - if (rho_ve2t) { - ddt(rho) += VEt * vE_Grad(VEt, Nit); - } - } - - ///////////////////////////////////////////////////////////////////////////////////// - // AJPAR - - ddt(ajpar) = 0.0; - if (evolve_ajpar) { - - if (ajpar_phi1) { - ddt(ajpar) += - (1. / fmei) - * Grad_par(phi, - CELL_YLOW); // Right-hand deriv with b.c. Necessary for sheath mode - } - - if (ajpar_jpar1) { - ddt(ajpar) -= 0.51 * interp_to(nu, CELL_YLOW) * ajpar; - } - - if (ajpar_te_ni) { - ddt(ajpar) -= - (1. / fmei) * interp_to(Tet / Nit, CELL_YLOW) * Grad_par(ni, CELL_YLOW); - } - - if (ajpar_te) { - ddt(ajpar) -= (1.71 / fmei) * Grad_par(te, CELL_YLOW); - } - - if (ajpar_ajpar1_phi0) { - ddt(ajpar) -= vE_Grad(ajpar, interp_to(phi0, CELL_YLOW)); - } - - if (ajpar_ajpar1_phi1) { - ddt(ajpar) -= vE_Grad(ajpar, interp_to(phi, CELL_YLOW)); - } - - if (ajpar_ve1_ve1) { - ddt(ajpar) -= Vpar_Grad_par(ajpar, ajpar); - } - } - - ///////////////////////////////////////////////////////////////////////////////////////// - // TEMPERATURE EQUATION - - ddt(te) = 0.0; - if (evolve_te) { - - if (te_te0_phi1) { - ddt(te) -= vE_Grad(Te0, phi); - } - - if (te_te1_phi0) { - ddt(te) -= vE_Grad(te, phi0); - } - - if (te_te1_phi1) { - ddt(te) -= vE_Grad(te, phi); - } - - if (te_ajpar_te) { - ddt(te) -= interp_to(ajpar, CELL_CENTRE) * Grad_par(te); - } - - if (te_te_ajpar) { - ddt(te) -= 2. / 3. * Tet * Grad_par(ajpar, CELL_CENTRE); - } - - if (te_nu_te1) { - ddt(te) -= 2. * fmei * nu_hat / sqrt(Te0) - * (ni - 1. / 2. * Ni0 / Te0 * te); // Explicitly linear - } - - if (te_nu_tet) { - ddt(te) -= 2. * fmei * (nu * Tet - nu_hat * Ni0 / sqrt(Te0)); // All Nonlinear - } - - if (te_jpar) { - ddt(te) += 0.71 * 2. / 3. * Tet / Nit * Grad_par(jpar, CELL_CENTRE); - } - - if (te_diff) { - ddt(te) += te_perpdiff * Delp2(te); - } - - if (remove_tor_av_te) { - ddt(te) -= DC(ddt(te)); // REMOVE TOROIDAL AVERAGE TEMPERATURE - } - - if (evolve_source_te) { - // Evolve source - ddt(St) = averageY(-1. * source_alpha * DC(te) / Te0); - - // Add heat source/sink - ddt(te) += St * where(St, Te0, Tet); - } - - // There is an ion collision term that can be added with finite T_i - } - - ///////////////////////////////////////////////////////////////////////////////////////// - // Z filtering - if (filter_z) { - // Filter out all except filter_z_mode - - ddt(rho) = filter(ddt(rho), filter_z_mode); - ddt(ni) = filter(ddt(ni), filter_z_mode); - ddt(ajpar) = filter(ddt(ajpar), filter_z_mode); - ddt(te) = filter(ddt(te), filter_z_mode); - } - - return 0; - } - - ///////////////////////////////////////////////////////////////// - - /****************SPECIAL DIFFERENTIAL OPERATORS******************/ - Coordinates::FieldMetric Perp_Grad_dot_Grad(const Field2D& p, const Field2D& f) { - - return DDX(p) * DDX(f) * mesh->getCoordinates()->g11; - } - - ///////////////////////////////////////////////////////////////// - // ExB terms. These routines allow comparisons with BOUT-06 - // if bout_exb=true is set in BOUT.inp - ///////////////////////////////////////////////////////////////// - Coordinates::FieldMetric vE_Grad(const Field2D& f, const Field2D& p) { - Coordinates::FieldMetric result; - if (bout_exb) { - // Use a subset of terms for comparison to BOUT-06 - result = 0.0; - } else { - // Use full expression with all terms - - result = b0xGrad_dot_Grad(p, f) / mesh->getCoordinates()->Bxy; - } - return result; - } - - const Field3D vE_Grad(const Field2D& f, const Field3D& p) { - Coordinates* coord = mesh->getCoordinates(); - Field3D result; - if (arakawa) { - // Arakawa scheme for perpendicular flow. Here as a test - - result.allocate(); - - int ncz = mesh->LocalNz; - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { - for (int jy = mesh->ystart; jy <= mesh->yend; jy++) { - for (int jz = 0; jz < ncz; jz++) { - int jzp = (jz + 1) % ncz; - int jzm = (jz - 1 + ncz) % ncz; - - // J++ = DDZ(p)*DDX(f) - DDX(p)*DDZ(f) - BoutReal Jpp = - 0.25 - * ((p(jx, jy, jzp) - p(jx, jy, jzm)) * (f(jx + 1, jy) - f(jx - 1, jy)) - - (p(jx + 1, jy, jz) - p(jx - 1, jy, jz)) * (f(jx, jy) - f(jx, jy))) - / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); - - // J+x - BoutReal Jpx = 0.25 - * (f(jx + 1, jy) * (p(jx + 1, jy, jzp) - p(jx + 1, jy, jzm)) - - f(jx - 1, jy) * (p(jx - 1, jy, jzp) - p(jx - 1, jy, jzm)) - - f(jx, jy) * (p(jx + 1, jy, jzp) - p(jx - 1, jy, jzp)) - + f(jx, jy) * (p(jx + 1, jy, jzm) - p(jx - 1, jy, jzm))) - / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); - // Jx+ - BoutReal Jxp = 0.25 - * (f(jx + 1, jy) * (p(jx, jy, jzp) - p(jx + 1, jy, jz)) - - f(jx - 1, jy) * (p(jx - 1, jy, jz) - p(jx, jy, jzm)) - - f(jx - 1, jy) * (p(jx, jy, jzp) - p(jx - 1, jy, jz)) - + f(jx + 1, jy) * (p(jx + 1, jy, jz) - p(jx, jy, jzm))) - / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); - - result(jx, jy, jz) = (Jpp + Jpx + Jxp) / 3.; - } - } - } - - } else if (bout_exb) { - // Use a subset of terms for comparison to BOUT-06 - result = VDDX(DDZ(p), f); - } else { - // Use full expression with all terms - result = b0xGrad_dot_Grad(p, f) / coord->Bxy; - } - return result; - } - - const Field3D vE_Grad(const Field3D& f, const Field2D& p) { - Field3D result; - if (bout_exb) { - // Use a subset of terms for comparison to BOUT-06 - result = VDDZ(-DDX(p), f); - } else { - // Use full expression with all terms - result = b0xGrad_dot_Grad(p, f) / mesh->getCoordinates()->Bxy; - } - return result; - } - - const Field3D vE_Grad(const Field3D& f, const Field3D& p) { - Field3D result; - - Coordinates* coord = mesh->getCoordinates(); - if (arakawa) { - // Arakawa scheme for perpendicular flow. Here as a test - - result.allocate(); - - int ncz = mesh->LocalNz; - for (int jx = mesh->xstart; jx <= mesh->xend; jx++) { - for (int jy = mesh->ystart; jy <= mesh->yend; jy++) { - for (int jz = 0; jz < ncz; jz++) { - int jzp = (jz + 1) % ncz; - int jzm = (jz - 1 + ncz) % ncz; - - // J++ = DDZ(p)*DDX(f) - DDX(p)*DDZ(f) - BoutReal Jpp = 0.25 - * ((p(jx, jy, jzp) - p(jx, jy, jzm)) - * (f(jx + 1, jy, jz) - f(jx - 1, jy, jz)) - - (p(jx + 1, jy, jz) - p(jx - 1, jy, jz)) - * (f(jx, jy, jzp) - f(jx, jy, jzm))) - / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); - - // J+x - BoutReal Jpx = - 0.25 - * (f(jx + 1, jy, jz) * (p(jx + 1, jy, jzp) - p(jx + 1, jy, jzm)) - - f(jx - 1, jy, jz) * (p(jx - 1, jy, jzp) - p(jx - 1, jy, jzm)) - - f(jx, jy, jzp) * (p(jx + 1, jy, jzp) - p(jx - 1, jy, jzp)) - + f(jx, jy, jzm) * (p(jx + 1, jy, jzm) - p(jx - 1, jy, jzm))) - / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); - // Jx+ - BoutReal Jxp = 0.25 - * (f(jx + 1, jy, jzp) * (p(jx, jy, jzp) - p(jx + 1, jy, jz)) - - f(jx - 1, jy, jzm) * (p(jx - 1, jy, jz) - p(jx, jy, jzm)) - - f(jx - 1, jy, jzp) * (p(jx, jy, jzp) - p(jx - 1, jy, jz)) - + f(jx + 1, jy, jzm) * (p(jx + 1, jy, jz) - p(jx, jy, jzm))) - / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); - - result(jx, jy, jz) = (Jpp + Jpx + Jxp) / 3.; - } - } - } - - } else if (bout_exb) { - // Use a subset of terms for comparison to BOUT-06 - result = VDDX(DDZ(p), f) + VDDZ(-DDX(p), f); - } else { - // Use full expression with all terms - result = b0xGrad_dot_Grad(p, f) / coord->Bxy; - } - return result; - } -}; - -BOUTMAIN(LAPDdrift); diff --git a/examples/lapd-drift/pisces/BOUT.inp b/examples/lapd-drift/pisces/BOUT.inp deleted file mode 100644 index 90805f843e..0000000000 --- a/examples/lapd-drift/pisces/BOUT.inp +++ /dev/null @@ -1,241 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -nout = 400 # number of time-steps -timestep = 1 # time between outputs - -MZ = 32 # number of points in z direction (2^n + 1) -zperiod = 5 # Number of periods - -non_uniform = true - -[mesh] -# Simple mesh for linear device - -staggergrids = true # Enable staggered grids - -nx = 68 # Number of radial grid points, including guards -ny = 64 # Number of parallel (Y) grid points - -Length = 1 # length of machine in meters -Rmin = 0.005 # minimum radius in meters -Rmax = 0.05 # maximum radius - -Bxy = 0.15 # magnetic field in Tesla - -Ni0 = 1e-3 + 1e-2*exp(-(x/0.5)^2) # Density in units of 10^20 m^-3 -Te0 = 5 # Electron temperature in eV -Ti0 = 0.1 # Ion temperature in eV - -Ni_x = 0.01 # Density normalisation in units of 10^20 m^-3 -Te_x = 2 # Electron normalisation in eV -Ti_x = Te_x # Ion normalisation in eV -bmag = 0.15 # Magnetic field normalisation in Tesla - -Bpxy = Bxy -Btxy = 0 -hthe = 1 -dy = length / ny - -Rxy = Rmin + (Rmax - Rmin) * x - -dr = (Rmax - Rmin) / (nx - 4) -dx = Bpxy * Rxy * dr -dpsi = dx - -# ixseps1 and ixseps2 set the radial (x) index of the separatrix -ixseps1 = 10000 # >= nx -> periodic in Y. -1 -> boundaries in Y -ixseps2 = 10000 - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 # C4 = 4th order central, C2 = 2nd order central -second = C4 -upwind = W3 # U1 = 1st order upwind, W3 = 3rd order WENO - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Laplacian inversion settings - -[laplace] - -all_terms = true -nonuniform = true - -################################################## -# Solver settings - -[solver] -type = pvode - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 4.0 -ZZ = 1.0 - -estatic = true # if true, electrostatic (Apar = 0) -ZeroElMass = false # Use Ohms law without electron inertia -zeff = 1.0 # Z effective -nu_perp = 1e-20 - -nuIonNeutral = 0.002 # Ion-neutral collision rate, normalised to wci - -ni_perpdiff = 0.002 -rho_perpdiff = 0.002 -te_perpdiff = 0.002 - -nonlinear = true - -ShearFactor = 0.0 - -arakawa = false # Use Arakawa scheme for ExB advection -bout_exb = true # Use the BOUT-06 subset of ExB terms - -remove_tor_av_ni = true -remove_tor_av_te = false - -evolve_source_ni = false -evolve_source_te = false - -filter_z = false # Filter in Z -filter_z_mode = 1 # Keep this Z harmonic - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) - -phi_flags = 9 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# form of initial profile: -function = mixmode(x)*mixmode(y)*mixmode(z) - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -#bndry_core = relax(neumann) -#bndry_sol = relax(neumann) -#bndry_target = none -bndry_all = neumann - -# Section for only the Ni equation -# Contains switches for terms -[ni] -# Terms always present -evolve_ni = true -ni_jpar1 = true -ni_ni0_phi1 = true -ni_diff = true - -# Linear Terms with phi0 -ni_ni1_phi0 = false - -# Nonlinear Terms -ni_ni1_phi1 = true - -scale = 1e-08 # only perturbing Ni - -# Section for only the rho equation -# Contains switches for terms -[rho] -# Terms always present -evolve_rho = true -rho_jpar1 = true -rho_nuin_rho1 = true # Neutral Damping -rho_rho1 = false # Viscosity -rho_diff = true - -# Linear Terms with phi0 -rho_rho0_phi1 = false -rho_rho1_phi0 = false -rho_ve2lin = false - -# Nonlinear Terms -rho_rho1_phi1 = true -rho_ve2t = false - - -scale = -1e-08 - -bndry_all = dirichlet_o2 - -# Section for only the Ajpar equation -# Contains switches for terms -[ajpar] -# Terms always present -evolve_ajpar = true -ajpar_phi1 = true -ajpar_jpar1 = true -ajpar_te_ni = true -ajpar_te = false - -# Linear Terms with phi0 -ajpar_ajpar1_phi0 = false - -# Nonlinear terms -ajpar_ajpar1_phi1 = true -ajpar_ve1_ve1 = true - - -# Section for only the te equation -# Contains switches for terms -[te] -# Terms always present -evolve_te = false -te_te0_phi1 = false -te_te_ajpar = false -te_nu_te1 = false -te_jpar = false -te_diff = false - -# Linear Terms with phi0 -te_te1_phi0 = false - -# Nonlinear terms -te_te1_phi1 = false -te_ajpar_te = false -te_nu_tet = false diff --git a/examples/lapd-drift/runidl.pro b/examples/lapd-drift/runidl.pro deleted file mode 100644 index d6d2c614e8..0000000000 --- a/examples/lapd-drift/runidl.pro +++ /dev/null @@ -1,33 +0,0 @@ -path="." - - -fdu = path+'/uedge.grd.pdb' - -path=path+"/data" - -du=file_import(fdu) - -ni = collect(var="Ni", path=path) -rho = collect(var="rho", path=path) -phi = collect(var="phi", path=path) -jpar = collect(var="jpar", path=path) - -t_array = collect(var="t_array", path=path) -wci = collect(var="wci", path=path) -rho_s = collect(var="rho_s", path=path) - -; Remove the first time-point (as BOUT-06) -ni = ni[*,*,*,1:*] -rho = rho[*,*,*,1:*] -phi = phi[*,*,*,1:*] -jpar=jpar[*,*,*,1:*] -t_array = t_array[1:*] - -trange = N_ELEMENTS(t_array) - -; Put into a structure to mimic BOUT_FLUC_xyzt -d = {ni_xyzt:ni, rho_xyzt:rho, phi_xyzt:phi, jpar_xyzt:jpar, $ - t_array:t_array, wci:wci, rho_s:rho_s, trange:trange} - -fit_time, d,du - diff --git a/examples/lapd-drift/uedge.grd.nc b/examples/lapd-drift/uedge.grd.nc deleted file mode 100644 index 02f55eeeb3..0000000000 Binary files a/examples/lapd-drift/uedge.grd.nc and /dev/null differ diff --git a/examples/lapd-drift/uedge.grd.pdb b/examples/lapd-drift/uedge.grd.pdb deleted file mode 100644 index 88a3939336..0000000000 Binary files a/examples/lapd-drift/uedge.grd.pdb and /dev/null differ diff --git a/examples/lapd-drift/zero_cross.pro b/examples/lapd-drift/zero_cross.pro deleted file mode 100644 index d01e14497d..0000000000 --- a/examples/lapd-drift/zero_cross.pro +++ /dev/null @@ -1,70 +0,0 @@ -FUNCTION ZERO_CROSS, $ - Data, $ - SUBSTRACT_MEAN=subtract_meanopt, $ - POS=pos - -;*********************************************************************** -; Constants and Options - -; Length of the time series -nx = n_elements( data ) - -; We need to know if we need to use long integers for indices - idtype = 1 - -; Copy data -x = data -; Subtract mean if desired -;if keyword_set( subtract_meanopt ) then x = x - mean( x ) - -; Initialise zero crossing counter -nzeroes = 0 - -; Initialise zero crossing position vector -pos = [ -1 ] - -;*********************************************************************** -; Determine the Location of the Zero Crossings - -; Calculate the products of neighbouring values -signx = x[0*idtype:nx-2] * x[1*idtype:nx-1] - -; Iterate through values -for i = 0 * idtype, nx - 2 do begin - - ; If the product of neighbouring values is negative, the values are of - ; different sign and so there was a zero crossing between them. - if signx[i] lt 0 then begin - ; Add this zero crossing to our list - nzeroes = nzeroes + 1 - pos = [ pos, i ] - - ; If the product of neighbouring values is zero, there may still be a zero - ; crossing occurring later. - ; Also check that we are not in the middle of a flat zero region (ie that we - ; have not already counted this crossing). - endif else if ( signx[i] eq 0 ) and ( x[i] ne 0 ) then begin - ; Find the next non-zero value - id = min( where( x[i+1:nx-1] ne 0, nid ) ) - ; If such a value exists - if nid ne 0 then begin - ; If the two values at the end of this zero region are of opposite sign - ; then we have a crossing - if x[i] * x[i+1+id] lt 0 then begin - ; Add this zero crossing to our list. - ; Note we take the location of the middle of the zero region - nzeroes = nzeroes + 1 - pos = [ pos, i + ( id + 1 ) / 2 ] - endif - endif - endif -endfor - -; Remove initialising value from the locations vector -if nzeroes ne 0 then pos = pos[1*idtype:nzeroes] - -;*********************************************************************** -; The End - -return, nzeroes -END diff --git a/examples/laplacexy/alfven-wave/alfven.cxx b/examples/laplacexy/alfven-wave/alfven.cxx index e7a945b3f4..a4248afcf7 100644 --- a/examples/laplacexy/alfven-wave/alfven.cxx +++ b/examples/laplacexy/alfven-wave/alfven.cxx @@ -41,7 +41,7 @@ class Alfven : public PhysicsModel { int init(bool UNUSED(restarting)) { // Normalisation - auto opt = Options::root()["alfven"]; + auto& opt = Options::root()["alfven"]; Tnorm = opt["Tnorm"].withDefault(100); // Reference temperature [eV] Nnorm = opt["Nnorm"].withDefault(1e19); // Reference density [m^-3] Bnorm = opt["Bnorm"].withDefault(1.0); // Reference magnetic field [T] diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index 7881f4ab82..1312b005da 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -65,7 +65,7 @@ int main(int argc, char** argv) { Options::root()["input"] = input; Options::root()["solved"] = solved; - bout::writeDefaultOutputFile(); + bout::writeDefaultOutputFile(Options::root()); BoutFinalise(); return 0; diff --git a/examples/make-script/.gitignore b/examples/make-script/.gitignore deleted file mode 100644 index 9daeafb986..0000000000 --- a/examples/make-script/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/examples/make-script/makefile b/examples/make-script/makefile deleted file mode 100644 index b941125bce..0000000000 --- a/examples/make-script/makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Example makefile. Sources are listed in SOURCEC -# and optionally a TARGET executable name can be given -# It requires that bout-config is in $PATH - -SOURCEC = test.cxx - -############ - -OBJ = $(SOURCEC:%.cxx=%.o) -TARGET ?= $(SOURCEC:%.cxx=%) - -ifeq (, $(shell which bout-config)) -$(error No bout-config in $$PATH ($(PATH))) -endif - -# Use the bout-config script to get compiler, flags -CXX:=$(shell bout-config --cxx) - -CFLAGS:=$(shell bout-config --cflags) -LD:=$(shell bout-config --ld) -LDFLAGS:=$(shell bout-config --libs) - -$(TARGET): makefile $(OBJ) - @echo " Linking" $(TARGET) - $(LD) -o $(TARGET) $(OBJ) $(LDFLAGS) - -%.o: %.cxx - @echo " Compiling " $(@F:.o=.cxx) - $(CXX) $(CFLAGS) -c $(@F:.o=.cxx) -o $@ - -.PHONY: clean -clean: - rm $(OBJ) $(TARGET) - diff --git a/examples/make-script/test.cxx b/examples/make-script/test.cxx deleted file mode 100644 index 8086e7a9e3..0000000000 --- a/examples/make-script/test.cxx +++ /dev/null @@ -1,22 +0,0 @@ -/* - */ - -#include - -class Test : public PhysicsModel { -private: - Field2D f; - -public: - int init(bool) override { - SOLVE_FOR(f); - return 0; - } - - int rhs(BoutReal) override { - ddt(f) = -f; - return 0; - } -}; - -BOUTMAIN(Test); diff --git a/examples/monitor/.gitignore b/examples/monitor/.gitignore deleted file mode 100644 index edffd38e3d..0000000000 --- a/examples/monitor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -monitor \ No newline at end of file diff --git a/examples/monitor/CMakeLists.txt b/examples/monitor/CMakeLists.txt deleted file mode 100644 index 7316023256..0000000000 --- a/examples/monitor/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(monitor LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(monitor SOURCES monitor.cxx) diff --git a/examples/monitor/README.md b/examples/monitor/README.md deleted file mode 100644 index b92a6755ae..0000000000 --- a/examples/monitor/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Monitor example -=============== - -Demonstrates how to add monitors to a `Solver` diff --git a/examples/monitor/data/BOUT.inp b/examples/monitor/data/BOUT.inp deleted file mode 100644 index b9de46ae3a..0000000000 --- a/examples/monitor/data/BOUT.inp +++ /dev/null @@ -1,21 +0,0 @@ -timestep = 1.0 -nout = 10 - -MZ = 1 - -[mesh] - -nx = 12 -ny = 8 - -dx = 1.0 -dy = 1.0 - -[solver] -# Set this to true to enable 'my_timestep_monitor' -monitor_timestep = false - -[f] - -scale = 1.0 -function = gauss(x-0.5, 0.3) * gauss(y-0.5,0.3) diff --git a/examples/monitor/monitor.cxx b/examples/monitor/monitor.cxx deleted file mode 100644 index 37825e5ce9..0000000000 --- a/examples/monitor/monitor.cxx +++ /dev/null @@ -1,52 +0,0 @@ -/* - */ - -#include -#include - -/// Create a function to be called every timestep -int my_timestep_monitor(Solver* UNUSED(solver), BoutReal simtime, BoutReal dt) { - output.write("\nTimestep monitor, time = {:e}, dt = {:e}\n", simtime, dt); - return 0; -} - -/// Create a monitor to be called every output step -class MyOutputMonitor : public Monitor { -public: - explicit MyOutputMonitor(BoutReal timestep = -1) : Monitor(timestep){}; - int call(Solver* UNUSED(solver), BoutReal simtime, int iter, int NOUT) override { - output.write("\nOutput monitor, time = {:e}, step {:d} of {:d}\n", simtime, iter, - NOUT); - return 0; - } -}; - -class MonitorExample : public PhysicsModel { - Field2D f; - - /// Create instances of the output monitor - MyOutputMonitor my_output_monitor{}; - /// This output monitor is called twice every output step - MyOutputMonitor my_output_monitor_fast{.5}; - -protected: - int init(bool UNUSED(restarting)) override { - /// Add the output monitors - solver->addMonitor(&my_output_monitor); - solver->addMonitor(&my_output_monitor_fast); - - /// Add the timestep monitor. This also needs to enabled by - /// setting the input value solver:monitor_timestep to true - solver->addTimestepMonitor(my_timestep_monitor); - - SOLVE_FOR(f); - return 0; - } - - int rhs(BoutReal UNUSED(t)) override { - ddt(f) = -f; - return 0; - } -}; - -BOUTMAIN(MonitorExample) diff --git a/examples/orszag-tang/mhd.cxx b/examples/orszag-tang/mhd.cxx index 0e12db0cf4..5b007044c3 100644 --- a/examples/orszag-tang/mhd.cxx +++ b/examples/orszag-tang/mhd.cxx @@ -11,8 +11,6 @@ class MHD : public PhysicsModel { Field3D rho, p; // density, pressure Vector3D v, B; // velocity, magnetic field - Field3D divB; // Divergence of B (for monitoring) - // parameters BoutReal g; bool include_viscos; @@ -50,10 +48,6 @@ class MHD : public PhysicsModel { output.write("dx(0,0,0) = {:e}, dy(0,0,0) = {:e}, dz(0,0,0) = {:e}\n", coord->dx(0, 0, 0), coord->dy(0, 0, 0), coord->dz(0, 0, 0)); - SAVE_REPEAT(divB); - - divB.setBoundary("DivB"); // Set boundary conditions from options - if (!restarting) { // Set variables to these values (+ the initial perturbation) // NOTE: This must be after the calls to bout_solve @@ -71,18 +65,12 @@ class MHD : public PhysicsModel { return 0; } - /// This function is called every output, before - /// the data is written to file. It can therefore be used - /// to calculate diagnostics + /// Add variables to the output. This can be used to calculate + /// diagnostics /// - /// @param[in] simtime Simulation time - /// @param[in] iter Output step - /// @param[in] NOUT Total number of outputs requested - int outputMonitor(BoutReal UNUSED(simtime), int UNUSED(iter), - int UNUSED(NOUT)) override { - // Calculate divergence of magnetic field - divB = Div(B); - return 0; + /// @param[inout] state A nested dictionary that can be added to + void outputVars(Options& state) override { + state["divB"].assignRepeat(Div(B)).setAttributes({{"long_name", "Divergence of B"}}); } int rhs(BoutReal UNUSED(time)) override { diff --git a/examples/performance/bracket/bracket.cxx b/examples/performance/bracket/bracket.cxx index 1b4efa49aa..50012510ff 100644 --- a/examples/performance/bracket/bracket.cxx +++ b/examples/performance/bracket/bracket.cxx @@ -40,8 +40,8 @@ int main(int argc, char** argv) { std::vector times; // Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["performance"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["performance"]; int NUM_LOOPS; NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); bool profileMode, includeHeader, do2D3D, do3D3D; diff --git a/examples/performance/ddx/ddx.cxx b/examples/performance/ddx/ddx.cxx index 3e4a7803f6..b0bad711e6 100644 --- a/examples/performance/ddx/ddx.cxx +++ b/examples/performance/ddx/ddx.cxx @@ -43,8 +43,8 @@ int main(int argc, char** argv) { std::vector times; //Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["performanceIterator"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["performanceIterator"]; int NUM_LOOPS; NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); bool profileMode, includeHeader; diff --git a/examples/performance/ddy/ddy.cxx b/examples/performance/ddy/ddy.cxx index a11e1d52bc..4c9a336c8c 100644 --- a/examples/performance/ddy/ddy.cxx +++ b/examples/performance/ddy/ddy.cxx @@ -43,8 +43,8 @@ int main(int argc, char** argv) { std::vector times; //Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["performanceIterator"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["performanceIterator"]; int NUM_LOOPS; NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); bool profileMode, includeHeader; diff --git a/examples/performance/ddz/ddz.cxx b/examples/performance/ddz/ddz.cxx index 8a7262b1cb..5d3bf2c961 100644 --- a/examples/performance/ddz/ddz.cxx +++ b/examples/performance/ddz/ddz.cxx @@ -43,8 +43,8 @@ int main(int argc, char** argv) { std::vector times; //Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["performanceIterator"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["performanceIterator"]; int NUM_LOOPS; NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); bool profileMode, includeHeader; diff --git a/examples/performance/iterator-offsets/iterator-offsets.cxx b/examples/performance/iterator-offsets/iterator-offsets.cxx index 2376b63578..455df38ea5 100644 --- a/examples/performance/iterator-offsets/iterator-offsets.cxx +++ b/examples/performance/iterator-offsets/iterator-offsets.cxx @@ -42,8 +42,8 @@ int main(int argc, char** argv) { std::vector times; //Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["performanceIterator"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["performanceIterator"]; int NUM_LOOPS; NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); bool profileMode, includeHeader; diff --git a/examples/performance/iterator/iterator.cxx b/examples/performance/iterator/iterator.cxx index af1163d927..7a29b00298 100644 --- a/examples/performance/iterator/iterator.cxx +++ b/examples/performance/iterator/iterator.cxx @@ -37,8 +37,8 @@ int main(int argc, char** argv) { std::vector times; //Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["performanceIterator"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["performanceIterator"]; int NUM_LOOPS; NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); bool profileMode, includeHeader; diff --git a/examples/performance/laplace/laplace.cxx b/examples/performance/laplace/laplace.cxx index 1ebbfb7583..20da9311ad 100644 --- a/examples/performance/laplace/laplace.cxx +++ b/examples/performance/laplace/laplace.cxx @@ -39,8 +39,8 @@ int main(int argc, char** argv) { std::vector times; // Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["LaplaceTest"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["LaplaceTest"]; int NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(1000); ConditionalOutput time_output(Output::getInstance()); diff --git a/examples/performance/tuning_regionblocksize/tuning_regionblocksize.cxx b/examples/performance/tuning_regionblocksize/tuning_regionblocksize.cxx index 521ffede74..cfa7617e64 100644 --- a/examples/performance/tuning_regionblocksize/tuning_regionblocksize.cxx +++ b/examples/performance/tuning_regionblocksize/tuning_regionblocksize.cxx @@ -39,8 +39,8 @@ int main(int argc, char** argv) { std::vector times; // Get options root - auto globalOptions = Options::root(); - auto modelOpts = globalOptions["tuningRegionBlockSize"]; + auto& globalOptions = Options::root(); + auto& modelOpts = globalOptions["tuningRegionBlockSize"]; const int NUM_LOOPS = modelOpts["NUM_LOOPS"].withDefault(100); const int numSteps = modelOpts["numSteps"].withDefault(16); diff --git a/examples/reconnect-2field/.gitignore b/examples/reconnect-2field/.gitignore deleted file mode 100644 index 4e2e9e147e..0000000000 --- a/examples/reconnect-2field/.gitignore +++ /dev/null @@ -1 +0,0 @@ -2field \ No newline at end of file diff --git a/examples/reconnect-2field/2field.cxx b/examples/reconnect-2field/2field.cxx deleted file mode 100644 index ed800e18dd..0000000000 --- a/examples/reconnect-2field/2field.cxx +++ /dev/null @@ -1,354 +0,0 @@ -/***************************************************************************** - * 2 field (Apar, vorticity) model for benchmarking - * simple slab reconnection model - *****************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -class TwoField : public PhysicsModel { -private: - // 2D initial profiles - Field2D Jpar0, Te0, Ni0; - - // 3D evolving fields - Field3D U, Apar; - - // Derived 3D variables - Field3D phi, jpar; - - // External coil field - Field3D Apar_ext, Jpar_ext, Phi0_ext, U0_ext; - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - - // Constants - const BoutReal MU0 = 4.0e-7 * PI; - const BoutReal Charge = 1.60217646e-19; // electron charge e (C) - const BoutReal Mi = 2.0 * 1.67262158e-27; // Ion mass - const BoutReal Me = 9.1093816e-31; // Electron mass - const BoutReal Me_Mi = Me / Mi; // Electron mass / Ion mass - - // normalisation parameters - BoutReal Tenorm, Nenorm, Bnorm; - BoutReal Cs, rho_s, wci, beta_hat; - - BoutReal eta, mu; - - // Poisson brackets: b0 x Grad(f) dot Grad(g) / B = [f, g] - // Method to use: BRACKET_ARAKAWA, BRACKET_STD or BRACKET_SIMPLE - BRACKET_METHOD bm; // Bracket method for advection terms - - bool nonlinear; - bool include_jpar0; - int jpar_bndry; - - std::unique_ptr inv{ - nullptr}; // Parallel inversion class used in preconditioner - - // Coordinate system metric - Coordinates *coord, *coord_ylow; - - // Inverts a Laplacian to get potential - std::unique_ptr phiSolver{nullptr}; - -protected: - int init(bool UNUSED(restarting)) override { - - // Load 2D profiles - GRID_LOAD(Jpar0, Te0, Ni0); - Ni0 *= 1e20; // To m^-3 - - // Coordinate system - coord = mesh->getCoordinates(); - coord = mesh->getCoordinates(CELL_YLOW); - - // Load metrics - GRID_LOAD(Rxy, Bpxy, Btxy, hthe); - mesh->get(coord->Bxy, "Bxy"); - - // Set locations of staggered fields - Apar.setLocation(CELL_YLOW); - - // Read some parameters - auto& options = Options::root()["2field"]; - - // normalisation values - nonlinear = options["nonlinear"].withDefault(false); - include_jpar0 = options["include_jpar0"].withDefault(true); - jpar_bndry = options["jpar_bndry"].withDefault(0); - - eta = options["eta"].doc("Normalised resistivity").withDefault(1e-3); - mu = options["mu"].doc("Normalised vorticity").withDefault(1.e-3); - - switch (options["bracket_method"].withDefault(0)) { - case 0: { - bm = BRACKET_STD; - output << "\tBrackets: default differencing\n"; - break; - } - case 1: { - bm = BRACKET_SIMPLE; - output << "\tBrackets: simplified operator\n"; - break; - } - case 2: { - bm = BRACKET_ARAKAWA; - output << "\tBrackets: Arakawa scheme\n"; - break; - } - case 3: { - bm = BRACKET_CTU; - output << "\tBrackets: Corner Transport Upwind method\n"; - break; - } - default: - output << "ERROR: Invalid choice of bracket method. Must be 0 - 3\n"; - return 1; - } - - /////////////////////////////////////////////////// - // Normalisation - - Tenorm = max(Te0, true); - if (Tenorm < 1) { - Tenorm = 1000; - } - - Nenorm = max(Ni0, true); - if (Nenorm < 1) { - Nenorm = 1.e19; - } - - Bnorm = max(coord->Bxy, true); - - // Sound speed in m/s - Cs = sqrt(Charge * Tenorm / Mi); - - // drift scale - rho_s = Cs * Mi / (Charge * Bnorm); - - // Ion cyclotron frequency - wci = Charge * Bnorm / Mi; - - beta_hat = MU0 * Charge * Tenorm * Nenorm / (Bnorm * Bnorm); - - output << "\tNormalisations:" << endl; - output << "\tCs = " << Cs << endl; - output << "\trho_s = " << rho_s << endl; - output << "\twci = " << wci << endl; - output << "\tbeta_hat = " << beta_hat << endl; - - SAVE_ONCE(Tenorm, Nenorm, Bnorm); - SAVE_ONCE(Cs, rho_s, wci, beta_hat); - - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - coord->dx /= rho_s * rho_s * Bnorm; - - // Normalise magnetic field - Bpxy /= Bnorm; - Btxy /= Bnorm; - coord->Bxy /= Bnorm; - - // Plasma quantities - Jpar0 /= Nenorm * Charge * Cs; - - // CALCULATE METRICS - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = 0.; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11; - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = 0.; - coord->g_13 = 0.; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); - - // Tell BOUT++ which variables to evolve - SOLVE_FOR(U, Apar); - - // Set boundary conditions - jpar.setBoundary("jpar"); - phi.setBoundary("phi"); - - // Add any other variables to be dumped to file - SAVE_REPEAT(phi, jpar); - SAVE_ONCE(Jpar0); - - // Generate external field - - initial_profile("Apar_ext", Apar_ext); - Jpar_ext = -Delp2(Apar_ext); - SAVE_ONCE(Apar_ext, Jpar_ext); - - initial_profile("Phi0_ext", Phi0_ext); - U0_ext = -Delp2(Phi0_ext) / coord->Bxy; - SAVE_ONCE(Phi0_ext, U0_ext); - - // Give the solver the preconditioner function - setPrecon(&TwoField::precon); - - // Initialise parallel inversion class - inv = InvertPar::create(); - inv->setCoefA(1.0); - U.setBoundary("U"); - Apar.setBoundary("Apar"); - - // Create a solver for the Laplacian - phiSolver = Laplacian::create(); - - return 0; - } - - const Field3D Grad_parP(const Field3D& f, CELL_LOC loc = CELL_DEFAULT) { - Field3D result; - if (nonlinear) { - result = ::Grad_parP((Apar + Apar_ext) * beta_hat, f); - } else { - result = ::Grad_parP(Apar_ext * beta_hat, f); - } - if (mesh->StaggerGrids) { - mesh->communicate(result); - } - return interp_to(result, loc); - } - - int rhs(BoutReal UNUSED(time)) override { - // Solve EM fields - - // U = (1/B) * Delp2(phi) - phi = phiSolver->solve(coord->Bxy * U); - phi.applyBoundary(); // For target plates only - - mesh->communicate(U, phi, Apar); - - jpar = -Delp2(Apar + Apar_ext); // total Apar - jpar.applyBoundary(); - mesh->communicate(jpar); - - if (jpar_bndry > 0) { - // Boundary in jpar - if (mesh->firstX()) { - for (int i = jpar_bndry; i >= 0; i--) { - for (int j = 0; j < mesh->LocalNy; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - jpar(i, j, k) = jpar(i + 1, j, k); - } - } - } - } - if (mesh->lastX()) { - for (int i = mesh->LocalNx - jpar_bndry - 1; i < mesh->LocalNx; i++) { - for (int j = 0; j < mesh->LocalNy; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - jpar(i, j, k) = jpar(i - 1, j, k); - } - } - } - } - } - - // VORTICITY - ddt(U) = SQ(coord->Bxy) * Grad_parP(jpar / coord_ylow->Bxy, CELL_CENTRE); - - if (include_jpar0) { - ddt(U) -= - SQ(coord->Bxy) * beta_hat - * interp_to(bracket(Apar + Apar_ext, Jpar0 / coord_ylow->Bxy, BRACKET_ARAKAWA), - CELL_CENTRE); - } - - ddt(U) -= bracket(Phi0_ext, U, bm); // ExB advection - // ddt(U) -= bracket(phi, U0_ext, bm); // ExB advection - if (nonlinear) { - ddt(U) -= bracket(phi, U, bm); // ExB advection - } - - if (mu > 0.) { - ddt(U) += mu * Delp2(U); - } - - // APAR - - ddt(Apar) = -Grad_parP(phi, CELL_YLOW) / beta_hat; - ddt(Apar) += -Grad_parP(Phi0_ext, CELL_YLOW) / beta_hat; - - if (eta > 0.) { - ddt(Apar) -= eta * jpar / beta_hat; - } - - return 0; - } - -public: - /********************************************************* - * Preconditioner - * - * o System state in variables (as in rhs function) - * o Values to be inverted in time derivatives - * - * o Return values should be in time derivatives - * - *********************************************************/ - int precon(BoutReal UNUSED(t), BoutReal gamma, BoutReal UNUSED(delta)) { - mesh->communicate(ddt(Apar)); - Field3D Jp = -Delp2(ddt(Apar)); - mesh->communicate(Jp); - - if (jpar_bndry > 0) { - // Boundary in jpar - if (mesh->firstX()) { - for (int i = jpar_bndry; i >= 0; i--) { - for (int j = 0; j < mesh->LocalNy; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - Jp(i, j, k) = Jp(i + 1, j, k); - } - } - } - } - if (mesh->lastX()) { - for (int i = mesh->LocalNx - jpar_bndry - 1; i < mesh->LocalNx; i++) { - for (int j = 0; j < mesh->LocalNy; j++) { - for (int k = 0; k < mesh->LocalNz; k++) { - Jp(i, j, k) = Jp(i - 1, j, k); - } - } - } - } - } - - Field3D U1 = - ddt(U) + gamma * SQ(coord->Bxy) * Grad_par(Jp / coord_ylow->Bxy, CELL_CENTRE); - - inv->setCoefB(-SQ(gamma * coord->Bxy) / beta_hat); - ddt(U) = inv->solve(U1); - ddt(U).applyBoundary(); - - Field3D phip = phiSolver->solve(coord->Bxy * ddt(U)); - mesh->communicate(phip); - - ddt(Apar) = ddt(Apar) - (gamma / beta_hat) * Grad_par(phip, CELL_YLOW); - ddt(Apar).applyBoundary(); - - return 0; - } -}; - -BOUTMAIN(TwoField); diff --git a/examples/reconnect-2field/CMakeLists.txt b/examples/reconnect-2field/CMakeLists.txt deleted file mode 100644 index 8c6f40da80..0000000000 --- a/examples/reconnect-2field/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(reconnect-2field LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(reconnect-2field - SOURCES 2field.cxx - EXTRA_FILES slab_68x32.nc) diff --git a/examples/reconnect-2field/README.md b/examples/reconnect-2field/README.md deleted file mode 100644 index e631079e91..0000000000 --- a/examples/reconnect-2field/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Magnetic Reconnection -===================== - -2 field (Apar, vorticity) model for benchmarking simple slab reconnection model diff --git a/examples/reconnect-2field/data/BOUT.inp b/examples/reconnect-2field/data/BOUT.inp deleted file mode 100644 index e91ec85cad..0000000000 --- a/examples/reconnect-2field/data/BOUT.inp +++ /dev/null @@ -1,149 +0,0 @@ -################################################## -# Global settings used by the core code - -nout = 50 # number of time-steps -timestep = 1000.0 # time between outputs -archive = 20 # Archive restart files after this number of outputs -wall_limit = 4 # wall time limit (in hours) - -twistshift = true # use twist-shift condition? - -MZ = 64 # number of points in z direction (2^n) -zperiod = 1 # Fraction of a torus to simulate - -MXG = 2 -MYG = 2 - -grid = "slab_68x32.nc" # Grid file -restart_format = "nc" # Restart file format - -################################################## -[mesh] -staggergrids = false # Use staggered grids (EXPERIMENTAL) - -symmetricGlobalX = true - -[mesh:paralleltransform] -type = shifted # Use shifted metric method - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 # order of first x derivatives (options are 2 or 4) -second = C4 # order of second x derivatives (2 or 4) -upwind = W3 # order of upwinding method (1, 4, 0 = TVD (DO NOT USE), 3 = WENO) - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 # Z derivatives can be done using FFT -second = C4 -upwind = W3 - -################################################## -# Communications -# Fastest setting depends on machine and MPI -# implementation. Do not affect result. - -[comms] - -async = false # Use asyncronous sends? -pre_post = false # Post receives as early as possible -group_nonblock = false # Use non-blocking group operations? - -################################################## -# Laplacian inversion routines - -[laplace] - -# max_mode = 16 # Maximum N to solve for -all_terms = false -nonuniform = false -filter = 0.2 # Remove the top 20% of modes (BOUT-06 zwindow=0.4) - -################################################## -# FFTs - -[fft] - -fft_measurement_flag = measure # If using FFTW, perform tests to determine fastest method - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-08 # absolute tolerance -rtol = 1e-05 # relative tolerance - -use_precon = false # Use preconditioner: User-supplied or BBD -use_jacobian = false # Use user-supplied Jacobian - -mxstep = 5000 # Number of internal steps between outputs -adams_moulton = false # Use Adams-Moulton method (default is BDF) -func_iter = false # Functional iteration (default is Newton) - -################################################## - -[2field] - -eta = 1e-05 # Resistivity -mu = -1 # Viscosity - -bracket_method = 2 # Method to use for [f,g] terms -# 0 = Use default differencing methods -# 1 = Simplified operator -# 2 = Arakawa scheme -# 3 = Corner Transport Upwind (CTU) - -nonlinear = false # Include nonlinear terms? - -include_jpar0 = false - -jpar_bndry = 3 - -[all] -scale = 0.0 # default size of initial perturbations - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -bndry_all = neumann - -########### Evolving variables - -[Apar] - -function = (1 - 4*(x-0.5)^2 )*sin(3*y - z) -scale = 0.0 - -########### Auxilliary variables - -[phi] -bndry_xin = dirichlet # Radial boundaries specified in inversion -bndry_xout = dirichlet - -########## External field - -[Apar_ext] - -function = (1-4*x*(1-x))*sin(3*y - z) -scale = 0.01 - -[Phi0_ext] -function = x -scale = 0.0 diff --git a/examples/reconnect-2field/slab_68x32.nc b/examples/reconnect-2field/slab_68x32.nc deleted file mode 100644 index 0f66c488b1..0000000000 Binary files a/examples/reconnect-2field/slab_68x32.nc and /dev/null differ diff --git a/examples/shear-alfven-wave/.gitignore b/examples/shear-alfven-wave/.gitignore deleted file mode 100644 index d837f17cae..0000000000 --- a/examples/shear-alfven-wave/.gitignore +++ /dev/null @@ -1 +0,0 @@ -2fluid \ No newline at end of file diff --git a/examples/shear-alfven-wave/2fluid.cxx b/examples/shear-alfven-wave/2fluid.cxx deleted file mode 100644 index a38da9a22a..0000000000 --- a/examples/shear-alfven-wave/2fluid.cxx +++ /dev/null @@ -1,270 +0,0 @@ -/******************************************************************************* - * 2-fluid equations - * Same as Maxim's version of BOUT - simplified 2-fluid for benchmarking - *******************************************************************************/ - -#include - -#include -#include -#include - -class ShearAlfven : public PhysicsModel { -private: - // 2D initial profiles - Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, rho0, Ajpar0; - Vector2D b0xcv; // for curvature terms - - // 3D evolving fields - Field3D rho, Ajpar; - - // Derived 3D variables - Field3D phi, Apar, jpar; - - // pressures - Field3D pei, pe; - Field2D pei0, pe0; - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - - // parameters - BoutReal Te_x, Ti_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; - BoutReal wci; - BoutReal beta_p; - - // settings - bool ZeroElMass; - BoutReal zeff, nu_perp; - BoutReal ShearFactor; - - int phi_flags, apar_flags; // Inversion flags - - // Group fields together for communication - FieldGroup comms; - - // Coordinate system - Coordinates* coord; - - /// Solver for inverting Laplacian - std::unique_ptr phiSolver; - std::unique_ptr aparSolver; - -protected: - int init(bool UNUSED(restarting)) override { - Field2D I; // Shear factor - - output << "Solving 6-variable 2-fluid equations\n"; - - /************* LOAD DATA FROM GRID FILE ****************/ - - // Load 2D profiles (set to zero if not found) - GRID_LOAD(Ni0); - GRID_LOAD(Ti0); - GRID_LOAD(Te0); - GRID_LOAD(Vi0); - GRID_LOAD(Ve0); - GRID_LOAD(phi0); - GRID_LOAD(rho0); - GRID_LOAD(Ajpar0); - - // Coordinate system - coord = mesh->getCoordinates(); - - // Load magnetic curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // b0xkappa terms - - b0xcv *= -1.0; // NOTE: THIS IS FOR 'OLD' GRID FILES ONLY - - // Load metrics - GRID_LOAD(Rxy); - GRID_LOAD(Bpxy); - GRID_LOAD(Btxy); - GRID_LOAD(hthe); - mesh->get(coord->Bxy, "Bxy"); - mesh->get(coord->dx, "dpsi"); - mesh->get(I, "sinty"); - - // Load normalisation values - GRID_LOAD(Te_x); - GRID_LOAD(Ti_x); - GRID_LOAD(Ni_x); - GRID_LOAD(bmag); - - Ni_x *= 1.0e14; - bmag *= 1.0e4; - - /*************** READ OPTIONS *************************/ - - // Read some parameters - auto globalOptions = Options::root(); - auto options = globalOptions["2fluid"]; - AA = options["AA"].withDefault(2.0); - ZZ = options["ZZ"].withDefault(1.0); - - ZeroElMass = options["ZeroElMass"].withDefault(false); - zeff = options["zeff"].withDefault(1.0); - nu_perp = options["nu_perp"].withDefault(0.0); - ShearFactor = options["ShearFactor"].withDefault(1.0); - - /************* SHIFTED RADIAL COORDINATES ************/ - - // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault( - "identity"); - - if (lowercase(ptstr) == "shifted") { - ShearFactor = 0.0; // I disappears from metric - b0xcv.z += I * b0xcv.x; - } - - /************** CALCULATE PARAMETERS *****************/ - - rho_s = 1.02 * sqrt(AA * Te_x) / ZZ / bmag; - fmei = 1. / 1836.2 / AA; - - wci = 9.58e3 * ZZ * bmag / AA; - - beta_p = 4.03e-11 * Ni_x * Te_x / bmag / bmag; - - Vi_x = wci * rho_s; - - /************** PRINT Z INFORMATION ******************/ - - BoutReal hthe0; - if (mesh->get(hthe0, "hthe0") == 0) { - output.write( - " ****NOTE: input from BOUT, Z length needs to be divided by {:e}\n", - hthe0 / rho_s); - } - - /************** SHIFTED GRIDS LOCATION ***************/ - - // Velocities defined on cell boundaries - Ajpar.setLocation(CELL_YLOW); - - // Apar and jpar too - Apar.setLocation(CELL_YLOW); - jpar.setLocation(CELL_YLOW); - - /************** NORMALISE QUANTITIES *****************/ - - output.write("\tNormalising to rho_s = {:e}\n", rho_s); - - // Normalise profiles - Ni0 /= Ni_x / 1.0e14; - Ti0 /= Te_x; - Te0 /= Te_x; - phi0 /= Te_x; - Vi0 /= Vi_x; - - // Normalise curvature term - b0xcv.x /= (bmag / 1e4); - b0xcv.y *= rho_s * rho_s; - b0xcv.z *= rho_s * rho_s; - - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - I *= rho_s * rho_s * (bmag / 1e4) * ShearFactor; - coord->dx /= rho_s * rho_s * (bmag / 1e4); - - // Normalise magnetic field - Bpxy /= (bmag / 1.e4); - Btxy /= (bmag / 1.e4); - coord->Bxy /= (bmag / 1.e4); - - // calculate pressures - pei0 = (Ti0 + Te0) * Ni0; - pe0 = Te0 * Ni0; - - /**************** CALCULATE METRICS ******************/ - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - coord->geometry(); - - /**************** SET EVOLVING VARIABLES *************/ - - // Tell BOUT++ which variables to evolve - // add evolving variables to the communication object - - SOLVE_FOR(rho, Ajpar); - comms.add(rho, Ajpar); - - // Set boundary conditions - jpar.setBoundary("jpar"); - - /************** SETUP COMMUNICATIONS **************/ - - // add extra variables to communication - comms.add(phi); - if (!ZeroElMass) { - comms.add(Apar); - } - - // Add any other variables to be dumped to file - SAVE_REPEAT(phi, Apar, jpar); - - SAVE_ONCE(Ni0, Te0, Ti0); - SAVE_ONCE(Te_x, Ti_x, Ni_x, rho_s, wci); - - // Create a solver for the Laplacian - phiSolver = Laplacian::create(&options["phiSolver"]); - - aparSolver = Laplacian::create(&options["aparSolver"]); - aparSolver->setCoefA((-0.5 * beta_p / fmei) * Ni0); - - return 0; - } - - int rhs(BoutReal UNUSED(t)) override { - // Solve EM fields - - phi = phiSolver->solve(rho / Ni0); - - if (ZeroElMass) { - mesh->communicate(comms); - - Apar = -Ajpar; - jpar = -Delp2(Apar); - - mesh->communicate(jpar); - } else { - - Apar = aparSolver->solve((0.5 * beta_p / fmei) * Ni0 * Ajpar); - - // Communicate variables - mesh->communicate(comms); - - jpar = -Ni0 * (Ajpar + Apar); - } - - // VORTICITY - ddt(rho) = SQ(coord->Bxy) * Div_par(jpar, CELL_CENTRE); - - // AJPAR - - ddt(Ajpar) = (1. / fmei) * Grad_par(phi, CELL_YLOW); - - return 0; - } -}; - -BOUTMAIN(ShearAlfven); diff --git a/examples/shear-alfven-wave/CMakeLists.txt b/examples/shear-alfven-wave/CMakeLists.txt deleted file mode 100644 index 03491f8b33..0000000000 --- a/examples/shear-alfven-wave/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(shear-alfven-wave LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(shear-alfven-wave - SOURCES 2fluid.cxx - EXTRA_FILES uedge.grd_Te_10.nc) diff --git a/examples/shear-alfven-wave/alf_pproc.pro b/examples/shear-alfven-wave/alf_pproc.pro deleted file mode 100644 index 2001679877..0000000000 --- a/examples/shear-alfven-wave/alf_pproc.pro +++ /dev/null @@ -1,53 +0,0 @@ - -du=file_import(fu) - -wci = collect(var="wci", path=path) -rho_s = collect(var="rho_s", path=path) -zmax = collect(var="zmax", path=path) -tt = collect(var="t_array", path=path) / wci -jpar = collect(var="jpar", path=path, x=2, z=10) - - -tt=REFORM(tt) -sig=REFORM(jpar[0,32,0,*]) -xpar=10.*(0.5-findgen(64)/63.) - -tt2=max(tt)*findgen(1000)/999. -sig2=spline(tt,sig,tt2) - -!p.multi=[0,1,2,0,0] - ytit='poloidal coordinate, m' - tit='Pulse bouncing' - contour, TRANSPOSE(reform(jpar[0,*,0,*])),tt,xpar,nlev=11,$ - /xst,/yst,/fil, xtit=xtit, ytit=ytit, tit=tit - ; - xtit='time, s' - tit='Jpar @ x=x0' - plot, tt, sig,/xst,psym=3, xtit=xtit, tit=tit - oplot, tt2, sig2,col=3 - oplot, tt, sig,psym=3 - ; - ;print, 'Click on 1st peak:' - ;mark, x=t0, y=y0 - ;makesym,s=1 - ;for i=1,10 do plots, i*t0, y0, psym=8, syms=2, col=2, thick=3 - Find_Peaks, sig2, tt2, tMax=t0 -!p.multi=0 - - -Bpol=0.5*(min(du.bpxy)+max(du.bpxy)) -Btor=0.5*(min(du.btxy)+max(du.btxy)) -height=max(du.zxy)-min(du.zxy) -Lpar=height*(Btor/Bpol)*1e2 ;[cm] -vPulse=Lpar/t0 -print, 'vPulse = ', vPulse, " cm/s", format='(A10,e12.6,A5)' - -R0=du.R0 -hthe0=du.hthe0 -rho_s=rho_s*1e2 ;[cm] -Ltor=Zmax*2*!pi*R0*100. ;*rho_s/hthe0 -Lperp=Ltor*Bpol/Btor -kperp=2*!Pi/Lperp -print, 'kperp=', kperp, ' cm-1' - -WAIT, 3 diff --git a/examples/shear-alfven-wave/data/BOUT.inp b/examples/shear-alfven-wave/data/BOUT.inp deleted file mode 100644 index 849d97976e..0000000000 --- a/examples/shear-alfven-wave/data/BOUT.inp +++ /dev/null @@ -1,106 +0,0 @@ -# settings file for BOUT++ - -################################################## -# settings used by the core code - -nout = 100 # number of time-steps -timestep = 25.0 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 16 # number of points in z direction (2^n) -ZMIN = 0.0 -ZMAX = 0.00030246 - -MXG = 2 -MYG = 2 - -grid = "uedge.grd_Te_10.nc" - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 # order of first x derivatives -second = C2 # order of second x derivatives -upwind = W3 # order of upwinding method - -[mesh:ddy] - -first = C2 -second = C2 -upwind = W3 - -[mesh:ddz] - -first = FFT -second = FFT -upwind = W3 - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance - -################################################## -# settings for 2fluid - -[2fluid] - -AA = 1.0 -ZZ = 1.0 - -ZeroElMass = false # Use Ohms law without electron inertia -Zeff = 2.0 # Z effective -nu_perp = 1e-20 - -ShearFactor = 0.0 - -[phiSolver] -inner_boundary_flags = 3 # INVERT_DC_GRAD + INVERT_AC_GRAD -outer_boundary_flags = 0 - -[aparSolver] -inner_boundary_flags = 0 -outer_boundary_flags = 0 - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations -function = gauss(y) * sin(z) - -# boundary conditions (see boundary.h for values) -# 0 = none applied -# 1 = zero value -# 2 = zero gradient -# 3 = laplacian -# 4 = laplacian with zero-gradient - -bndry_all = neumann # Zero-gradient on all boundaries - -[Ni] -evolve = false - -[Vi] -evolve = false - -[Te] -evolve = false - -[Ti] -evolve = false - -[Ajpar] -scale = 0.001 - -function = sin(z) * exp( -((y/(2*pi) - 0.5)/0.5)^2 ) diff --git a/examples/shear-alfven-wave/find_peaks.pro b/examples/shear-alfven-wave/find_peaks.pro deleted file mode 100644 index 3b02fc3e4f..0000000000 --- a/examples/shear-alfven-wave/find_peaks.pro +++ /dev/null @@ -1,52 +0,0 @@ -pro find_peaks, sig, tt, tMax=tMax -; -; -Locate the peaks of sig and find the period -;------------------------------------------------; - - ;-isolate domains containing peaks - ii=where(sig gt 0.5*max(sig)) - nii=n_elements(ii) - ;plot, tt, sig - - - ;-locate first maximum - iFirst1=0 - for i=0,nii-2 do begin - if ((ii[i+1]-ii[i]) gt 1) then begin - ;-this is a gap in sequence - i0=i - break - endif - endfor - iLast1=ii[i0] - ;print, 'iFirst1:iLast1=', iFirst1, iLast1 - ;oplot, tt[iFirst1:iLast1], sig[iFirst1:iLast1], psym=2 - - - ;-locate second maximum - iFirst2=ii[i0+1] - for i=i0+1,nii-2 do begin - if ((ii[i+1]-ii[i]) gt 1) then begin - ;-this is a gap in sequence - break - endif - endfor - iLast2=ii[i] - ;print, 'iFirst2:iLast2=', iFirst2, iLast2 - ;plots, tt[iFirst2], sig[iFirst2], psym=4 - ;oplot, tt[iFirst2:iLast2], sig[iFirst2:iLast2], psym=2 - - - ;-second maximum defines the period - indices=iFirst2 + indgen(iLast2-iFirst2) - iMax=where(sig[indices] eq max(sig[indices])) - - tMax=tt[indices[iMax]] - sigMax=sig[indices[iMax]] - print, 'tMax=', tMax - - plots, tMax, sigMax, psym=4, syms=4 -; -; -; -end diff --git a/examples/shear-alfven-wave/qsubcase.sh b/examples/shear-alfven-wave/qsubcase.sh deleted file mode 100755 index 775002dc33..0000000000 --- a/examples/shear-alfven-wave/qsubcase.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -QSUB=mpich2sub # Common values are qsub, mpisub -NP=4 - -#-compile/build local executable -make - -#- Some queueing systems don't like name starting with number -mv 2fluid twofluid - -rm -rf data* - -label=( "0.15" "0.25" "0.50" "1.00" ) -zmax=( 3.0246e-4 5.0410e-4 1.0082e-3 2.0164e-3 ) - -for ((i=0; i <= 3 ; i++)) -do - d=data_${label[$i]} - mkdir ${d} - sed "s/ZMAX = 3.0246e-4/ZMAX = ${zmax[$i]}/g" BOUT.inp > ${d}/BOUT.inp - $QSUB $NP ./twofluid -d ${d} -done diff --git a/examples/shear-alfven-wave/runcase.sh b/examples/shear-alfven-wave/runcase.sh deleted file mode 100755 index a69cb25045..0000000000 --- a/examples/shear-alfven-wave/runcase.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -MPIEXEC=mpirun -NP=2 - -rm -rf data* - -label=( "0.15" "0.25" "0.50" "1.00" ) -zmax=( 3.0246e-4 5.0410e-4 1.0082e-3 2.0164e-3 ) - -for ((i=0; i <= 3 ; i++)) -do - mkdir data_${label[$i]} - ln -s data_${label[$i]} data - sed "s/ZMAX = 3.0246e-4/ZMAX = ${zmax[$i]}/g" BOUT.inp > data/BOUT.inp - $MPIEXEC -np $NP ./2fluid - rm -f data -done diff --git a/examples/shear-alfven-wave/runidl.pro b/examples/shear-alfven-wave/runidl.pro deleted file mode 100644 index ffbbf40501..0000000000 --- a/examples/shear-alfven-wave/runidl.pro +++ /dev/null @@ -1,82 +0,0 @@ -;pathnow=getenv('PWD') -;cd,getenv('BOUT_DA') -;.run PDB2IDL/pdb2idl.pro -;.run Plots2D/moment_xyzt.pro -;.run Plots2D/allrms.pro -;cd,pathnow - -device, decomposed=0 -tek_color - -.r pdb2idl -.r moment_xyzt -.r allrms - -;safe_colors, /first - - fu='uedge.grd_Te_10.nc' - - path = "data_0.15/" - @alf_pproc - k015=kPerp & v015=vPulse - - path = "data_0.25/" - @alf_pproc - k025=kPerp & v025=vPulse - - path = "data_0.50/" - @alf_pproc - k050=kPerp & v050=vPulse - - path = "data_1.00/" - @alf_pproc - k100=kPerp & v100=vPulse - - vte=0.0 - va=2.2e8 ;cm/s @1 T, 1e14 cm-3 - wpe=5.6e11 ;rad/s @1 T - c=3e10 ;cm/s - - safe_colors, /first - - plot, [k015,k025,k050,k100], [v015,v025,v050,v100], psym=4, yr=[0,3e8], syms=3,$ - xtit='kperp, cm-1', ytit='V, cm/s', tit='Dispersion relation for Alfven wave', col=1, chars=2 - kk=35*findgen(101)/100. - oplot, kk, va*sqrt((1+((vte/va)*(kk*c/wpe))^2)/(1+(kk*c/wpe)^2)), col=1, lin=2 - - ;-save the picture - ;image=TVRD(/true) - ;file='alftest_noPe.jpg' - ;print, "Saving in file ", file - ;write_jpeg, file, image,/true - - ;-compare results with original test - restore, 'orig_test.idl.dat' - result_31jan2007=[v015orig, v025orig, v050orig, v100orig] - error1=max(abs(result_31jan2007-[v015,v025,v050,v100])/result_31jan2007) - print, "Deviation from original test result is" , error1*1e2, " %" - - oplot, [k015,k025,k050,k100], [v015orig, v025orig, v050orig, v100orig], col=1, psym=7 - - - ;-compare results with analytic answer - result_analytic=[1.08129e+08, 1.50732e+08, 1.94260e+08, 2.12618e+08] - error2=max(abs(result_analytic-[v015,v025,v050,v100])/result_analytic) - print, "Deviation from analytic result is" , error2*1e2, " %" - - - ;- Output to a Postscript file - SET_PLOT, 'PS' - DEVICE, file="shearwave.ps" - plot, [k015,k025,k050,k100], [v015,v025,v050,v100], psym=4, yr=[0,3e8], syms=3,$ - xtit='kperp, cm-1', ytit='V, cm/s', tit='Dispersion relation for Alfven wave', col=1 - oplot, kk, va*sqrt((1+((vte/va)*(kk*c/wpe))^2)/(1+(kk*c/wpe)^2)), col=1, lin=2 - oplot, [k015,k025,k050,k100], [v015orig, v025orig, v050orig, v100orig], col=1, psym=7 - DEVICE, /close - SET_PLOT, 'X' - - for i=10,0,-1 do begin print, "exiting in ", i, " seconds" & wait,1 - - if (error1 gt 1e-4) then status=1 else status=0 - print, 'status=', status - exit, status=status diff --git a/examples/shear-alfven-wave/uedge.grd_Te_10.nc b/examples/shear-alfven-wave/uedge.grd_Te_10.nc deleted file mode 100644 index 8751302e9c..0000000000 Binary files a/examples/shear-alfven-wave/uedge.grd_Te_10.nc and /dev/null differ diff --git a/examples/shear-alfven-wave/uedge.grd_Te_10.pdb b/examples/shear-alfven-wave/uedge.grd_Te_10.pdb deleted file mode 100644 index 9b38fc531d..0000000000 Binary files a/examples/shear-alfven-wave/uedge.grd_Te_10.pdb and /dev/null differ diff --git a/examples/subsampling/monitor.cxx b/examples/subsampling/monitor.cxx index 981ff8b235..788853a595 100644 --- a/examples/subsampling/monitor.cxx +++ b/examples/subsampling/monitor.cxx @@ -16,10 +16,9 @@ class Monitor1dDump : public Monitor { public: Monitor1dDump(BoutReal timestep, std::string section_name) : Monitor(timestep), - output_file(getCustomOutputName(Options::root()[section_name]), - Options::root()[section_name]["append"].withDefault(false) - ? bout::OptionsNetCDF::FileMode::append - : bout::OptionsNetCDF::FileMode::replace) {} + output_file(bout::OptionsIO::create( + {{"file", getCustomOutputName(Options::root()[section_name])}, + {"append", Options::root()[section_name]["append"].withDefault(false)}})) {} int call(Solver*, BoutReal _time, int, int) override { // This method writes all the diagnostics to a unique file @@ -31,7 +30,7 @@ class Monitor1dDump : public Monitor { output[item.name].attributes["time_dimension"] = "t"; } } - output_file.write(output); + output_file->write(output); return 0; } @@ -48,7 +47,7 @@ class Monitor1dDump : public Monitor { private: bout::DataFileFacade dump; - bout::OptionsNetCDF output_file; + std::unique_ptr output_file; }; /// An example of using multiple monitors on different timescales diff --git a/examples/tokamak-2fluid/.gitignore b/examples/tokamak-2fluid/.gitignore deleted file mode 100644 index d837f17cae..0000000000 --- a/examples/tokamak-2fluid/.gitignore +++ /dev/null @@ -1 +0,0 @@ -2fluid \ No newline at end of file diff --git a/examples/tokamak-2fluid/2fluid.cxx b/examples/tokamak-2fluid/2fluid.cxx deleted file mode 100644 index 03458d2d4e..0000000000 --- a/examples/tokamak-2fluid/2fluid.cxx +++ /dev/null @@ -1,972 +0,0 @@ -/******************************************************************************* - * 2-fluid turbulence model - * This version intended to have inputs as similar to BOUT-06 as possible - * for cross-benchmarking etc. - *******************************************************************************/ - -#include "bout/bout_types.hxx" -#include - -#include -#include -#include -#include -#include - -class TwoFluid : public PhysicsModel { -private: - // 2D initial profiles - Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, rho0, Ajpar0; - Vector2D b0xcv; // for curvature terms - - // 3D evolving fields - Field3D rho, Te, Ni, Ajpar, Vi, Ti; - - // Derived 3D variables - Field3D phi, Apar, Ve, jpar; - - // Non-linear coefficients - Field3D nu, mu_i, kapa_Te, kapa_Ti; - - // 3D total values - Field3D Nit, Tit, Tet, Vit; - - // pressures - Field3D pei, pe; - Field2D pei0, pe0; - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - - // parameters - BoutReal Te_x, Ti_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; - BoutReal lambda_ei, lambda_ii; - BoutReal nu_hat, mui_hat, wci, nueix, nuiix; - BoutReal beta_p; - BoutReal nuIonNeutral; // Ion-neutral collision rate (normalised by wci) - - // settings - bool estatic, ZeroElMass; // Switch for electrostatic operation (true = no Apar) - BoutReal zeff, nu_perp; - bool evolve_rho, evolve_te, evolve_ni, evolve_ajpar, evolve_vi, evolve_ti; - BoutReal ShearFactor; - - bool curv_upwind; // Use upwinding methods for curvature terms - - bool laplace_extra_rho_term; // An extra first-order term in the vorticity inversion - bool vort_include_pi; // Include Pi in vorticity - - bool bout_jpar; // Use BOUT-06 method for Jpar - bool OhmPe; // Include the Pe term in Ohm's law - - int bkgd; // Profile options for coefficients (same options as BOUT-06) - int iTe_dc; // Profile evolution options - - // Poisson brackets: b0 x Grad(f) dot Grad(g) / B = [f, g] - // Method to use: BRACKET_ARAKAWA, BRACKET_STD or BRACKET_SIMPLE - BRACKET_METHOD bm; // Bracket method for advection terms - - // Switches for the equation terms - bool ni_ni1_phi0, ni_ni0_phi1, ni_ni1_phi1, ni_nit_phit; - bool ni_vi1_ni0, ni_vi0_ni1, ni_vi1_ni1, ni_vit_nit; - bool ni_jpar1, ni_pe1, ni_ni1; - bool ni_ni0_curv_phi1, ni_ni1_curv_phi0, ni_ni1_curv_phi1, ni_nit_curv_phit; - - bool rho_rho0_phi1, rho_rho1_phi0, rho_rho1_phi1; - bool rho_vi1_rho0, rho_vi0_rho1, rho_vi1_rho1; - bool rho_pei1, rho_jpar1, rho_rho1; - - bool vi_vi0_phi1, vi_vi1_phi0, vi_vi1_phi1, vi_vit_phit; - bool vi_vi1_vi0, vi_vi0_vi1, vi_vi1_vi1, vi_vit_vit; - bool vi_pei1, vi_peit, vi_vi1; - - bool te_te1_phi0, te_te0_phi1, te_te1_phi1; - - bool ti_ti1_phi0, ti_ti0_phi1, ti_ti1_phi1; - - int lowPass_z; // Low-pass filter result - - // Group of objects for communications - FieldGroup comms; - - // Coordinate system metrics - Coordinates* coord; - - // Inverts a Laplacian to get potential - std::unique_ptr phiSolver; - - // Solves the electromagnetic potential - std::unique_ptr aparSolver; - Field2D acoef; // Coefficient in the Helmholtz equation - - /// Location of possibly staggered fields - CELL_LOC stagger_loc = CELL_LOC::deflt; - - int init(bool UNUSED(restarting)) override { - TRACE("int init(bool) "); - - Field2D I; // Shear factor - - // Get the coordinate system - coord = mesh->getCoordinates(); - - output.write("Solving 6-variable 2-fluid equations\n"); - - //////////////////////////////////////////////////////// - // LOAD DATA FROM GRID FILE - - // Load 2D profiles (set to zero if not found) - GRID_LOAD(Ni0); - GRID_LOAD(Ti0); - GRID_LOAD(Te0); - GRID_LOAD(Vi0); - GRID_LOAD(Ve0); - GRID_LOAD(phi0); - GRID_LOAD(rho0); - GRID_LOAD(Ajpar0); - - // Load magnetic curvature term - b0xcv.covariant = false; // Read contravariant components - mesh->get(b0xcv, "bxcv"); // b0xkappa terms - - // Load metrics - GRID_LOAD(Rxy); - GRID_LOAD(Bpxy); - GRID_LOAD(Btxy); - GRID_LOAD(hthe); - - Field2D dx; - if (!mesh->get(dx, "dpsi")) { - output << "\tUsing dpsi as the x grid spacing\n"; - coord->dx = dx; // Only use dpsi if found - } else { - // dx will have been read already from the grid - output << "\tUsing dx as the x grid spacing\n"; - } - mesh->get(I, "sinty"); - - // Load normalisation values - GRID_LOAD(Te_x); - GRID_LOAD(Ti_x); - GRID_LOAD(Ni_x); - GRID_LOAD(bmag); - - Ni_x *= 1.0e14; - bmag *= 1.0e4; - - //////////////////////////////////////////////////////// - // READ OPTIONS - - // Read some parameters - auto& globalOptions = Options::root(); - auto& options = globalOptions["2fluid"]; - - AA = options["AA"].withDefault(2.0); - ZZ = options["ZZ"].withDefault(1.0); - - estatic = options["estatic"].withDefault(false); - ZeroElMass = options["ZeroElMass"].withDefault(false); - zeff = options["Zeff"].withDefault(1.0); - nu_perp = options["nu_perp"].withDefault(0.0); - ShearFactor = options["ShearFactor"].withDefault(1.0); - OhmPe = options["OhmPe"].withDefault(true); - bout_jpar = options["bout_jpar"].withDefault(false); - curv_upwind = options["curv_upwind"].withDefault(false); - - // Choose method to use for Poisson bracket advection terms - int bracket_method = options["bracket_method"].withDefault(0); - switch (bracket_method) { - case 0: { - bm = BRACKET_STD; - output << "\tBrackets: default differencing\n"; - break; - } - case 1: { - bm = BRACKET_SIMPLE; - output << "\tBrackets: simplified operator\n"; - break; - } - case 2: { - bm = BRACKET_ARAKAWA; - output << "\tBrackets: Arakawa scheme\n"; - break; - } - case 3: { - bm = BRACKET_CTU; - output << "\tBrackets: Corner Transport Upwind method\n"; - break; - } - default: - output << "ERROR: Invalid choice of bracket method. Must be 0 - 3\n"; - return 1; - } - - nuIonNeutral = options["nuIonNeutral"].withDefault(-1.); - - bkgd = options["bkgd"].withDefault(2); - iTe_dc = options["iTe_dc"].withDefault(2); - - laplace_extra_rho_term = options["laplace_extra_rho_term"].withDefault(false); - vort_include_pi = options["vort_include_pi"].withDefault(false); - - lowPass_z = options["low_pass_z"].withDefault(-1); - - //////////////////////////////////////////////////////// - // Equation terms - - auto& ni_options = globalOptions["Ni"]; - ni_options.setConditionallyUsed(); - evolve_ni = ni_options["evolve"].withDefault(true); - - auto& rho_options = globalOptions["rho"]; - rho_options.setConditionallyUsed(); - evolve_rho = rho_options["evolve"].withDefault(true); - - auto& vi_options = globalOptions["Vi"]; - vi_options.setConditionallyUsed(); - evolve_vi = vi_options["evolve"].withDefault(true); - - auto& te_options = globalOptions["Te"]; - te_options.setConditionallyUsed(); - evolve_ti = te_options["evolve"].withDefault(true); - - auto& ti_options = globalOptions["Ti"]; - ti_options.setConditionallyUsed(); - evolve_ti = ti_options["evolve"].withDefault(true); - - auto& ajpar_options = globalOptions["Ajpar"]; - ajpar_options.setConditionallyUsed(); - evolve_ajpar = ajpar_options["evolve"].withDefault(true); - - if (ZeroElMass) { - evolve_ajpar = false; // Don't need ajpar - calculated from ohm's law - } - - if (evolve_ni) { - ni_ni1_phi0 = ni_options["ni1_phi0"].withDefault(false); - ni_ni0_phi1 = ni_options["ni0_phi1"].withDefault(false); - ni_ni1_phi1 = ni_options["ni1_phi1"].withDefault(false); - ni_nit_phit = ni_options["nit_phit"].withDefault(false); - ni_vi1_ni0 = ni_options["vi1_ni0"].withDefault(false); - ni_vi0_ni1 = ni_options["vi0_ni1"].withDefault(false); - ni_vi1_ni1 = ni_options["vi1_ni1"].withDefault(false); - ni_vit_nit = ni_options["vit_nit"].withDefault(false); - ni_jpar1 = ni_options["jpar1"].withDefault(false); - ni_pe1 = ni_options["pe1"].withDefault(false); - ni_ni0_curv_phi1 = ni_options["ni0_curv_phi1"].withDefault(false); - ni_ni1_curv_phi0 = ni_options["ni1_curv_phi0"].withDefault(false); - ni_ni1_curv_phi1 = ni_options["ni1_curv_phi1"].withDefault(false); - ni_nit_curv_phit = ni_options["nit_curv_phit"].withDefault(false); - } - - if (evolve_rho) { - rho_rho0_phi1 = rho_options["rho0_phi1"].withDefault(false); - rho_rho1_phi0 = rho_options["rho1_phi0"].withDefault(false); - rho_rho1_phi1 = rho_options["rho1_phi1"].withDefault(false); - rho_vi1_rho0 = rho_options["vi1_rho0"].withDefault(false); - rho_vi0_rho1 = rho_options["vi0_rho1"].withDefault(false); - rho_vi1_rho1 = rho_options["vi1_rho1"].withDefault(false); - rho_pei1 = rho_options["pei1"].withDefault(false); - rho_jpar1 = rho_options["jpar1"].withDefault(false); - rho_rho1 = rho_options["rho1"].withDefault(false); - } - - if (evolve_vi) { - vi_vi0_phi1 = vi_options["vi0_phi1"].withDefault(false); - vi_vi1_phi0 = vi_options["vi1_phi0"].withDefault(false); - vi_vi1_phi1 = vi_options["vi1_phi1"].withDefault(false); - vi_vit_phit = vi_options["vit_phit"].withDefault(false); - vi_vi1_vi0 = vi_options["vi1_vi0"].withDefault(false); - vi_vi0_vi1 = vi_options["vi0_vi1"].withDefault(false); - vi_vi1_vi1 = vi_options["vi1_vi1"].withDefault(false); - vi_vit_vit = vi_options["vit_vit"].withDefault(false); - vi_pei1 = vi_options["pei1"].withDefault(false); - vi_peit = vi_options["peit"].withDefault(false); - vi_vi1 = vi_options["vi1"].withDefault(false); - } - - if (evolve_te) { - te_te1_phi0 = te_options["te1_phi0"].withDefault(false); - te_te0_phi1 = te_options["te0_phi1"].withDefault(false); - te_te1_phi1 = te_options["te1_phi1"].withDefault(false); - } - - if (evolve_ti) { - ti_ti1_phi0 = ti_options["ti1_phi0"].withDefault(false); - ti_ti0_phi1 = ti_options["ti0_phi1"].withDefault(false); - ti_ti1_phi1 = ti_options["ti1_phi1"].withDefault(false); - } - - //////////////////////////////////////////////////////// - // SHIFTED RADIAL COORDINATES - - // Check type of parallel transform - std::string ptstr = - Options::root()["mesh"]["paralleltransform"]["type"].withDefault( - "identity"); - - if (lowercase(ptstr) == "shifted") { - ShearFactor = 0.0; // I disappears from metric - b0xcv.z += I * b0xcv.x; - } - - //////////////////////////////////////////////////////// - // CALCULATE PARAMETERS - - rho_s = 1.02 * sqrt(AA * Te_x) / ZZ / bmag; - fmei = 1. / 1836.2 / AA; - - lambda_ei = 24. - log(sqrt(Ni_x) / Te_x); - lambda_ii = 23. - log(ZZ * ZZ * ZZ * sqrt(2. * Ni_x) / pow(Ti_x, 1.5)); - wci = 9.58e3 * ZZ * bmag / AA; - nueix = 2.91e-6 * Ni_x * lambda_ei / pow(Te_x, 1.5); - nuiix = 4.78e-8 * pow(ZZ, 4.) * Ni_x * lambda_ii / pow(Ti_x, 1.5) / sqrt(AA); - nu_hat = zeff * nueix / wci; - - if (nu_perp < 1.e-10) { - mui_hat = (3. / 10.) * nuiix / wci; - } else { - mui_hat = nu_perp; - } - - if (estatic) { - beta_p = 1.e-29; - } else { - beta_p = 4.03e-11 * Ni_x * Te_x / bmag / bmag; - } - - Vi_x = wci * rho_s; - - output.write("Collisions: nueix = {:e}, nu_hat = {:e}\n", nueix, nu_hat); - - //////////////////////////////////////////////////////// - // PRINT Z INFORMATION - - BoutReal hthe0; - if (mesh->get(hthe0, "hthe0") == 0) { - output.write( - " ****NOTE: input from BOUT, Z length needs to be divided by {:e}\n", - hthe0 / rho_s); - } - - if (mesh->StaggerGrids) { - //////////////////////////////////////////////////////// - // SHIFTED GRIDS LOCATION - - stagger_loc = CELL_LOC::ylow; - - // Velocities defined on cell boundaries - Vi.setLocation(stagger_loc); - Ajpar.setLocation(stagger_loc); - - // Apar and jpar too - Apar.setLocation(stagger_loc); - jpar.setLocation(stagger_loc); - } - - //////////////////////////////////////////////////////// - // NORMALISE QUANTITIES - - output.write("\tNormalising to rho_s = {:e}\n", rho_s); - - // Normalise profiles - Ni0 /= Ni_x / 1.0e14; - Ti0 /= Te_x; - Te0 /= Te_x; - phi0 /= Te_x; - Vi0 /= Vi_x; - - // Normalise curvature term - b0xcv.x /= (bmag / 1e4); - b0xcv.y *= rho_s * rho_s; - b0xcv.z *= rho_s * rho_s; - - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - I *= rho_s * rho_s * (bmag / 1e4) * ShearFactor; - coord->dx /= rho_s * rho_s * (bmag / 1e4); - - // Normalise magnetic field - Bpxy /= (bmag / 1.e4); - Btxy /= (bmag / 1.e4); - coord->Bxy /= (bmag / 1.e4); - - // calculate pressures - pei0 = (Ti0 + Te0) * Ni0; - pe0 = Te0 * Ni0; - - //////////////////////////////////////////////////////// - // CALCULATE METRICS - - coord->g11 = SQ(Rxy * Bpxy); - coord->g22 = 1.0 / SQ(hthe); - coord->g33 = SQ(I) * coord->g11 + SQ(coord->Bxy) / coord->g11; - coord->g12 = 0.0; - coord->g13 = -I * coord->g11; - coord->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coord->J = hthe / Bpxy; - - coord->g_11 = 1.0 / coord->g11 + SQ(I * Rxy); - coord->g_22 = SQ(coord->Bxy * hthe / Bpxy); - coord->g_33 = Rxy * Rxy; - coord->g_12 = Btxy * hthe * I * Rxy / Bpxy; - coord->g_13 = I * Rxy * Rxy; - coord->g_23 = Btxy * hthe * Rxy / Bpxy; - - //////////////////////////////////////////////////////// - // SET EVOLVING VARIABLES - - // Tell BOUT++ which variables to evolve - // add evolving variables to the communication object - if (evolve_rho) { - SOLVE_FOR(rho); - comms.add(rho); - output.write("rho\n"); - } else { - initial_profile("rho", rho); - rho.setBoundary("rho"); - rho.applyBoundary(); - } - - if (evolve_ni) { - SOLVE_FOR(Ni); - comms.add(Ni); - output.write("ni\n"); - } else { - initial_profile("Ni", Ni); - Ni.setBoundary("Ni"); - Ni.applyBoundary(); - } - - if (evolve_te) { - SOLVE_FOR(Te); - comms.add(Te); - output.write("te\n"); - } else { - initial_profile("Te", Te); - Te.setBoundary("Te"); - Te.applyBoundary(); - } - - if (evolve_ajpar) { - SOLVE_FOR(Ajpar); - comms.add(Ajpar); - output.write("ajpar\n"); - } else { - initial_profile("Ajpar", Ajpar); - if (ZeroElMass) { - dump.add(Ajpar, "Ajpar", 1); // output calculated Ajpar - } - Ajpar.setBoundary("Ajpar"); - Ajpar.applyBoundary(); - } - - if (evolve_vi) { - SOLVE_FOR(Vi); - comms.add(Vi); - output.write("vi\n"); - } else { - initial_profile("Vi", Vi); - Vi.setBoundary("Vi"); - Vi.applyBoundary(); - } - - if (evolve_ti) { - SOLVE_FOR(Ti); - comms.add(Ti); - output.write("ti\n"); - } else { - initial_profile("Ti", Ti); - Ti.setBoundary("Ti"); - Ti.applyBoundary(); - } - - jpar.setBoundary("jpar"); - - //////////////////////////////////////////////////////// - // SETUP COMMUNICATIONS - - // add extra variables to communication - comms.add(phi); - comms.add(Apar); - - // Add any other variables to be dumped to file - dump.addRepeat(phi, "phi"); - dump.addRepeat(Apar, "Apar"); - dump.addRepeat(jpar, "jpar"); - - dump.addOnce(Ni0, "Ni0"); - dump.addOnce(Te0, "Te0"); - dump.addOnce(Ti0, "Ti0"); - - dump.addOnce(Te_x, "Te_x"); - dump.addOnce(Ti_x, "Ti_x"); - dump.addOnce(Ni_x, "Ni_x"); - dump.addOnce(rho_s, "rho_s"); - dump.addOnce(wci, "wci"); - - // Create a solver for the Laplacian - phiSolver = Laplacian::create(&globalOptions["phiSolver"]); - if (laplace_extra_rho_term) { - // Include the first order term Grad_perp Ni dot Grad_perp phi - phiSolver->setCoefC(Ni0); - } - - globalOptions["aparSolver"].setConditionallyUsed(); - - if (!(estatic || ZeroElMass)) { - // Create a solver for the electromagnetic potential - aparSolver = Laplacian::create(&globalOptions["aparSolver"], stagger_loc); - if (mesh->StaggerGrids) { - acoef = (-0.5 * beta_p / fmei) * interp_to(Ni0, CELL_YLOW); - } else { - acoef = (-0.5 * beta_p / fmei) * Ni0; - } - aparSolver->setCoefA(acoef); - } - - return 0; - } - - // ExB terms using Poisson bracket -#define vE_Grad(f, p) (bracket(p, f, bm)) - - int rhs(BoutReal UNUSED(t)) override { - - //////////////////////////////////////////////////////// - // Invert vorticity to get phi - // - // Solves \nabla^2_\perp x + \nabla_perp c\cdot\nabla_\perp x + a x = b - // Arguments are: (b, bit-field, a, c) - // Passing NULL -> missing term - - { - TRACE("Solving for phi"); - - phi = phiSolver->solve(rho / Ni0); - - if (vort_include_pi) { - // Include Pi term in vorticity - phi -= (Ti * Ni0 + Ni * Te0) / Ni0; - } - } - - //////////////////////////////////////////////////////// - // Invert Ajpar to get Apar - - { - TRACE("Solving for Apar"); - if (estatic || ZeroElMass) { - // Electrostatic operation - Apar = 0.0; - } else { - Apar = aparSolver->solve(acoef * (Vi - Ajpar)); - } - } - - //////////////////////////////////////////////////////// - // Communicate variables - mesh->communicate(comms); - - //////////////////////////////////////////////////////// - // Update profiles for calculating nu, mu_i, kapa_Te,i - switch (bkgd) { - case 0: { // Toroidal averages - Nit = Ni0 + DC(Ni); - Tit = Ti0 + DC(Ti); - Tet = Te0 + DC(Te); - Vit = Vi0 + DC(Vi); - break; - } - case 1: { // Full perturbed values - Nit = Ni0 + Ni; - Tit = Ti0 + Ti; - Tet = Te0 + Te; - Vit = Vi0 + Vi; - break; - } - case 2: { // Unperturbed values - Nit = Ni0; - Tit = Ti0; - Tet = Te0; - Vit = Vi0; - break; - } - default: { - throw BoutException("ERROR: Invalid bkgd option\n"); - } - } - - //////////////////////////////////////////////////////// - // Update non-linear coefficients on the mesh - if (mesh->StaggerGrids) { - nu = nu_hat * interp_to(Nit / pow(Tet, 1.5), CELL_YLOW); - } else { - nu = nu_hat * Nit / pow(Tet, 1.5); - } - mu_i = mui_hat * Nit / sqrt(Tit); - kapa_Te = 3.2 * (1. / fmei) * (wci / nueix) * pow(Tet, 2.5); - kapa_Ti = 3.9 * (wci / nuiix) * pow(Tit, 2.5); - - // note: nonlinear terms are not here - pei = (Te0 + Ti0) * Ni + (Te + Ti) * Ni0; - pe = Te0 * Ni + Te * Ni0; - - //////////////////////////////////////////////////////// - if (ZeroElMass) { - // Set jpar,Ve,Ajpar neglecting the electron inertia term - // Calculate Jpar, communicating across processors - - jpar = - -interp_to(Ni0, stagger_loc) * Grad_par(phi, stagger_loc) / (fmei * 0.51 * nu); - - if (OhmPe) { - jpar += - interp_to(Te0, stagger_loc) * Grad_par(Ni, stagger_loc) / (fmei * 0.51 * nu); - } - - // Need to communicate jpar - mesh->communicate(jpar); - jpar.applyBoundary(); - - if (!mesh->StaggerGrids) { - Ve = Vi - jpar / Ni0; - } else { - Ve = Vi - jpar / interp_to(Ni0, CELL_YLOW); - } - Ajpar = Ve; - } else { - - Ve = Ajpar + Apar; - if (!mesh->StaggerGrids) { - jpar = Ni0 * (Vi - Ve); - } else { - jpar = interp_to(Ni0, CELL_YLOW) * (Vi - Ve); - } - } - - //////////////////////////////////////////////////////// - // DENSITY EQUATION - - ddt(Ni) = 0.0; - if (evolve_ni) { - TRACE("Density equation"); - - if (ni_ni1_phi0) { - ddt(Ni) -= vE_Grad(Ni, phi0); - } - - if (ni_ni0_phi1) { - ddt(Ni) -= vE_Grad(Ni0, phi); - } - - if (ni_ni1_phi1) { - ddt(Ni) -= vE_Grad(Ni, phi); - } - - if (ni_nit_phit) { - ddt(Ni) -= vE_Grad(Nit, phi0 + phi) - vE_Grad(Ni0, phi0); - } - - if (ni_vi1_ni0) { - ddt(Ni) -= Vpar_Grad_par(Vi, Ni0); - } - - if (ni_vi0_ni1) { - ddt(Ni) -= Vpar_Grad_par(Vi0, Ni); - } - - if (ni_vi1_ni1) { - ddt(Ni) -= Vpar_Grad_par(Vi, Ni); - } - - if (ni_vit_nit) { - ddt(Ni) -= Vpar_Grad_par(Vit, Nit) - Vpar_Grad_par(Vi0, Ni0); - } - - if (ni_jpar1) { - ddt(Ni) += Div_par(jpar, CELL_CENTRE); - } - - if (ni_pe1) { - ddt(Ni) += 2.0 * V_dot_Grad(b0xcv, pe); - } - - if (ni_ni0_curv_phi1) { - ddt(Ni) -= 2.0 * Ni0 * V_dot_Grad(b0xcv, phi); - } - - if (ni_ni1_curv_phi0) { - ddt(Ni) -= 2.0 * Ni * V_dot_Grad(b0xcv, phi0); - } - - if (ni_ni1_curv_phi1) { - ddt(Ni) -= 2.0 * Ni * V_dot_Grad(b0xcv, phi); - } - - if (ni_nit_curv_phit) { - ddt(Ni) -= 2.0 * Nit * V_dot_Grad(b0xcv, phi + phi0) - - 2.0 * Ni0 * V_dot_Grad(b0xcv, phi0); - } - - if (ni_ni1) { - ddt(Ni) += mu_i * Delp2(Ni); - } - - //ddt(Ni) -= Ni0*Div_par(Vi) + Ni*Div_par(Vi0) + Ni*Div_par(Vi); - - if (lowPass_z > 0) { - ddt(Ni) = lowPass(ddt(Ni), lowPass_z); - } - } - - //////////////////////////////////////////////////////// - // ION VELOCITY - - ddt(Vi) = 0.0; - if (evolve_vi) { - TRACE("Ion velocity equation"); - - if (vi_vi0_phi1) { - ddt(Vi) -= vE_Grad(Vi0, phi); - } - - if (vi_vi1_phi0) { - ddt(Vi) -= vE_Grad(Vi, phi0); - } - - if (vi_vi1_phi1) { - ddt(Vi) -= vE_Grad(Vi, phi); - } - - if (vi_vit_phit) { - ddt(Vi) -= vE_Grad(Vit, phi + phi0) - vE_Grad(Vi0, phi + phi0); - } - - if (vi_vi1_vi0) { - ddt(Vi) -= Vpar_Grad_par(Vi0, Vi); - } - - if (vi_vi0_vi1) { - ddt(Vi) -= Vpar_Grad_par(Vi, Vi0); - } - - if (vi_vi1_vi1) { - ddt(Vi) -= Vpar_Grad_par(Vi, Vi); - } - - if (vi_vit_vit) { - ddt(Vi) -= Vpar_Grad_par(Vit, Vit) - Vpar_Grad_par(Vi0, Vi0); - } - - if (vi_pei1) { - ddt(Vi) -= Grad_par(pei) / Ni0; - } - - if (vi_peit) { - ddt(Vi) -= Grad_par(pei) / Nit; - } - - if (vi_vi1) { - ddt(Vi) -= mu_i * Delp2(Vi); - } - - if (lowPass_z > 0) { - ddt(Vi) = lowPass(ddt(Vi), lowPass_z); - } - } - - //////////////////////////////////////////////////////// - // ELECTRON TEMPERATURE - - ddt(Te) = 0.0; - if (evolve_te) { - TRACE("Electron temperature equation"); - - if (te_te1_phi0) { - ddt(Te) -= vE_Grad(Te, phi0); - } - if (te_te0_phi1) { - ddt(Te) -= vE_Grad(Te0, phi); - } - if (te_te1_phi1) { - ddt(Te) -= vE_Grad(Te, phi); - } - - /* - ddt(Te) -= vE_Grad(Te0, phi) + vE_Grad(Te, phi0) + vE_Grad(Te, phi); - ddt(Te) -= Vpar_Grad_par(Ve, Te0) + Vpar_Grad_par(Ve0, Te) + Vpar_Grad_par(Ve, Te); - ddt(Te) += 1.333*Te0*( V_dot_Grad(b0xcv, pe)/Ni0 - V_dot_Grad(b0xcv, phi) ); - ddt(Te) += 3.333*Te0*V_dot_Grad(b0xcv, Te); - ddt(Te) += (0.6666667/Ni0)*Div_par_K_Grad_par(kapa_Te, Te); - - */ - if (lowPass_z > 0) { - ddt(Te) = lowPass(ddt(Te), lowPass_z); - } - } - - //////////////////////////////////////////////////////// - // ION TEMPERATURE - - ddt(Ti) = 0.0; - if (evolve_ti) { - TRACE("Ion temperature equation"); - - if (ti_ti1_phi0) { - ddt(Ti) -= vE_Grad(Ti, phi0); - } - if (ti_ti0_phi1) { - ddt(Ti) -= vE_Grad(Ti0, phi); - } - if (ti_ti1_phi1) { - ddt(Ti) -= vE_Grad(Ti, phi); - } - - /* - ddt(Ti) -= vE_Grad(Ti0, phi) + vE_Grad(Ti, phi0) + vE_Grad(Ti, phi); - ddt(Ti) -= Vpar_Grad_par(Vi, Ti0) + Vpar_Grad_par(Vi0, Ti) + Vpar_Grad_par(Vi, Ti); - ddt(Ti) += 1.333*( Ti0*V_dot_Grad(b0xcv, pe)/Ni0 - Ti*V_dot_Grad(b0xcv, phi) ); - ddt(Ti) -= 3.333*Ti0*V_dot_Grad(b0xcv, Ti); - ddt(Ti) += (0.6666667/Ni0)*Div_par_K_Grad_par(kapa_Ti, Ti); - */ - - if (lowPass_z > 0) { - ddt(Ti) = lowPass(ddt(Ti), lowPass_z); - } - } - - //////////////////////////////////////////////////////// - // VORTICITY - - ddt(rho) = 0.0; - if (evolve_rho) { - TRACE("Vorticity equation"); - - if (rho_rho0_phi1) { - ddt(rho) -= vE_Grad(rho0, phi); - } - - if (rho_rho1_phi0) { - ddt(rho) -= vE_Grad(rho, phi0); - } - - if (rho_rho1_phi1) { - ddt(rho) -= vE_Grad(rho, phi); - } - - if (rho_vi1_rho0) { - ddt(rho) -= Vpar_Grad_par(Vi, rho0); - } - - if (rho_vi0_rho1) { - ddt(rho) -= Vpar_Grad_par(Vi0, rho); - } - - if (rho_vi1_rho1) { - ddt(rho) -= Vpar_Grad_par(Vi, rho); - } - - if (rho_pei1) { - if (curv_upwind) { - ddt(rho) += 2.0 * coord->Bxy * V_dot_Grad(b0xcv, pei); // Use upwinding - } else { - ddt(rho) += 2.0 * coord->Bxy * b0xcv * Grad(pei); // Use central differencing - } - } - - if (rho_jpar1) { - ddt(rho) += SQ(coord->Bxy) * Div_par(jpar, CELL_CENTRE); - } - - if (rho_rho1) { - ddt(rho) += mu_i * Delp2(rho); - } - - if (lowPass_z > 0) { - ddt(rho) = lowPass(ddt(rho), lowPass_z); - } - } - - //////////////////////////////////////////////////////// - // AJPAR - - ddt(Ajpar) = 0.0; - if (evolve_ajpar) { - TRACE("Ajpar equation"); - - //ddt(Ajpar) -= vE_Grad(Ajpar0, phi) + vE_Grad(Ajpar, phi0) + vE_Grad(Ajpar, phi); - //ddt(Ajpar) -= (1./fmei)*1.71*Grad_par(Te, CELL_YLOW); - - ddt(Ajpar) += (1. / fmei) * Grad_par(phi, CELL_YLOW); - - if (OhmPe) { - ddt(Ajpar) -= (1. / fmei) * (Te0 / Ni0) * Grad_par(Ni, CELL_YLOW); - } - - if (mesh->StaggerGrids) { - ddt(Ajpar) += 0.51 * nu * jpar / interp_to(Ni0, CELL_YLOW); - } else { - ddt(Ajpar) += 0.51 * nu * jpar / Ni0; - } - - if (lowPass_z > 0) { - ddt(Ajpar) = lowPass(ddt(Ajpar), lowPass_z); - } - } - - //////////////////////////////////////////////////////// - // Profile evolution options - - switch (iTe_dc) { - case 1: { // subtacting out toroidal averages for all fields - if (evolve_ni) { - ddt(Ni) -= DC(ddt(Ni)); - } - if (evolve_rho) { - ddt(rho) -= DC(ddt(rho)); - } - if (evolve_te) { - ddt(Te) -= DC(ddt(Te)); - } - if (evolve_ti) { - ddt(Ti) -= DC(ddt(Ti)); - } - if (evolve_ajpar) { - ddt(Ajpar) -= DC(ddt(Ajpar)); - } - break; - } - case 2: { // not subtacting out toroidal averages for any field - break; - } - case 4: { // using toroidal averages in right-hand sides, e.g., axisymmetric mode - if (evolve_ni) { - ddt(Ni) = DC(ddt(Ni)); - } - if (evolve_rho) { - ddt(rho) = DC(ddt(rho)); - } - if (evolve_te) { - ddt(Te) = DC(ddt(Te)); - } - if (evolve_ti) { - ddt(Ti) = DC(ddt(Ti)); - } - if (evolve_ajpar) { - ddt(Ajpar) = DC(ddt(Ajpar)); - } - break; - } - default: { - throw BoutException("ERROR: invalid option for iTe_dc\n"); - } - } - - return (0); - } -}; - -BOUTMAIN(TwoFluid); diff --git a/examples/tokamak-2fluid/CMakeLists.txt b/examples/tokamak-2fluid/CMakeLists.txt deleted file mode 100644 index 8998706373..0000000000 --- a/examples/tokamak-2fluid/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(tokamak-2fluid LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(tokamak-2fluid - SOURCES 2fluid.cxx - DATA_DIRS d3d-119919 - d3d-129131 - data - EXTRA_FILES uedge.grd.nc - uedge.grd_129131_newpproc.nc - data/uedge.grd.nc) diff --git a/examples/tokamak-2fluid/README.md b/examples/tokamak-2fluid/README.md deleted file mode 100644 index cb281be529..0000000000 --- a/examples/tokamak-2fluid/README.md +++ /dev/null @@ -1,15 +0,0 @@ -Tokamak edge turbulence -======================= - -Equilibrium from DIII-D tokamak, discharge 129131 - -Running the case ----------------- - -To set up the case, run the following in this directory - - make - -Then run the 2fluid executable on >= 16 processors - - mpirun -np 16 ./2fluid diff --git a/examples/tokamak-2fluid/d3d-119919/BOUT.inp b/examples/tokamak-2fluid/d3d-119919/BOUT.inp deleted file mode 100644 index 69cd480a50..0000000000 --- a/examples/tokamak-2fluid/d3d-119919/BOUT.inp +++ /dev/null @@ -1,193 +0,0 @@ -# settings file for BOUT++ 2-fluid model -# As far as possible, the names used here are the same -# as those used in the BOUT-06 input file - -################################################## -# settings used by the core code - -nout = 200 # number of time-steps -timestep = 1.0 # time between outputs - -twistshift = true # use twist-shift condition? - -MZ = 64 # number of points in z direction (2^n) - -zperiod = 20 # Fraction of a torus - -MXG = 2 -MYG = 2 - -grid = "uedge.grd.nc" -twistshift_pf = true # Grid has twist-shift in PF region - -[mesh:paralleltransform] -type = shifted # Use shifted metric method - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Laplacian inversion settings - -[laplace] -all_terms = false -nonuniform = true -filter = 0.2 # Remove the top 20% of modes (BOUT-06 zwindow=0.4) - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -nu_perp = 1e-20 - -bkgd = 2 # Profile option for coefficients (ni, mu_i etc.) -iTe_dc = 1 # Profile evolution option - -AA = 2.0 # Ion mass -ZZ = 1.0 # Ion charge -Zeff = 2.0 # Z effective - -estatic = true # if true, electrostatic (Apar = 0). (BOUT-06 = esop) -ZeroElMass = true # Use Ohms law without electron inertia -bout_jpar = false # Use BOUT-06 method to calculate ZeroElMass jpar - -stagger = true # Use CtoL and LtoC parallel differencing - -# Form to use for the ExB advection (Poisson bracket) terms -bracket_method = 1 # 0 = full terms, 1 = simplified (BOUT-06), 2 = Arakawa, 3 = CTU - -curv_upwind = false # Use upwinding for b0xkappa_dot_Grad terms - -laplace_extra_rho_term = true # include Grad_perp(Ni) dot Grad_perp(phi) term -vort_include_pi = false # Include Pi term in vorticity (BOUT-06 vortPi) - -ShearFactor = 1.0 - -OhmPe = true # Include Pe in Ohm's law? - -low_pass_z = -1 # Keep n up to (and including) this number - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) -phi_flags = 1 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -# All variables and all regions to zero-gradient -bndry_all = relax(neumann) - -################################################## -# DENSITY -# NOTE: By default all terms are off (false) so -# any unused options can just be removed - -[Ni] -scale = 0.001 # Initial perturbation size - -# Form of the initial perturbation -function = ballooning( exp(-((x-0.5)/0.25)^2) * exp(-((y/(2*pi)-0.5)/0.6)^2) * sin(z) ) - -# ExB advection terms -ni1_phi0 = false -ni0_phi1 = true -ni1_phi1 = true -nit_phit = false - -# Parallel advection -vi1_ni0 = false -vi0_ni1 = false -vi1_ni1 = false -vit_nit = false - -jpar1 = true # Div_par(Jpar) linear term -pe1 = false # b0xkappa_Grad(Pe) linear term -ni1 = false # Perpendicular ion viscosity - -# Ni * b0xkappa_Grad(phi) terms -ni0_curv_phi1 = false -ni1_curv_phi0 = false -ni1_curv_phi1 = false -nit_curv_phit = false - -[Vi] -evolve = false - -[Te] -evolve = false - -[Ti] -evolve = false - -################################################## -# VORTICITY - -[rho] - -bndry_xin = relax(dirichlet) -bndry_xout = relax(dirichlet) - -# ExB advection terms -rho0_phi1 = false -rho1_phi0 = false -rho1_phi1 = true - -# Parallel advection -vi1_rho0 = false -vi0_rho1 = false -vi1_rho1 = false - -pei1 = true # b0xkappa_Grad(Pei) linear curvature drive -jpar1 = true # Div_par(Jpar) linear drive -rho1 = false # Perpendicular ion viscosity diff --git a/examples/tokamak-2fluid/d3d-129131/BOUT.inp b/examples/tokamak-2fluid/d3d-129131/BOUT.inp deleted file mode 100644 index f17c58865a..0000000000 --- a/examples/tokamak-2fluid/d3d-129131/BOUT.inp +++ /dev/null @@ -1,193 +0,0 @@ -# settings file for BOUT++ 2-fluid model -# As far as possible, the names used here are the same -# as those used in the BOUT-06 input file - -################################################## -# settings used by the core code - -nout = 200 # number of time-steps -timestep = 1.0 # time between outputs - -twistshift = true # use twist-shift condition? - -MZ = 64 # number of points in z direction (2^n) - -zperiod = 20 # Fraction of a torus - -MXG = 2 -MYG = 2 - -grid = "uedge.grd_129131_newpproc.nc" -twistshift_pf = true # Grid has twist-shift in PF region - -[mesh:paralleltransform] -type = shifted # Use shifted metric method - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddy] - -first = C4 -second = C4 -upwind = W3 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Laplacian inversion settings - -[laplace] -all_terms = false -nonuniform = true -filter = 0.2 # Remove the top 20% of modes (BOUT-06 zwindow=0.4) - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -nu_perp = 1e-20 - -bkgd = 2 # Profile option for coefficients (ni, mu_i etc.) -iTe_dc = 1 # Profile evolution option - -AA = 2.0 # Ion mass -ZZ = 1.0 # Ion charge -Zeff = 2.0 # Z effective - -estatic = true # if true, electrostatic (Apar = 0). (BOUT-06 = esop) -ZeroElMass = true # Use Ohms law without electron inertia -bout_jpar = false # Use BOUT-06 method to calculate ZeroElMass jpar - -stagger = true # Use CtoL and LtoC parallel differencing - -# Form to use for the ExB advection (Poisson bracket) terms -bracket_method = 1 # 0 = full terms, 1 = simplified (BOUT-06), 2 = Arakawa, 3 = CTU - -curv_upwind = false # Use upwinding for b0xkappa_dot_Grad terms - -laplace_extra_rho_term = true # include Grad_perp(Ni) dot Grad_perp(phi) term -vort_include_pi = false # Include Pi term in vorticity (BOUT-06 vortPi) - -ShearFactor = 1.0 - -OhmPe = true # Include Pe in Ohm's law? - -low_pass_z = -1 # Keep n up to (and including) this number - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) -phi_flags = 1 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations - -# boundary conditions -# ------------------- -# dirichlet - Zero value -# neumann - Zero gradient -# zerolaplace - Laplacian = 0, decaying solution -# constlaplace - Laplacian = const, decaying solution -# -# relax( ) - Make boundary condition relaxing - -bndry_all = relax(neumann) # Relax to zero-gradient inner boundary - -################################################## -# DENSITY -# NOTE: By default all terms are off (false) so -# any unused options can just be removed - -[Ni] -scale = 0.001 # Initial perturbation size - -# Form of the initial perturbation -function = ballooning( exp(-((x-0.5)/0.25)^2) * exp(-((y/(2*pi)-0.5)/0.6)^2) * sin(z) ) - -# ExB advection terms -ni1_phi0 = false -ni0_phi1 = true -ni1_phi1 = true -nit_phit = false - -# Parallel advection -vi1_ni0 = false -vi0_ni1 = false -vi1_ni1 = false -vit_nit = false - -jpar1 = true # Div_par(Jpar) linear term -pe1 = false # b0xkappa_Grad(Pe) linear term -ni1 = false # Perpendicular ion viscosity - -# Ni * b0xkappa_Grad(phi) terms -ni0_curv_phi1 = false -ni1_curv_phi0 = false -ni1_curv_phi1 = false -nit_curv_phit = false - -[Vi] -evolve = false - -[Te] -evolve = false - -[Ti] -evolve = false - -################################################## -# VORTICITY - -[rho] -#scale = 1.0e-3 - -bndry_xin = relax(dirichlet) -bndry_xout = relax(dirichlet) - -# ExB advection terms -rho0_phi1 = false -rho1_phi0 = false -rho1_phi1 = true - -# Parallel advection -vi1_rho0 = false -vi0_rho1 = false -vi1_rho1 = false - -pei1 = true # b0xkappa_Grad(Pei) linear curvature drive -jpar1 = true # Div_par(Jpar) linear drive -rho1 = false # Perpendicular ion viscosity diff --git a/examples/tokamak-2fluid/data/BOUT.inp b/examples/tokamak-2fluid/data/BOUT.inp deleted file mode 100644 index 214bafc19a..0000000000 --- a/examples/tokamak-2fluid/data/BOUT.inp +++ /dev/null @@ -1,172 +0,0 @@ -# settings file for BOUT++ 2-fluid model -# As far as possible, the names used here are the same -# as those used in the BOUT-06 input file - -################################################## -# settings used by the core code - -nout = 200 # number of time-steps -timestep = 10.0 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 32 # number of points in z direction (2^n) - -ZMIN = 0.0 -ZMAX = 0.0202509 # 1e1 / 4.938060e+02 -#ZPERIOD = 50 - -MXG = 2 -MYG = 2 - -grid = "data/uedge.grd.nc" - -[mesh] -staggergrids = true - -################################################## -# derivative methods - -[mesh:ddx] - -first = C4 -second = C4 -upwind = U1 - -[mesh:ddy] - -first = C4 -second = C4 -upwind = U1 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = U1 - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance -mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -nu_perp = 1e-20 - -bkgd = 2 # Profile option for coefficients (ni, mu_i etc.) -iTe_dc = 2 # Profile evolution option - -AA = 2.0 # Ion mass -ZZ = 1.0 # Ion charge -Zeff = 32.0 # Z effective - -estatic = true # if true, electrostatic (Apar = 0). (BOUT-06 = esop) -ZeroElMass = true # Use Ohms law without electron inertia -bout_jpar = true # Use BOUT-06 method to calculate ZeroElMass jpar - -curv_upwind = false # Use upwinding for b0xkappa_dot_Grad terms - -laplace_extra_rho_term = false # include Grad_perp(Ni) dot Grad_perp(phi) term -vort_include_pi = false # Include Pi term in vorticity (BOUT-06 vortPi) - -ShearFactor = 0.0 - -OhmPe = false # Include Pe in Ohm's law? - -low_pass_z = -1 # Keep n up to (and including) this number - -[phiSolver] -inner_boundary_flags = 1 + 2 # INVERT_DC_GRAD + INVERT_AC_GRAD -outer_boundary_flags = 1 + 2 # INVERT_DC_GRAD + INVERT_AC_GRAD - -[aparSolver] -inner_boundary_flags = 0 -outer_boundary_flags = 0 - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations -function = gauss(y, 0.1) * sin(z) - -# boundary conditions -# -# dirichlet = Zero value -# neumann = Zero gradient -# -# relax(neumann) = Relax towards zero gradient -# relax(neumann, 10) = Relax with a rate (= 1/timescale) of 10 - -bndry_all = relax(neumann,20) - -################################################## -# DENSITY -# NOTE: By default all terms are off (false) so -# any unused options can just be removed - -[Ni] -scale = 0.01 # Initial perturbation size - -# ExB advection terms -ni1_phi0 = false -ni0_phi1 = true -ni1_phi1 = true -nit_phit = false - -# Parallel advection -vi1_ni0 = false -vi0_ni1 = false -vi1_ni1 = false -vit_nit = false - -jpar1 = false # Div_par(Jpar) linear term -pe1 = false # b0xkappa_Grad(Pe) linear term -ni1 = false # Perpendicular ion viscosity - -# Ni * b0xkappa_Grad(phi) terms -ni0_curv_phi1 = false -ni1_curv_phi0 = false -ni1_curv_phi1 = false -nit_curv_phit = false - -[Vi] -evolve = false - -[Te] -evolve = false - -[Ti] -evolve = false - -################################################## -# VORTICITY - -[rho] -scale = 0.01 - -# ExB advection terms -rho0_phi1 = false -rho1_phi0 = false -rho1_phi1 = true - -# Parallel advection -vi1_rho0 = false -vi0_rho1 = false -vi1_rho1 = false - -pei1 = true # b0xkappa_Grad(Pei) linear curvature drive -jpar1 = true # Div_par(Jpar) linear drive -rho1 = false # Perpendicular ion viscosity diff --git a/examples/tokamak-2fluid/data/BOUT.inp_nl b/examples/tokamak-2fluid/data/BOUT.inp_nl deleted file mode 100644 index d4c644a3ca..0000000000 --- a/examples/tokamak-2fluid/data/BOUT.inp_nl +++ /dev/null @@ -1,193 +0,0 @@ -# settings file for BOUT++ 2-fluid model -# As far as possible, the names used here are the same -# as those used in the BOUT-06 input file - -################################################## -# settings used by the core code - -NOUT = 100 # number of time-steps -TIMESTEP = 1e-1 # time between outputs - -ShiftXderivs = true # use shifted radial derivatives? -TwistShift = true # use twist-shift condition? - -MZ = 33 # number of points in z direction (2^n + 1) - -ZMIN = 0.0 -ZMAX = 0.0202509 # 1e1 / 4.938060e+02 -#ZPERIOD = 50 - -MXG = 2 -MYG = 2 - -grid="data/uedge.grd.nc" - -dump_format = "nc" # Set extension for dump files (nc = NetCDF) - -NXPE = 2 - -#StaggerGrids = true - -################################################## -# derivative methods - -[ddx] - -first = C4 -second = C4 -upwind = W3 - -[ddy] - -first = C4 -second = C4 -upwind = W3 - -[ddz] - -first = C4 -second = C4 -upwind = W3 - -################################################## -# Laplacian inversion settings - -[laplace] -all_terms = false -laplace_nonuniform = true -filter = 0.2 # Remove the top 20% of modes (BOUT-06 zwindow=0.4) - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1.0e-10 # absolute tolerance -rtol = 1.0e-5 # relative tolerance -pvode_mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -nu_perp = 1.0e-20 - -relax_flat_bndry = true # If true, use BOUT-06 relaxating boundaries -lambda = -20. # Boundary relaxation rate -bkgd = 2 # Profile option for coefficients (ni, mu_i etc.) -iTe_dc = 2 # Profile evolution option - -AA = 2.0 # Ion mass -ZZ = 1.0 # Ion charge -Zeff = 1 # Z effective - -estatic = true # if true, electrostatic (Apar = 0). (BOUT-06 = esop) -ZeroElMass = true # Use Ohms law without electron inertia -bout_jpar = false # Use BOUT-06 method to calculate ZeroElMass jpar - -stagger = true # Use CtoL and LtoC parallel differencing - -bout_exb = true # Use the BOUT-06 subset of ExB terms - -curv_upwind = false # Use upwinding for b0xkappa_dot_Grad terms - -laplace_extra_rho_term = true # include Grad_perp(Ni) dot Grad_perp(phi) term -vort_include_pi = false # Include Pi term in vorticity (BOUT-06 vortPi) - -ShearFactor = 0.0 - -OhmPe = true # Include Pe in Ohm's law? - -low_pass_z = -1 # Keep n up to (and including) this number - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) -phi_flags = 1 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[All] -scale = 0.0 # default size of initial perturbations -function = gauss(y, 0.5) * sin(z) - -bndry_xin = neumann -bndry_xout = neumann - -################################################## -# DENSITY -# NOTE: By default all terms are off (false) so -# any unused options can just be removed - -[Ni] -scale = 1.0e-1 # Initial perturbation size - -# ExB advection terms -ni1_phi0 = false -ni0_phi1 = true -ni1_phi1 = true -nit_phit = false - -# Parallel advection -vi1_ni0 = false -vi0_ni1 = false -vi1_ni1 = false -vit_nit = false - -jpar1 = true # Div_par(Jpar) linear term -pe1 = false # b0xkappa_Grad(Pe) linear term -ni1 = false # Perpendicular ion viscosity - -# Ni * b0xkappa_Grad(phi) terms -ni0_curv_phi1 = false -ni1_curv_phi0 = false -ni1_curv_phi1 = false -nit_curv_phit = false - -[Vi] -evolve = false - -[Te] -evolve = false - -[Ti] -evolve = false - -################################################## -# VORTICITY - -[rho] -scale = 1.0e-1 - -bndry_xin = dirichlet -bndry_xout = dirichlet - -# ExB advection terms -rho0_phi1 = false -rho1_phi0 = false -rho1_phi1 = true - -# Parallel advection -vi1_rho0 = false -vi0_rho1 = false -vi1_rho1 = false - -pei1 = true # b0xkappa_Grad(Pei) linear curvature drive -jpar1 = true # Div_par(Jpar) linear drive -rho1 = false # Perpendicular ion viscosity - -[jpar] -bndry_xin = neumann -bndry_xout = neumann diff --git a/examples/tokamak-2fluid/data/BOUT.inp_simple b/examples/tokamak-2fluid/data/BOUT.inp_simple deleted file mode 100644 index f13a6fbd5f..0000000000 --- a/examples/tokamak-2fluid/data/BOUT.inp_simple +++ /dev/null @@ -1,186 +0,0 @@ -# settings file for BOUT++ 2-fluid model -# As far as possible, the names used here are the same -# as those used in the BOUT-06 input file - -################################################## -# settings used by the core code - -NOUT = 100 # number of time-steps -TIMESTEP = 1e1 # time between outputs - -ShiftXderivs = true # use shifted radial derivatives? -TwistShift = true # use twist-shift condition? - -MZ = 33 # number of points in z direction (2^n + 1) - -#ZMIN = 0.0 -#ZMAX = 0.0202509 # 1e1 / 4.938060e+02 -ZPERIOD = 10 - -MXG = 2 -MYG = 2 - -grid="data/uedge.grd.nc" - -dump_format = "pdb" # Set extension for dump files (nc = NetCDF) - -NXPE = 2 - -#StaggerGrids = true - -################################################## -# derivative methods - -[ddx] - -first = C4 -second = C4 -upwind = U1 - -[ddy] - -first = C4 -second = C4 -upwind = U1 - -[ddz] - -first = C4 -second = C4 -upwind = U1 - -################################################## -# Laplacian inversion settings - -[laplace] -all_terms = false -laplace_nonuniform = true -filter = 0.2 # Remove the top 20% of modes (BOUT-06 zwindow=0.4) - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -atol = 1.0e-10 # absolute tolerance -rtol = 1.0e-5 # relative tolerance -pvode_mxstep = 50000 - -################################################## -# settings for 2fluid - -[2fluid] - -nu_perp = 1.0e-20 - -relax_flat_bndry = false # If true, use BOUT-06 relaxating boundaries -lambda = -20. # Boundary relaxation rate -bkgd = 2 # Profile option for coefficients (ni, mu_i etc.) -iTe_dc = 2 # Profile evolution option - -AA = 1.0 # Ion mass -ZZ = 1.0 # Ion charge -Zeff = 1e3 # Z effective - -estatic = true # if true, electrostatic (Apar = 0). (BOUT-06 = esop) -ZeroElMass = true # Use Ohms law without electron inertia -bout_jpar = false # Use BOUT-06 method to calculate ZeroElMass jpar - -stagger = false # Use CtoL and LtoC parallel differencing - -bout_exb = true # Use the BOUT-06 subset of ExB terms - -curv_upwind = false # Use upwinding for b0xkappa_dot_Grad terms - -laplace_extra_rho_term = false # include Grad_perp(Ni) dot Grad_perp(phi) term -vort_include_pi = false # Include Pi term in vorticity (BOUT-06 vortPi) - -ShearFactor = 1.0 - -OhmPe = false # Include Pe in Ohm's law? - -low_pass_z = -1 # Keep n up to (and including) this number - -# field inversion flags: Add the following -# 1 - Zero-gradient DC component on inner boundary -# 2 - Zero-gradient AC component on inner boundary -# 4 - " DC " " outer " -# 8 - " AC " " outer " -# 16 - Zero all DC components of the result -# 32 - Don't use previous solution to start iterations -# (iterative methods only) -phi_flags = 10 # inversion flags for phi -apar_flags = 0 # flags for apar inversion - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[All] -scale = 0.0 # default size of initial perturbations -function = gauss(y, 0.1) * sin(z) - -bndry_xin = neumann ## Zero-gradient inner boundary -bndry_xout = neumann ## Zero-gradient outer boundary - -################################################## -# DENSITY -# NOTE: By default all terms are off (false) so -# any unused options can just be removed - -[Ni] -scale = 1.0e-2 # Initial perturbation size - -# ExB advection terms -ni1_phi0 = false -ni0_phi1 = true -ni1_phi1 = false -nit_phit = false - -# Parallel advection -vi1_ni0 = false -vi0_ni1 = false -vi1_ni1 = false -vit_nit = false - -jpar1 = false # Div_par(Jpar) linear term -pe1 = false # b0xkappa_Grad(Pe) linear term -ni1 = false # Perpendicular ion viscosity - -# Ni * b0xkappa_Grad(phi) terms -ni0_curv_phi1 = false -ni1_curv_phi0 = false -ni1_curv_phi1 = false -nit_curv_phit = false - -[Vi] -evolve = false - -[Te] -evolve = false - -[Ti] -evolve = false - -################################################## -# VORTICITY - -[rho] -scale = 1.0e-2 - -# ExB advection terms -rho0_phi1 = false -rho1_phi0 = false -rho1_phi1 = false - -# Parallel advection -vi1_rho0 = false -vi0_rho1 = false -vi1_rho1 = false - -pei1 = true # b0xkappa_Grad(Pei) linear curvature drive -jpar1 = true # Div_par(Jpar) linear drive -rho1 = false # Perpendicular ion viscosity diff --git a/examples/tokamak-2fluid/data/uedge.grd.nc b/examples/tokamak-2fluid/data/uedge.grd.nc deleted file mode 100644 index e70d83a5c3..0000000000 Binary files a/examples/tokamak-2fluid/data/uedge.grd.nc and /dev/null differ diff --git a/examples/tokamak-2fluid/data/uedge.grd.pdb b/examples/tokamak-2fluid/data/uedge.grd.pdb deleted file mode 100644 index a4b05a26d5..0000000000 Binary files a/examples/tokamak-2fluid/data/uedge.grd.pdb and /dev/null differ diff --git a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh3.nc b/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh3.nc deleted file mode 100644 index d7dba2d1c3..0000000000 Binary files a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh3.nc and /dev/null differ diff --git a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh3.pdb b/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh3.pdb deleted file mode 100644 index 3bbf33e0c4..0000000000 Binary files a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh3.pdb and /dev/null differ diff --git a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh5.nc b/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh5.nc deleted file mode 100644 index b142f32ece..0000000000 Binary files a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh5.nc and /dev/null differ diff --git a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh5.pdb b/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh5.pdb deleted file mode 100644 index e2d5821bc9..0000000000 Binary files a/examples/tokamak-2fluid/data/uedge.grd_rbtok_20x32_tanh5.pdb and /dev/null differ diff --git a/examples/tokamak-2fluid/idlTools/compile_all.pro b/examples/tokamak-2fluid/idlTools/compile_all.pro deleted file mode 100644 index 7c9e767beb..0000000000 --- a/examples/tokamak-2fluid/idlTools/compile_all.pro +++ /dev/null @@ -1,5 +0,0 @@ -$rm -f *.so; ln -s ../../../PDB2IDL/pdb2idl.so . -.run ../../../idllib/pdb2idl.pro -.run ../../../idllib/moment_xyzt.pro -.run idlTools/get_bpp_data -.run idlTools/show_nphi diff --git a/examples/tokamak-2fluid/idlTools/compile_all_b06.pro b/examples/tokamak-2fluid/idlTools/compile_all_b06.pro deleted file mode 100644 index e8d8e7e9ce..0000000000 --- a/examples/tokamak-2fluid/idlTools/compile_all_b06.pro +++ /dev/null @@ -1,19 +0,0 @@ -$rm *.so -$ln -s $HOME/BoutDataAnalysis/PDB2IDL/pdb2idl.so . - -pwd=getenv('PWD') -cd,'$HOME/BoutDataAnalysis/' - -.run PDB2IDL/pdb2idl.pro -.run PDB2IDL/reformat.pro -.run Plots2D/moment_xyzt.pro -.run Plots2D/allrms.pro - -.run UEgrid/curvature.pro -.run GRD2PDB/grd2pdb -.run UEgrid/read_uedgegrd - -.run UEgrid/read_uedata.pro -.run UEgrid/read_uedata3.pro - -cd,pwd diff --git a/examples/tokamak-2fluid/idlTools/doplot2.pro b/examples/tokamak-2fluid/idlTools/doplot2.pro deleted file mode 100644 index cea588dc6b..0000000000 --- a/examples/tokamak-2fluid/idlTools/doplot2.pro +++ /dev/null @@ -1,10 +0,0 @@ -;===============================================; - -Get_bpp_data, du=dubpp, t=tbpp, a=armsbpp - -loadct,39 -SHOW_NPHI, arms=armsbpp, du=dubpp,/fill,/al, it=99 - - -plot, tbpp, armsbpp.NI_XYZT[10,15,*],/yl, xtitle="time, [s]", ytitle="RMS" -mark, x=x1, y=y1 & mark, x=x2, y=y2 & gamma=alog(y2/y1)/(x2-x1) & print, "gamma=", gamma diff --git a/examples/tokamak-2fluid/idlTools/get_b06_data.pro b/examples/tokamak-2fluid/idlTools/get_b06_data.pro deleted file mode 100644 index 192603a252..0000000000 --- a/examples/tokamak-2fluid/idlTools/get_b06_data.pro +++ /dev/null @@ -1,41 +0,0 @@ -pro get_b06_data, arms=arms, du=du, t=t, wci=wci, ni=ni, phi=phi, rho=rho, jpar=jpar, debug=debug, file=file -; -; -; - -if not keyword_set(FILE) then file='BOUT_FLUC_xyzt.pdb' -print, "Restoring data from ", file -d=pd_import(file) - -gridFile="uedge.grd.pdb" -print, "Importing BOUT-06 grid from ", gridfile -du=pd_import(gridFile) - -wci=d.wci -t=d.t_array/wci ;;-[s] - -ni =d.ni_xyzt[*,*,0:d.ngz-2,*] -phi =d.phi_xyzt[*,*,0:d.ngz-2,*] -rho =d.rho_xyzt[*,*,0:d.ngz-2,*] -jpar=d.jpar_xyzt[*,*,0:d.ngz-2,*] - - -;if keyword_set(ARMS) then begin - MOMENT_XYZT, ni, rms=rms_ni - MOMENT_XYZT, phi, rms=rms_phi - MOMENT_XYZT, rho, rms=rms_rho - MOMENT_XYZT, jpar, rms=rms_jpar - - - arms={$ - ni_xyzt:rms_ni,$ - phi_xyzt:rms_phi,$ - rho_xyzt:rms_rho,$ - jpar_xyzt:rms_jpar} -;endif - -; -; -; -if keyword_set(DEBUG) then STOP -end diff --git a/examples/tokamak-2fluid/idlTools/get_bpp_data.pro b/examples/tokamak-2fluid/idlTools/get_bpp_data.pro deleted file mode 100644 index 8b7b2aa5dd..0000000000 --- a/examples/tokamak-2fluid/idlTools/get_bpp_data.pro +++ /dev/null @@ -1,36 +0,0 @@ -pro get_bpp_data, arms=arms, du=du, t=t, wci=wci, ni=ni, phi=phi, rho=rho, jpar=jpar, debug=debug, file=file -; -; -; - -du=pd_import("data/uedge.grd.pdb") - -d = collect(path="data", var="Ni") -moment_xyzt, d, rms=rms_ni - -d = collect(path="data", var="phi") -moment_xyzt, d, rms=rms_phi - -d = collect(path="data", var="rho") -moment_xyzt, d, rms=rms_rho - -d = collect(path="data", var="jpar") -moment_xyzt, d, rms=rms_jpar - - -arms={$ - ni_xyzt:rms_ni[*,*,1:*],$ - phi_xyzt:rms_phi[*,*,1:*],$ - rho_xyzt:rms_rho[*,*,1:*],$ - jpar_xyzt:rms_jpar[*,*,1:*]} - - -tt = collect(path="data", var="t_array") -wci = collect(path="data", var="wci") -t = tt[1:*] / wci - -; -; -; -if keyword_set(DEBUG) then STOP -end diff --git a/examples/tokamak-2fluid/idlTools/show_nphi.pro b/examples/tokamak-2fluid/idlTools/show_nphi.pro deleted file mode 100644 index eef695282f..0000000000 --- a/examples/tokamak-2fluid/idlTools/show_nphi.pro +++ /dev/null @@ -1,78 +0,0 @@ -pro show_one, v,r,z, alog=alog, fill=fill, title=title -; -; - -nlev=30 -contour, v, r, z, /iso, nlev=nlev,fill=fill,title=title, c_col=findgen(nlev)*255/nlev - -oplot, r, z, psym=3 -xyouts, chars=1.5, 0.7*(min(r)+max(r))/2, (min(z)+max(z))/2, min(v) -xyouts, chars=1.5, 0.7*(min(r)+max(r))/2, 0.9*(min(z)+max(z))/2, max(v) - -;;stop -; -; -end - - -pro show_two, v1,r1,z1, v2,r2,z2, alog=alog, fill=fill, title1=title1, title2=title2 -; -; -; - -!p.multi=[0,2,1,0,0] -Show_One, v1,r1,z1, alog=alog, fill=fill, title=title1 -Show_One, v2,r2,z2, alog=alog, fill=fill, title=title2 -!p.multi=0 - -; -; -; -end - - - - -pro show_nphi, arms=arms, du=du, alog=alog, fill=fill, it=it -; -; -; - -if not keyword_set(IT) then begin - it=0 - read, it, prompt='it=' -endif -!p.subtitle="it="+STRTRIM(STRING(it),2) - - -rb06=du.rxy -zb06=du.zxy -rbpp=du.rxy -zbpp=du.zxy - - -!p.multi=[0,2,1,0,0] - - vb06=REFORM(arms.ni_xyzt[*,*,it]) - title="RMS" - if keyword_set(ALOG) then begin - vb06=alog(vb06+1e-20) - title="ALOG("+title+")" - endif - SHOW_ONE, vb06,rb06,zb06, alog=alog, fill=fill, title=title - - - vb06=REFORM(arms.phi_xyzt[*,*,it]) - title="RMS" - if keyword_set(ALOG) then begin - vb06=alog(vb06+1e-20) - title="ALOG("+title+")" - endif - SHOW_ONE, vb06,rb06,zb06, alog=alog, fill=fill, title=title - -!p.multi=0 -!p.subtitle='' -; -; -; -end diff --git a/examples/tokamak-2fluid/uedge.grd.nc b/examples/tokamak-2fluid/uedge.grd.nc deleted file mode 100644 index e70a6a4258..0000000000 Binary files a/examples/tokamak-2fluid/uedge.grd.nc and /dev/null differ diff --git a/examples/tokamak-2fluid/uedge.grd_129131_newpproc.nc b/examples/tokamak-2fluid/uedge.grd_129131_newpproc.nc deleted file mode 100644 index a0f02ae17a..0000000000 Binary files a/examples/tokamak-2fluid/uedge.grd_129131_newpproc.nc and /dev/null differ diff --git a/examples/uedge-benchmark/CMakeLists.txt b/examples/uedge-benchmark/CMakeLists.txt deleted file mode 100644 index 7b2648ff2d..0000000000 --- a/examples/uedge-benchmark/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -project(uedge-benchmark LANGUAGES CXX) - -if (NOT TARGET bout++::bout++) - find_package(bout++ REQUIRED) -endif() - -bout_add_example(uedge-benchmark - SOURCES ue_bmark.cxx - EXTRA_FILES uedge.grd_Up_Ni_Tei_2d.nc) diff --git a/examples/uedge-benchmark/README.md b/examples/uedge-benchmark/README.md deleted file mode 100644 index 6afb7b2f27..0000000000 --- a/examples/uedge-benchmark/README.md +++ /dev/null @@ -1,10 +0,0 @@ -UEDGE benchmark case -==================== - -Solves equations for -* density `Ni` -* parallel ion velocity `Vi` -* electron and ion temperatures `Te`, `Ti` - -Intended to be run for `nz = 1` (i.e. `X` and `Y` only) for comparison with -[`UEDGE`](https://github.com/LLNL/UEDGE) diff --git a/examples/uedge-benchmark/data/BOUT.inp b/examples/uedge-benchmark/data/BOUT.inp deleted file mode 100644 index 86cb361067..0000000000 --- a/examples/uedge-benchmark/data/BOUT.inp +++ /dev/null @@ -1,117 +0,0 @@ -# settings file for BOUT++ UEDGE benchmark test - -################################################## -# settings used by the core code - -nout = 400 # number of time-steps -timestep = 1000.0 # time between outputs - -twistshift = false # use twist-shift condition? - -MZ = 2 # number of points in z direction (2^n + 1) -ZMIN = 0.0 -ZMAX = 0.05546 - -MXG = 2 -MYG = 2 - -grid = "uedge.grd_Up_Ni_Tei_2d.nc" - -################################################## -# derivative methods - -[mesh:ddx] - -first = C2 # order of first x derivatives (options are 2 or 4) -second = C2 # order of second x derivatives (2 or 4) -upwind = U1 # order of upwinding method (1, 4, or 0 = TVD) - -[mesh:ddy] - -first = C4 -second = C2 -upwind = U1 - -[mesh:ddz] - -first = C4 -second = C4 -upwind = U1 - -################################################## -# Solver settings - -[solver] - -# mudq, mldq, mukeep, mlkeep preconditioner options -mxstep = 5000 # Maximum number of internal steps -atol = 1e-10 # absolute tolerance -rtol = 1e-05 # relative tolerance - -################################################## -# settings for uedge model - -[uedge] - -AA = 2.0 -ZZ = 1.0 - -chi_perp = 0.6 - -################################################## -# settings for individual variables -# The section "All" defines default settings for all variables -# These can be overridden for individual variables in -# a section of that name. - -[all] -scale = 0.0 # default size of initial perturbations -function = gauss(x - 0.5, 0.5) * sin(y) * mixmode(z) - -# boundary conditions -# ------------------- -# dirichlet = zero value -# dirichlet(val) = Fix at val -# neumann = zero gradient -# zerolaplace = Laplacian = 0, decaying solution -# constlaplace = Laplacian = 0, decaying solution -# -# Regions: core, pf, sol, target -# xin, xout, ydown, yup, all -# -# All boundaries can be made relaxing e.g. -# "relax(dirichlet(1.))" will relax towards 1 -# To specify a relaxation rate (1/timescale), pass an argument to relax: -# "relax(dirichlet(1.), 10)" sets the rate to 10. (the default). -# -# NOTE: The boundary quantities are normalised to -# the values set in the grid file: -# Te_x = 10 eV -# Ni_x = 1.e13 cm^-3 -# Vi_x = 21850.0 cm/s NB: Depends on bmag, Te_x, AA and ZZ - -bndry_all = neumann # Default for all variables, boundaries - -[Ni] - -bndry_target = neumann -bndry_core = relax(dirichlet(1.)) # 1e13 cm^-3 on core boundary -bndry_all = relax(dirichlet(0.1)) # 1e12 cm^-3 on all other boundaries - -[Vi] - -bndry_core = neumann -bndry_pf = neumann -bndry_sol = neumann -bndry_ydown = relax(dirichlet(-1.41648)) # -3.095e4/Vi_x -bndry_yup = relax(dirichlet( 1.41648)) - -[Te] - -bndry_core = relax(dirichlet(10.)) # 100eV / Te_x on core boundary -bndry_all = relax(dirichlet(1.)) # Relax to 10.eV / Te_x on other boundaries - -[Ti] - -bndry_core = relax(dirichlet(10.)) -bndry_all = relax(dirichlet(1.)) diff --git a/examples/uedge-benchmark/plotresult.pro b/examples/uedge-benchmark/plotresult.pro deleted file mode 100644 index 0d2c10fc49..0000000000 --- a/examples/uedge-benchmark/plotresult.pro +++ /dev/null @@ -1,178 +0,0 @@ -; Produce plots of the result -; Keywords: -; /orig Over-plot original result as symbols -; /output Write plots to a PS file result.ps -; /nodata Reproduce original plot (no new data) -; /nouedge Don't overplot UEDGE result - -PRO plotresult, orig=orig, output=output, nodata=nodata, nouedge=nouedge - -path = "data/" - -; set the time axis range and units -tmax = 4.0 -tfactor = 1000. -xtitle="Time [ms]" - -IF NOT KEYWORD_SET(nodata) THEN BEGIN - -;; read time-base - -tarr = collect(path=path, var="t_array") -wci = collect(path=path, var="wci") - -time = tarr*tfactor / wci - -nt = N_ELEMENTS(tarr) - -;; collect data - -ni = collect(path=path, var="Ni", y=40) -vi = collect(path=path, var="Vi", y=40) -ti = collect(path=path, var="Ti", y=40) -te = collect(path=path, var="Te", y=40) - -;; read normalisations - -ni_x = collect(path=path, var="Ni_x") -rho_s = collect(path=path, var="rho_s") -Vi_x = rho_s * wci -Te_x = collect(path=path, var="Te_x") - -;; read grid file - -u = file_import("uedge.grd_Up_Ni_Tei_2d.nc") - -;; Normalise - -nit = reform(ni[*,0,0,*])*ni_x -FOR t=0, nt-1 DO nit[*,t] = nit[*,t] + u.ni0[*,40]*1.e14 - -vit = REFORM(vi) * vi_x - -tit = reform(ti[*,0,0,*])*te_x -FOR t=0, nt-1 DO tit[*,t] = tit[*,t] + u.Ti0[*,40] - -tet = reform(te[*,0,0,*])*te_x -FOR t=0, nt-1 DO tet[*,t] = tet[*,t] + u.Te0[*,40] - -ENDIF ELSE BEGIN - ; Make original plot (no new data) - - RESTORE, "result_080917.idl" - - time = time_orig - nit = ni_orig - vit = vi_orig - tit = ti_orig - tet = te_orig - orig = 0 -ENDELSE - -;; restore the original data (if needed) - -IF KEYWORD_SET(orig) THEN BEGIN - RESTORE, "result_080917.idl" -ENDIF - -IF NOT KEYWORD_SET(nouedge) THEN BEGIN - RESTORE, "ue_bmk.idl" - - time_ue = time_ue * tfactor - - ni_ue = ni_ue * 1.e-6 ; convert to cm^-3 -ENDIF - -;; Produce plots - -IF KEYWORD_SET(output) THEN BEGIN - SET_PLOT, 'PS' - DEVICE, file="result.ps", /color, /landscape -ENDIF - -safe_colors, /first - -!P.MULTI=[0,2,2,0,0] - -;; NI - -plot, time, nit[40,*], color=1, xr=[0,tmax], xstyle=1, xtitle=xtitle, title="Ni" -oplot, time, nit[20,*], color=2 -oplot, time, nit[10,*], color=4 - -IF KEYWORD_SET(orig) THEN BEGIN - oplot, time_orig, ni_orig[40,*], color=1, lines=1 - oplot, time_orig, ni_orig[20,*], color=2, lines=1 - oplot, time_orig, ni_orig[10,*], color=4, lines=1 -ENDIF - -IF NOT KEYWORD_SET(nouedge) THEN BEGIN - oplot, time_ue, ni_ue[*,10], color=3, thick=1.5 - oplot, time_ue, ni_ue[*,20], color=3, thick=1.5 - oplot, time_ue, ni_ue[*,40], color=3, thick=1.5 -ENDIF - -;; VI - -plot, time, vit[40,*], color=1, xr=[0,tmax], xstyle=1, xtitle=xtitle, title="Vi" -oplot, time, vit[20,*], color=2 -oplot, time, vit[10,*], color=4 - -IF KEYWORD_SET(orig) THEN BEGIN - oplot, time_orig, vi_orig[40,*], color=1, lines=1 - oplot, time_orig, vi_orig[20,*], color=2, lines=1 - oplot, time_orig, vi_orig[10,*], color=4, lines=1 -ENDIF - -IF NOT KEYWORD_SET(nouedge) THEN BEGIN - oplot, time_ue, vi_ue[*,10], color=3, thick=1.5 - oplot, time_ue, vi_ue[*,20], color=3, thick=1.5 - oplot, time_ue, vi_ue[*,40], color=3, thick=1.5 -ENDIF - -;; TI - -plot, time, tit[40,*], color=1, xr=[0,tmax], xstyle=1, xtitle=xtitle, title="Ti", yr=[0,MAX(tit)] -oplot, time, tit[20,*], color=2 -oplot, time, tit[10,*], color=4 - -IF KEYWORD_SET(orig) THEN BEGIN - oplot, time_orig, ti_orig[40,*], color=1, lines=1 - oplot, time_orig, ti_orig[20,*], color=2, lines=1 - oplot, time_orig, ti_orig[10,*], color=4, lines=1 -ENDIF - -IF NOT KEYWORD_SET(nouedge) THEN BEGIN - oplot, time_ue, ti_ue[*,10], color=3, thick=1.5 - oplot, time_ue, ti_ue[*,20], color=3, thick=1.5 - oplot, time_ue, ti_ue[*,40], color=3, thick=1.5 -ENDIF - -;; TE - -plot, time, tet[40,*], color=1, xr=[0,tmax], xstyle=1, xtitle=xtitle, title="Te", yr=[0,MAX(tet)] -oplot, time, tet[20,*], color=2 -oplot, time, tet[10,*], color=4 - -IF KEYWORD_SET(orig) THEN BEGIN - oplot, time_orig, te_orig[40,*], color=1, lines=1 - oplot, time_orig, te_orig[20,*], color=2, lines=1 - oplot, time_orig, te_orig[10,*], color=4, lines=1 -ENDIF - -IF NOT KEYWORD_SET(nouedge) THEN BEGIN - oplot, time_ue, te_ue[*,10], color=3, thick=1.5 - oplot, time_ue, te_ue[*,20], color=3, thick=1.5 - oplot, time_ue, te_ue[*,40], color=3, thick=1.5 -ENDIF - -IF KEYWORD_SET(output) THEN BEGIN - DEVICE, /close - SET_PLOT, 'X' -ENDIF - -!P.MULTI=0 - -STOP -END - diff --git a/examples/uedge-benchmark/qsubcase.sh b/examples/uedge-benchmark/qsubcase.sh deleted file mode 100755 index fe871e6117..0000000000 --- a/examples/uedge-benchmark/qsubcase.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -QSUB=mpich2sub # Common values are qsub, mpisub -NP=16 - -# compile -make - -echo Running with NP = $NP - -# run case -$QSUB $NP ./ue_bmark - diff --git a/examples/uedge-benchmark/result.ps b/examples/uedge-benchmark/result.ps deleted file mode 100644 index 61f0e980af..0000000000 Binary files a/examples/uedge-benchmark/result.ps and /dev/null differ diff --git a/examples/uedge-benchmark/runcase.sh b/examples/uedge-benchmark/runcase.sh deleted file mode 100755 index d4234c81ca..0000000000 --- a/examples/uedge-benchmark/runcase.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -MPIEXEC=mpirun -NP=16 - -# compile -make - -echo Running with NP = $NP - -# run case -$MPIEXEC -np $NP ./ue_bmark - diff --git a/examples/uedge-benchmark/runidl.pro b/examples/uedge-benchmark/runidl.pro deleted file mode 100644 index 10f4b019b9..0000000000 --- a/examples/uedge-benchmark/runidl.pro +++ /dev/null @@ -1,4 +0,0 @@ -.r pdb2idl - -plotresult - diff --git a/examples/uedge-benchmark/ue_bmark.cxx b/examples/uedge-benchmark/ue_bmark.cxx deleted file mode 100644 index 2d03885c45..0000000000 --- a/examples/uedge-benchmark/ue_bmark.cxx +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************************* - * UEDGE benchmark case - * - * Solves equations for - * density Ni - * parallel ion velocity Vi - * electron and ion temperatures Te, Ti - * - * Intended to be run for NZ=1 (i.e. X and Y only) for comparison with UEDGE - * - *******************************************************************************/ - -#include -#include -#include - -#include - -class UedgeBenchmark : public PhysicsModel { -private: - // 2D initial profiles - Field2D Ni0, Ti0, Te0, Vi0; - - // 3D evolving fields - Field3D Te, Ni, Vi, Ti; - - // Non-linear coefficients - Field3D kapa_Te, kapa_Ti; - - // 3D total values - Field3D Nit, Tit, Tet, Vit; - - // pressures - Field3D peit, pe; - Field2D pei0, pe0; - - // Metric coefficients - Field2D Rxy, Bpxy, Btxy, hthe; - - // parameters - BoutReal Te_x, Ti_x, Ni_x, Vi_x, bmag, rho_s, fmei, AA, ZZ; - BoutReal lambda_ei, lambda_ii; - BoutReal nu_hat, mui_hat, wci, nueix, nuiix; - - BoutReal chi_perp, D_perp, mu_perp; - -protected: - int init(bool UNUSED(restarting)) { - Field2D I; // Shear factor - - output.write("Solving transport equations for Ni, Vi, Ti, Te\n"); - - /////////////// LOAD DATA FROM GRID FILE ////////////// - - // Load 2D profiles (set to zero if not found) - GRID_LOAD(Ni0, Ti0, Te0, Vi0); - - // Load metrics - GRID_LOAD(Rxy); // Major radius [m] - GRID_LOAD(Bpxy, Btxy); // Poloidal, Toroidal B field [T] - GRID_LOAD(hthe); // Poloidal arc length [m / radian] - mesh->get(mesh->getCoordinates()->dx, "dpsi"); - - // Load normalisation values - GRID_LOAD(Te_x, Ti_x, Ni_x, bmag); - - Ni_x *= 1.0e14; - bmag *= 1.0e4; - - /////////////// READ OPTIONS ////////////////////////// - - // Read some parameters - auto& globalOptions = Options::root(); - auto& options = globalOptions["uedge"]; - AA = options["AA"].withDefault(2.0); - ZZ = options["ZZ"].withDefault(1.0); - - chi_perp = options["chi_perp"].withDefault(0.6); // Read in m^2 / s - D_perp = options["D_perp"].withDefault(0.6); - mu_perp = options["mu_perp"].withDefault(0.6); - - ////////////// CALCULATE PARAMETERS /////////////////// - - rho_s = 1.02 * sqrt(AA * Te_x) / ZZ / bmag; - fmei = 1. / 1836.2 / AA; - - lambda_ei = 24. - log(sqrt(Ni_x) / Te_x); - lambda_ii = 23. - log(ZZ * ZZ * ZZ * sqrt(2. * Ni_x) / pow(Ti_x, 1.5)); - wci = 9.58e3 * ZZ * bmag / AA; - nueix = 2.91e-6 * Ni_x * lambda_ei / pow(Te_x, 1.5); - nuiix = 4.78e-8 * pow(ZZ, 4.) * Ni_x * lambda_ii / pow(Ti_x, 1.5) / sqrt(AA); - - Vi_x = wci * rho_s; - - ///////////// PRINT Z INFORMATION ///////////////////// - - BoutReal hthe0; - if (GRID_LOAD1(hthe0) == 0) { - output.write( - " ****NOTE: input from BOUT, Z length needs to be divided by {:e}\n", - hthe0 / rho_s); - } - - ///////////// NORMALISE QUANTITIES //////////////////// - - output.write("\tNormalising to rho_s = {:e}\n", rho_s); - - auto* coords = mesh->getCoordinates(); - // Normalise profiles - Ni0 /= Ni_x / 1.0e14; - Ti0 /= Te_x; - Te0 /= Te_x; - Vi0 /= Vi_x; - - // Normalise geometry - Rxy /= rho_s; - hthe /= rho_s; - coords->dx /= rho_s * rho_s * (bmag / 1e4); - - // Normalise magnetic field - Bpxy /= (bmag / 1e4); - Btxy /= (bmag / 1e4); - coords->Bxy /= (bmag / 1e4); - - // calculate pressures - pei0 = (Ti0 + Te0) * Ni0; - pe0 = Te0 * Ni0; - - // Normalise coefficients - chi_perp /= rho_s * rho_s * wci; - D_perp /= rho_s * rho_s * wci; - mu_perp /= rho_s * rho_s * wci; - - chi_perp = 0.1; - D_perp = 0.1; - mu_perp = 0.1; - - output.write("Diffusion coefficients: chi {:e} D {:e} Mu {:e}\n", chi_perp, D_perp, - mu_perp); - - /////////////// CALCULATE METRICS ///////////////// - - coords->g11 = pow(Rxy * Bpxy, 2.0); - coords->g22 = 1.0 / pow(hthe, 2.0); - coords->g33 = pow(coords->Bxy, 2.0) / coords->g11; - coords->g12 = 0.0; - coords->g13 = 0.0; - coords->g23 = -Btxy / (hthe * Bpxy * Rxy); - - coords->J = hthe / Bpxy; - - coords->g_11 = 1.0 / coords->g11; - coords->g_22 = pow(coords->Bxy * hthe / Bpxy, 2.0); - coords->g_33 = Rxy * Rxy; - coords->g_12 = 0.0; - coords->g_13 = 0.0; - coords->g_23 = Btxy * hthe * Rxy / Bpxy; - - coords->geometry(); // Calculate other metrics - - //////////////// BOUNDARIES /////////////////////// - // - // We want to apply the relaxing boundries to total density, - // temperature etc. - - Nit.setBoundary("Ni"); - Tet.setBoundary("Te"); - Tit.setBoundary("Ti"); - Vit.setBoundary("Vi"); - - Ni0.applyBoundary("neumann"); - Te0.applyBoundary("neumann"); - Ti0.applyBoundary("neumann"); - - ///////////// SET EVOLVING VARIABLES ////////////// - // - // Tell BOUT++ which variables to evolve - - SOLVE_FOR(Ni, Vi, Te, Ti); - - ///////////// ADD OUTPUT VARIABLES //////////////// - // - // Add any other variables to be dumped to file - - SAVE_ONCE(Ni0, Te0, Ti0); // Background quantities - SAVE_ONCE(Te_x, Ti_x, Ni_x, rho_s, wci); // Normalisation factors - - return 0; - } - - // Operator for radial diffusive flux - /* - Field3D Div_X_K_Grad_X(const Field3D &difVi, const Field3D &Vi) { - Field2D sg = 1./sqrt(mesh->g_11); - return difVi * D2DX2(Vi)/mesh->g_11 - + DDX( difVi * sg ) * DDX(Vi) * sg; - } - */ - - // This version the same as in BOUT-06. Note the R's moved,and hthe added - Field3D Div_X_K_Grad_X(const Field3D& difFi, const Field3D& Fi) { - Field3D result; - - result = difFi * (pow(Rxy * Bpxy, 2.0)) * D2DX2(Fi) - + (Bpxy / hthe) * DDX(difFi * Rxy * Rxy * Bpxy * hthe) * DDX(Fi); - - return result; - } - - int rhs(BoutReal UNUSED(t)) { - // Communicate variables - mesh->communicate(Ni, Vi, Te, Ti); - - // Update profiles - Nit = Ni0 + DC(Ni); - Tit = Ti0 + DC(Ti); - Tet = Te0 + DC(Te); - Vit = Vi0 + DC(Vi); - - // Apply boundary conditions to total fields - Nit.applyBoundary(); - Tet.applyBoundary(); - Tit.applyBoundary(); - Vit.applyBoundary(); - - // Update non-linear coefficients on the mesh - kapa_Te = 3.2 * (1. / fmei) * (wci / nueix) * pow(Tet, 2.5); - kapa_Ti = 3.9 * (wci / nuiix) * pow(Tit, 2.5); - - peit = (Tet + Tit) * Nit; - - // DENSITY EQUATION - ddt(Ni) = -Vpar_Grad_par(Vit, Nit) - Nit * Div_par(Vit) - + Div_X_K_Grad_X(D_perp * (Nit * 0.0 + 1.0), Nit); - - // ION VELOCITY - ddt(Vi) = (-Grad_par(peit) + Div_X_K_Grad_X(mu_perp * Nit, Vit)) / Nit - - Vpar_Grad_par(Vit, Nit * Vit) / Nit - ddt(Ni) * Vit / Nit; - - // ELECTRON TEMPERATURE - ddt(Te) = (Div_par_K_Grad_par(kapa_Te, Tet) + Div_X_K_Grad_X(chi_perp * Nit, Tet)) - / (1.5 * Nit) - - ddt(Ni) * Tet / Nit; - - // ION TEMPERATURE - ddt(Ti) = (Div_par_K_Grad_par(kapa_Ti, Tit) + Div_X_K_Grad_X(chi_perp * Nit, Tit)) - / (1.5 * Nit) - - ddt(Ni) * Tit / Nit; - - return 0; - } -}; - -BOUTMAIN(UedgeBenchmark); diff --git a/examples/uedge-benchmark/uedge.grd_Up_Ni_Tei_2d.nc b/examples/uedge-benchmark/uedge.grd_Up_Ni_Tei_2d.nc deleted file mode 100644 index d534855699..0000000000 Binary files a/examples/uedge-benchmark/uedge.grd_Up_Ni_Tei_2d.nc and /dev/null differ diff --git a/examples/uedge-benchmark/uedge.grd_Up_Ni_Tei_2d.pdb b/examples/uedge-benchmark/uedge.grd_Up_Ni_Tei_2d.pdb deleted file mode 100644 index 299cde0a4f..0000000000 Binary files a/examples/uedge-benchmark/uedge.grd_Up_Ni_Tei_2d.pdb and /dev/null differ diff --git a/examples/zoidberg/README.md b/examples/zoidberg/README.md deleted file mode 100644 index b500c09b01..0000000000 --- a/examples/zoidberg/README.md +++ /dev/null @@ -1,16 +0,0 @@ -Example Zoidberg grid generation -================================ - -Here are several examples of generating grids using Zoidberg for simulations -using the FCI parallel transform: - -- `example-straight-stellarator.py`: A "straight stellarator", a rotating - ellipse stellarator without curvature -- `straight-stellarator-curvilinear.py`: A straight stellarator but based on - curvilinear grids -- `tokamak.py`: A tokamak grid generated from an EFIT "geqdsk" file - -The remaining files demonstrate some of the plotting capabilities of Zoidberg: - -- `field_line.py`: 3D plots of magnetic field lines -- `poincare.py`: A Poincaré plot of a straight stellarator diff --git a/examples/zoidberg/example-straight-stellarator.py b/examples/zoidberg/example-straight-stellarator.py deleted file mode 100755 index 52c794608f..0000000000 --- a/examples/zoidberg/example-straight-stellarator.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -import zoidberg -import matplotlib.pyplot as plt - -nx = 5 -ny = 6 -nz = 7 - -# Create magnetic field -magnetic_field = zoidberg.field.StraightStellarator(radius = 1.0) - -# Create a rectangular grid in (x,y,z) -rectangle = zoidberg.grid.rectangular_grid(nx,ny,nz, - Lx = 1.0, Lz = 1.0, Ly = 10.0, - yperiodic = True) - -# Here both the field and and grid are centred at (x,z) = (0,0) -# and the rectangular grid here fits entirely within the coils - -maps = zoidberg.make_maps(rectangle, magnetic_field) - -# Pick a poloidal slice and the next slice -yslice = 0 -pol, ycoord = rectangle.getPoloidalGrid(yslice) -pol_next, ycoord_next = rectangle.getPoloidalGrid(yslice+1) - -# Plot the grid points at this poloidal slice -plt.plot(pol.R, pol.Z, 'x') - -# Get the coordinates which the forward map corresponds to -R_next, Z_next = pol_next.getCoordinate( maps['forward_xt_prime'][:,yslice,:], maps['forward_zt_prime'][:,yslice,:] ) - -plt.plot(R_next, Z_next, 'o') - -plt.show() - - diff --git a/examples/zoidberg/field_line.py b/examples/zoidberg/field_line.py deleted file mode 100755 index 359c115219..0000000000 --- a/examples/zoidberg/field_line.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python - -# Demonstrates how to generate 3D plots of magnetic field lines - -import zoidberg - -# Size of the domain in y (periodic) -yperiod = 10. - -# Define magnetic field -magnetic_field = zoidberg.field.StraightStellarator(I_coil=0.4, radius = 1.0, yperiod = yperiod) - -# Make 3D plot -zoidberg.plot.plot_3d_field_line(magnetic_field, - 0.3, # x starting position - 0.0, # z starting position - yperiod, # Periodicity of y domain - cycles = 20) diff --git a/examples/zoidberg/g014220.00200 b/examples/zoidberg/g014220.00200 deleted file mode 120000 index fe3bc63546..0000000000 --- a/examples/zoidberg/g014220.00200 +++ /dev/null @@ -1 +0,0 @@ -../../tools/tokamak_grids/gridgen/efit/g014220.00200 \ No newline at end of file diff --git a/examples/zoidberg/poincare.py b/examples/zoidberg/poincare.py deleted file mode 100755 index 8b361ae3cf..0000000000 --- a/examples/zoidberg/poincare.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python - -# Demonstrates how to generate Poincare plots of magnetic fields - -import zoidberg - -# Size of the domain in y (periodic) -yperiod = 10. - -# Define magnetic field -magnetic_field = zoidberg.field.StraightStellarator(I_coil=0.4, radius = 1.0, yperiod = yperiod) - -# Make Poincare plot -zoidberg.plot.plot_poincare(magnetic_field, - np.linspace(0,0.5,5), # x starting positions - 0.0, # z starting positions - yperiod, # Periodicity of y domain - interactive=True) # Click on plot to add points diff --git a/examples/zoidberg/straight-stellarator-curvilinear.py b/examples/zoidberg/straight-stellarator-curvilinear.py deleted file mode 100755 index 6b96c2f520..0000000000 --- a/examples/zoidberg/straight-stellarator-curvilinear.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python - -# Create grids for a straight stellarator, based on curvilinear grids - -import numpy as np - -import zoidberg - - -############################################################################# -# Define the magnetic field - -# Length in y after which the coils return to their starting (R,Z) locations -yperiod = 10. - -magnetic_field = zoidberg.field.StraightStellarator(I_coil=0.3, radius = 1.0, yperiod = yperiod) - -############################################################################# -# Create the inner flux surface, starting at a point at phi=0 -# To do this we need to define the y locations of the poloidal points -# where we will construct grids - -start_r = 0.2 -start_z = 0.0 - -nslices = 8 # Number of poloidal slices -ycoords = np.linspace(0, yperiod, nslices) -npoints = 20 # Points per poloidal slice - -rzcoord, ycoords = zoidberg.fieldtracer.trace_poincare(magnetic_field, start_r, start_z, yperiod, - y_slices=ycoords, revs=npoints) - -inner_lines = [] -for i in range(nslices): - r = rzcoord[:,i,0] - z = rzcoord[:,i,1] - line = zoidberg.rzline.line_from_points(r,z) - # Re-map the points so they're approximately uniform in distance along the surface - # Note that this results in some motion of the line - line = line.equallySpaced() - inner_lines.append(line) - -# Now have a list of y coordinates (ycoords) and inner lines (inner_lines) - -############################################################################# -# Generate a fixed circle for the outer boundary - -outer_line = zoidberg.rzline.circle(R0=0.0, r=0.8) - -############################################################################# -# Now have inner and outer boundaries for each poloidal grid -# Generate a grid on each poloidal slice using the elliptic grid generator - -nx = 20 -ny = 20 - -pol_grids = [ zoidberg.poloidal_grid.grid_elliptic(inner_line, outer_line, nx,ny) for inner_line in inner_lines ] - -############################################################################# -# Create a grid, then calculate forward and backward maps - -grid = zoidberg.grid.Grid( pol_grids, ycoords, yperiod, yperiodic=True) - -maps = zoidberg.make_maps(grid, magnetic_field) - -############################################################################# -# Write grid file - -filename = "stellarator.fci.nc" - -print("Writing to grid file '{0}'".format(filename)) -zoidberg.write_maps(grid, magnetic_field, maps, gridfile=filename, new_names=False, metric2d=True) - -############################################################################# -# Plot maps - -zoidberg.plot.plot_forward_map(grid, maps) diff --git a/examples/zoidberg/straight-stellarator-poincare.py b/examples/zoidberg/straight-stellarator-poincare.py deleted file mode 100644 index d81e179390..0000000000 --- a/examples/zoidberg/straight-stellarator-poincare.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -# Create grids for a straight stellarator, based on -# curvilinear grids - -import numpy as np -import matplotlib.pyplot as plt - -import zoidberg - -############################################################################# -# Define the magnetic field - -# Length in y after which the coils return to their starting (R,Z) locations -yperiod = 10. - -magnetic_field = zoidberg.field.StraightStellarator(I_coil=0.4, radius = 1.0, yperiod = yperiod) - -start_r = 0.3 -start_z = 0.0 - -nslices = 4 # Number of poloidal slices -ycoords = np.linspace(0, yperiod, nslices) -npoints = 60 # Points per poloidal slice - -# Create a field line tracer -tracer = zoidberg.fieldtracer.FieldTracer(magnetic_field) -#tracer = zoidberg.fieldtracer.FieldTracerReversible(magnetic_field) - -# Extend the y coordinates so the tracer loops npoints times around yperiod -ycoords_all = ycoords -for i in range(1,npoints): - ycoords_all = np.append(ycoords_all, ycoords + i*yperiod) - -coord = tracer.follow_field_lines(start_r, start_z, ycoords_all, rtol=1e-12) - -for i in range(nslices): - r = coord[i::nslices,0] - z = coord[i::nslices,1] - plt.plot(r,z,'o') - -#i = 1 -#plt.plot(coord[i::nslices,0], coord[i::nslices,1],'o') - -plt.show() - - diff --git a/examples/zoidberg/tokamak.py b/examples/zoidberg/tokamak.py deleted file mode 100644 index ea1c9add6a..0000000000 --- a/examples/zoidberg/tokamak.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python - -import numpy as np -import zoidberg - -field = zoidberg.field.GEQDSK("g014220.00200") # Read magnetic field - -grid = zoidberg.grid.rectangular_grid(100, 10, 100, - 1.5-0.1, # Range in R (max - min) - 2*np.pi, # Toroidal angle - 3., # Range in Z - xcentre=(1.5+0.1)/2, # Middle of grid in R - yperiodic=True) # Periodic in toroidal angle - -# Create the forward and backward maps -maps = zoidberg.make_maps(grid, field) - -# Save to file -zoidberg.write_maps(grid, field, maps, gridfile="tokamak.fci.nc") - -############################################################################# -# Plot maps - -zoidberg.plot.plot_forward_map(grid, maps) - diff --git a/include/bout/options.hxx b/include/bout/options.hxx index 4a32907b17..9f3dd46a19 100644 --- a/include/bout/options.hxx +++ b/include/bout/options.hxx @@ -432,25 +432,35 @@ public: /// Assign a value to the option. /// This will throw an exception if already has a value /// - /// Example: + /// Returns + /// ------- + /// A reference to `this`, for method chaining + /// + /// Example + /// ------- /// /// Options option; /// option["test"].assign(42, "some source"); /// /// Note: Specialised versions for types stored in ValueType template - void assign(T val, std::string source = "") { + Options& assign(T val, std::string source = "") { std::stringstream as_str; as_str << val; _set(as_str.str(), std::move(source), false); + return *this; } /// Force to a value /// Overwrites any existing setting + /// + /// Returns + /// ------- + /// A reference to `this`, for method chaining template - void force(T val, const std::string source = "") { + Options& force(T val, const std::string source = "") { is_section = true; // Invalidates any existing setting - assign(val, source); + return assign(val, source); } /// Assign a value that is expected to vary in time. @@ -459,12 +469,13 @@ public: /// attribute is set. If \p save_repeat is false, doesn't set /// "time_dimension". This can be useful in some generic functions template - void assignRepeat(T val, std::string time_dimension = "t", bool save_repeat = true, - std::string source = "") { + Options& assignRepeat(T val, std::string time_dimension = "t", bool save_repeat = true, + std::string source = "") { force(val, std::move(source)); if (save_repeat) { attributes["time_dimension"] = std::move(time_dimension); } + return *this; } /// Test if a key is set by the user. @@ -884,39 +895,44 @@ private: // Specialised assign methods for types stored in ValueType template <> -inline void Options::assign<>(bool val, std::string source) { +inline Options& Options::assign<>(bool val, std::string source) { _set(val, std::move(source), false); + return *this; } template <> -inline void Options::assign<>(int val, std::string source) { +inline Options& Options::assign<>(int val, std::string source) { _set(val, std::move(source), false); + return *this; } template <> -inline void Options::assign<>(BoutReal val, std::string source) { +inline Options& Options::assign<>(BoutReal val, std::string source) { _set(val, std::move(source), false); + return *this; } template <> -inline void Options::assign<>(std::string val, std::string source) { +inline Options& Options::assign<>(std::string val, std::string source) { _set(std::move(val), std::move(source), false); + return *this; } // Note: const char* version needed to avoid conversion to bool template <> -inline void Options::assign<>(const char* val, std::string source) { +inline Options& Options::assign<>(const char* val, std::string source) { _set(std::string(val), std::move(source), false); + return *this; } // Note: Field assignments don't check for previous assignment (always force) template <> -void Options::assign<>(Field2D val, std::string source); +Options& Options::assign<>(Field2D val, std::string source); template <> -void Options::assign<>(Field3D val, std::string source); +Options& Options::assign<>(Field3D val, std::string source); template <> -void Options::assign<>(FieldPerp val, std::string source); +Options& Options::assign<>(FieldPerp val, std::string source); template <> -void Options::assign<>(Array val, std::string source); +Options& Options::assign<>(Array val, std::string source); template <> -void Options::assign<>(Matrix val, std::string source); +Options& Options::assign<>(Matrix val, std::string source); template <> -void Options::assign<>(Tensor val, std::string source); +Options& Options::assign<>(Tensor val, std::string source); /// Specialised similar comparison methods template <> diff --git a/include/options_netcdf.hxx b/include/options_netcdf.hxx deleted file mode 100644 index c0d14c536a..0000000000 --- a/include/options_netcdf.hxx +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -// BOUT++ header shim -#warning Header "options_netcdf.hxx" has moved to "bout/options_netcdf.hxx". Run `bin/bout-v5-header-upgrader.py` to fix -#include "bout/options_netcdf.hxx" diff --git a/manual/sphinx/developer_docs/debugging.rst b/manual/sphinx/developer_docs/debugging.rst new file mode 100644 index 0000000000..805cb5409a --- /dev/null +++ b/manual/sphinx/developer_docs/debugging.rst @@ -0,0 +1,146 @@ +.. _sec-debugging: + +================== + Debugging Models +================== + +When developing a new physics model, or using an existing one in new +regimes, it's expected that things will occasionally go wrong and +you'll need to debug the program. While debuggers like ``gdb`` are +very powerful, using them in parallel can be difficult unless you have +access to a dedicated parallel debugger. BOUT++ has some utilities +that make it easier to debug issues that only arise in parallel and/or +long-running simulations. + +Loggers +======= + +The first of these is the standard "write to screen" with the +``output.write`` :ref:`family of logging functions `. If +you have a bug which is easily reproducible and occurs almost +immediately every time you run the code, then this is probably the +easiest way to hunt it down. + +The main downside of (most of) these loggers is that if you have a lot of +output they will slow down simulations. Even if you use the +``--quiet`` command line option to turn them off, they will still add +some overhead. The `output_debug` logger can be disabled entirely at +compile-time (so there will be no overhead at all), which means it's +well suited to adding in-depth diagnostic or debugging information +that can be kept permanently in the code and only enabled if needed. + +To enable the ``output_debug`` messages, configure BOUT++ with a +``CHECK`` level ``>= 3``. To enable it at lower check levels, +configure BOUT++ with ``-DENABLE_OUTPUT_DEBUG``. When running BOUT++ +add a ``-v -v`` flag to see ``output_debug`` messages. + +Message Stack +============= + +The second utility BOUT++ has to help debugging is the message stack +using the `TRACE` (and related `AUTO_TRACE`) macro. These are very +useful for when a bug only occurs after a long time of running, and/or +only occasionally. The ``TRACE`` macro can simply be dropped in +anywhere in the code:: + + { + TRACE("Some message here"); // message pushed + + } // Scope ends, message popped + +This will push the message, then pop the message when the current +scope ends. If an error occurs or BOUT++ crashes, any un-popped +messages will be printed, along with the file name and line number, to +help find where an error occurred. For example, given this snippet:: + + { + TRACE("1. Outer-most scope"); + { + TRACE("2. Middle scope"); + { + TRACE("3. Scope not appearing in the output"); + } + { + TRACE("4. Inner-most scope"); + throw BoutException("Something went wrong"); + } + } + } + +we would see something like the following output: + +.. code:: text + + ====== Back trace ====== + -> 4. Inner-most scope on line 58 of '/path/to/model.cxx' + -> 2. Middle scope on line 53 of '/path/to/model.cxx' + -> 1. Outer-most scope on line 51 of '/path/to/model.cxx' + + ====== Exception thrown ====== + Something went wrong + +The third ``TRACE`` message doesn't appear in the output because we've +left its scope and it's no longer relevant. + +The run-time overhead of this should be small, but can be removed +entirely if the compile-time flag ``-DCHECK`` is not defined or set to +``0``. This turns off checking, and ``TRACE`` becomes an empty +macro. This means that ``TRACE`` macros can be left in your code +permanently, providing some simple diagnostics without compromising +performance, as well as demarcating separate sections with +user-friendly names. + +If you need to capture runtime information in the message, you can use +the ``fmt`` syntax also used by the loggers:: + + TRACE("Value of i={}, some arbitrary {}", i, "string"); + +There is also an ``AUTO_TRACE`` macro that automatically captures the +name of the function it's used in. This is used throughout the main +library, especially in functions where numerical issues are likely to +arise. + +Backtrace +========= + +Lastly, BOUT++ can also automatically print a backtrace in the event +of a crash. This is a compile-time option in the BOUT++ library +(``-DBOUT_ENABLE_BACKTRACE=ON``, the default, requires the +``addr2line`` program to be installed), and debug symbols to be turned +on (``-DCMAKE_BUILD_TYPE=Debug`` or ``=RelWithDebInfo``) in BOUT++ +_and_ the physics model. If debug symbols are only present in part, the +backtrace will be missing names for the other part. + +The output looks something like this: + +.. code:: text + + ... + Error encountered + ====== Exception path ====== + [bt] #10 ./backtrace() [0x40a27e] + _start at /home/abuild/rpmbuild/BUILD/glibc-2.33/csu/../sysdeps/x86_64/start.S:122 + [bt] #9 /lib64/libc.so.6(__libc_start_main+0xd5) [0x7fecbfa28b25] + __libc_start_main at /usr/src/debug/glibc-2.33-4.1.x86_64/csu/../csu/libc-start.c:332 + [bt] #8 ./backtrace() [0x40a467] + main at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:32 (discriminator 9) + [bt] #7 /path/to/BOUT-dev/build/libbout++.so(_ZN6Solver8setModelEP12PhysicsModel+0xb5) [0x7fecc0ca2e93] + Solver::setModel(PhysicsModel*) at /path/to/BOUT-dev/build/../src/solver/solver.cxx:94 + [bt] #6 /path/to/BOUT-dev/build/libbout++.so(_ZN12PhysicsModel10initialiseEP6Solver+0xc0) [0x7fecc0cad594] + PhysicsModel::initialise(Solver*) at /path/to/BOUT-dev/build/../include/bout/physicsmodel.hxx:93 (discriminator 5) + [bt] #5 ./backtrace() [0x40a986] + Backtrace::init(bool) at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:27 + [bt] #4 ./backtrace() [0x40a3cf] + f3() at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:19 + [bt] #3 ./backtrace() [0x40a3be] + f2(int) at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:15 + [bt] #2 ./backtrace() [0x40a386] + f1() at /path/to/BOUT-dev/build/../examples/backtrace/backtrace.cxx:13 (discriminator 2) + [bt] #1 ./backtrace(_ZN13BoutExceptionC1IA19_cJEEERKT_DpRKT0_+0xba) [0x40ae16] + BoutException::BoutException(char const (&) [19]) at /path/to/BOUT-dev/build/../include/bout/../boutexception.hxx:28 (discriminator 2) + + +This output tends to be much harder to read than the message stack +from ``TRACE`` macros, but the advantage is that it doesn't require +any modifications to the code to use, and can give you more precise +location information. diff --git a/manual/sphinx/index.rst b/manual/sphinx/index.rst index 9f661ca187..c150273285 100644 --- a/manual/sphinx/index.rst +++ b/manual/sphinx/index.rst @@ -97,6 +97,7 @@ The documentation is divided into the following sections: developer_docs/petsc_interface developer_docs/mesh developer_docs/file_io + developer_docs/debugging developer_docs/natural_language developer_docs/performance_profiling diff --git a/manual/sphinx/user_docs/physics_models.rst b/manual/sphinx/user_docs/physics_models.rst index 56e3b719b4..aae4edbb3d 100644 --- a/manual/sphinx/user_docs/physics_models.rst +++ b/manual/sphinx/user_docs/physics_models.rst @@ -161,7 +161,7 @@ During initialisation (the ``init`` function), the conduction example first reads an option (lines 21 and 24) from the input settings file (``data/BOUT.inp`` by default):: - auto options = Options::root()["conduction"]; + auto& options = Options::root()["conduction"]; OPTION(options, chi, 1.0); @@ -500,8 +500,8 @@ object in the initialisation function:: BoutReal gamma; int init(bool restarting) override { - auto globalOptions = Options::root(); - auto options = globalOptions["mhd"]; + auto& globalOptions = Options::root(); + auto& options = globalOptions["mhd"]; OPTION(options, g, 5.0 / 3.0); ... @@ -636,43 +636,28 @@ Finding where bugs have occurred in a (fairly large) parallel code is a difficult problem. This is more of a concern for developers of BOUT++ (see the developers manual), but it is still useful for the user to be able to hunt down bug in their own code, or help narrow -down where a bug could be occurring. +down where a bug could be occurring. BOUT++ comes with a `TRACE` macro +that can be used to easily identify specific regions in a model when +an error occurs. -If you have a bug which is easily reproduceable i.e. it occurs almost -immediately every time you run the code, then the easiest way to hunt -down the bug is to insert lots of ``output.write`` statements (see -:ref:`sec-logging`). Things get harder when a bug only occurs after a -long time of running, and/or only occasionally. For this type of -problem, a useful tool can be the message stack. An easy way to use -this message stack is to use the `TRACE` macro:: - - { - TRACE("Some message here"); // message pushed - - } // Scope ends, message popped - -This will push the message, then pop the message when the current -scope ends (except when an exception occurs). The error message will -also have the file name and line number appended, to help find where -an error occurred. The run-time overhead of this should be small, but -can be removed entirely if the compile-time flag ``-DCHECK`` is not -defined or set to ``0``. This turns off checking, and ``TRACE`` -becomes an empty macro. It is possible to use standard ``printf`` -like formatting with the trace macro, for example:: - - { - TRACE("The value of i is %d and this is an arbitrary %s", i, "string"); // message pushed - } // Scope ends, message popped - -In the ``mhd.cxx`` example each part of the ``rhs`` function is -trace'd. If an error occurs then at least the equation where it -happened will be printed:: +In the ``mhd.cxx`` example each part of the ``rhs`` function has a +separate ``TRACE`` macro:: { TRACE("ddt(rho)"); ddt(rho) = -V_dot_Grad(v, rho) - rho*Div(v); } +If there's a problem here that causes the model to crash, BOUT++ will +print something like: + +.. code:: text + + ====== Back trace ====== + -> ddt(rho) on line 83 of 'examples/orszag-tang/mhd.cxx' + +For more details on what you can do with ``TRACE`` macros, see +:ref:`sec-debugging`. .. _sec-physicsmodel-boundary-conditions: @@ -1069,7 +1054,7 @@ styles. For example:: output.write("This is an integer: {}, and this a real: {}\n", 5, 2.0) - output << "This is an integer: " << 5 << ", and this a real: " << 2.0 << endl; + output << "This is an integer: " << 5 << ", and this a real: " << 2.0 << '\n'; Formatting in the ``output.write`` function is done using the `{fmt} @@ -1096,7 +1081,7 @@ For finer control over which messages are printed, several outputs are available, listed in the table below. =================== ================================================================= -Name Useage +Name Usage =================== ================================================================= ``output_debug`` For highly verbose output messages, that are normally not needed. Needs to be enabled with a compile switch @@ -1110,20 +1095,20 @@ Name Useage Controlling logging level ~~~~~~~~~~~~~~~~~~~~~~~~~ -By default all of the outputs except ``output_debug`` are saved to log -and printed to console (processor 0 only). +By default all of the outputs (except ``output_debug``) are saved to +log and printed to console (processor 0 only). -To reduce the volume of outputs the command line argument ``-q`` -(quiet) reduces the output level by one, and ``-v`` (verbose) -increases it by one. Running with ``-q`` in the command line arguments -suppresses the ``output_info`` messages, so that they will not appear -in the console or log file. Running with ``-q -q`` suppresses -everything except ``output_warn`` and ``output_error``. +To reduce the volume of outputs the command line argument ``--quiet`` +(``-q`` for short) reduces the output level by one, and ``--verbose`` +(``-v`` for short) increases it by one. Running with ``-q`` in the +command line arguments suppresses the ``output_info`` messages, so +that they will not appear in the console or log file. Running with +``-q -q`` suppresses everything except ``output_warn`` and +``output_error``. To enable the ``output_debug`` messages, configure BOUT++ with a ``CHECK`` level ``>= 3``. To enable it at lower check levels, -configure BOUT++ with ``-DENABLE_OUTPUT_DEBUG`` (for ``CMake``; -``--enable-debug-output`` for ``./configure``)). When running BOUT++ +configure BOUT++ with ``-DBOUT_ENABLE_OUTPUT_DEBUG=ON``. When running BOUT++ add a ``-v -v`` flag to see ``output_debug`` messages. .. _sec-3to4: diff --git a/src/physics/physicsmodel.cxx b/src/physics/physicsmodel.cxx index 9f538895ed..8936982561 100644 --- a/src/physics/physicsmodel.cxx +++ b/src/physics/physicsmodel.cxx @@ -246,10 +246,13 @@ int PhysicsModel::PhysicsModelMonitor::call(Solver* solver, BoutReal simtime, model->output_options["t_array"].assignRepeat(simtime); model->output_options["iteration"].assignRepeat(iteration); + // Call user output monitor + // Note: This may allocate fields that are written to output + auto monitor_result = model->outputMonitor(simtime, iteration, nout); + solver->outputVars(model->output_options, true); model->outputVars(model->output_options); model->writeOutputFile(); - // Call user output monitor - return model->outputMonitor(simtime, iteration, nout); + return monitor_result; } diff --git a/src/sys/options.cxx b/src/sys/options.cxx index e2f39542fd..85ab47a7a7 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -303,38 +303,44 @@ bool Options::isSection(const std::string& name) const { } template <> -void Options::assign<>(Field2D val, std::string source) { +Options& Options::assign<>(Field2D val, std::string source) { attributes["cell_location"] = toString(val.getLocation()); attributes["direction_y"] = toString(val.getDirectionY()); attributes["direction_z"] = toString(val.getDirectionZ()); _set_no_check(std::move(val), std::move(source)); + return *this; } template <> -void Options::assign<>(Field3D val, std::string source) { +Options& Options::assign<>(Field3D val, std::string source) { attributes["cell_location"] = toString(val.getLocation()); attributes["direction_y"] = toString(val.getDirectionY()); attributes["direction_z"] = toString(val.getDirectionZ()); _set_no_check(std::move(val), std::move(source)); + return *this; } template <> -void Options::assign<>(FieldPerp val, std::string source) { +Options& Options::assign<>(FieldPerp val, std::string source) { attributes["cell_location"] = toString(val.getLocation()); attributes["direction_y"] = toString(val.getDirectionY()); attributes["direction_z"] = toString(val.getDirectionZ()); attributes["yindex_global"] = val.getGlobalIndex(); _set_no_check(std::move(val), std::move(source)); + return *this; } template <> -void Options::assign<>(Array val, std::string source) { +Options& Options::assign<>(Array val, std::string source) { _set_no_check(std::move(val), std::move(source)); + return *this; } template <> -void Options::assign<>(Matrix val, std::string source) { +Options& Options::assign<>(Matrix val, std::string source) { _set_no_check(std::move(val), std::move(source)); + return *this; } template <> -void Options::assign<>(Tensor val, std::string source) { +Options& Options::assign<>(Tensor val, std::string source) { _set_no_check(std::move(val), std::move(source)); + return *this; } namespace {