From 2909334416b2df8af63967d8ae687a469299b862 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 23 Mar 2018 11:23:07 +0000 Subject: [PATCH 01/69] AX_LIB_HDF5: fix order of flags When iterating over flags from h5cc, the HDF5_{CPPFLAGS,LDFLAGS,LIBS} variables were assembled in reverse order. This causes problems when linking against static libraries. Fixes #961 --- configure | 20 ++++++++++---------- m4/ax_lib_hdf5.m4 | 10 +++++----- m4/ax_lib_parallelhdf5.m4 | 10 +++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/configure b/configure index c440c3570f..5f8f2cc439 100755 --- a/configure +++ b/configure @@ -7386,18 +7386,18 @@ HDF5 support is being disabled (equivalent to --with-hdf5=no). for arg in $HDF5_SHOW $HDF5_tmp_flags ; do case "$arg" in -I*) echo $HDF5_CPPFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || HDF5_CPPFLAGS="$arg $HDF5_CPPFLAGS" + || HDF5_CPPFLAGS="$HDF5_CPPFLAGS $arg" ;; -L*) echo $HDF5_LDFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || HDF5_LDFLAGS="$arg $HDF5_LDFLAGS" + || HDF5_LDFLAGS="$HDF5_LDFLAGS $arg" ;; -l*) echo $HDF5_LIBS | $GREP -e "$arg" 2>&1 >/dev/null \ - || HDF5_LIBS="$arg $HDF5_LIBS" + || HDF5_LIBS="$HDF5_LIBS $arg" ;; esac done - HDF5_LIBS="$HDF5_LIBS -lhdf5" + HDF5_LIBS="-lhdf5 $HDF5_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $HDF5_VERSION)" >&5 $as_echo "yes (version $HDF5_VERSION)" >&6; } @@ -7500,7 +7500,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf5_hl_main" >&5 $as_echo "$ac_cv_lib_hdf5_hl_main" >&6; } if test "x$ac_cv_lib_hdf5_hl_main" = xyes; then : - HDF5_LIBS="$HDF5_LIBS -lhdf5_hl" + HDF5_LIBS="-lhdf5_hl $HDF5_LIBS" fi ac_cv_lib_hdf5_hl=ac_cv_lib_hdf5_hl_main @@ -7688,18 +7688,18 @@ HDF5 support is being disabled (equivalent to --with-parallelhdf5=no). for arg in $PARALLELHDF5_SHOW $PARALLELHDF5_tmp_flags ; do case "$arg" in -I*) echo $PARALLELHDF5_CPPFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || PARALLELHDF5_CPPFLAGS="$arg $PARALLELHDF5_CPPFLAGS" + || PARALLELHDF5_CPPFLAGS="$PARALLELHDF5_CPPFLAGS $arg" ;; -L*) echo $PARALLELHDF5_LDFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || PARALLELHDF5_LDFLAGS="$arg $PARALLELHDF5_LDFLAGS" + || PARALLELHDF5_LDFLAGS="$PARALLELHDF5_LDFLAGS $arg" ;; -l*) echo $PARALLELHDF5_LIBS | $GREP -e "$arg" 2>&1 >/dev/null \ - || PARALLELHDF5_LIBS="$arg $PARALLELHDF5_LIBS" + || PARALLELHDF5_LIBS="$PARALLELHDF5_LIBS $arg" ;; esac done - PARALLELHDF5_LIBS="$PARALLELHDF5_LIBS -lhdf5" + PARALLELHDF5_LIBS="-lhdf5 $PARALLELHDF5_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $PARALLELHDF5_VERSION)" >&5 $as_echo "yes (version $PARALLELHDF5_VERSION)" >&6; } @@ -7802,7 +7802,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf5_hl_main" >&5 $as_echo "$ac_cv_lib_hdf5_hl_main" >&6; } if test "x$ac_cv_lib_hdf5_hl_main" = xyes; then : - PARALLELHDF5_LIBS="$PARALLELHDF5_LIBS -lhdf5_hl" + PARALLELHDF5_LIBS="-lhdf5_hl $PARALLELHDF5_LIBS" fi ac_cv_lib_hdf5_hl=ac_cv_lib_hdf5_hl_main diff --git a/m4/ax_lib_hdf5.m4 b/m4/ax_lib_hdf5.m4 index a032ed6de2..dacfc6ef66 100644 --- a/m4/ax_lib_hdf5.m4 +++ b/m4/ax_lib_hdf5.m4 @@ -226,18 +226,18 @@ HDF5 support is being disabled (equivalent to --with-hdf5=no). for arg in $HDF5_SHOW $HDF5_tmp_flags ; do case "$arg" in -I*) echo $HDF5_CPPFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || HDF5_CPPFLAGS="$arg $HDF5_CPPFLAGS" + || HDF5_CPPFLAGS="$HDF5_CPPFLAGS $arg" ;; -L*) echo $HDF5_LDFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || HDF5_LDFLAGS="$arg $HDF5_LDFLAGS" + || HDF5_LDFLAGS="$HDF5_LDFLAGS $arg" ;; -l*) echo $HDF5_LIBS | $GREP -e "$arg" 2>&1 >/dev/null \ - || HDF5_LIBS="$arg $HDF5_LIBS" + || HDF5_LIBS="$HDF5_LIBS $arg" ;; esac done - HDF5_LIBS="$HDF5_LIBS -lhdf5" + HDF5_LIBS="-lhdf5 $HDF5_LIBS" AC_MSG_RESULT([yes (version $[HDF5_VERSION])]) dnl See if we can compile @@ -257,7 +257,7 @@ HDF5 support is being disabled (equivalent to --with-hdf5=no). AC_MSG_WARN([Unable to compile HDF5 test program]) fi dnl Look for HDF5's high level library - AC_HAVE_LIBRARY([hdf5_hl], [HDF5_LIBS="$HDF5_LIBS -lhdf5_hl"], [], []) + AC_HAVE_LIBRARY([hdf5_hl], [HDF5_LIBS="-lhdf5_hl $HDF5_LIBS"], [], []) CC=$ax_lib_hdf5_save_CC CPPFLAGS=$ax_lib_hdf5_save_CPPFLAGS diff --git a/m4/ax_lib_parallelhdf5.m4 b/m4/ax_lib_parallelhdf5.m4 index 06500e85b0..a9470aa747 100644 --- a/m4/ax_lib_parallelhdf5.m4 +++ b/m4/ax_lib_parallelhdf5.m4 @@ -194,18 +194,18 @@ HDF5 support is being disabled (equivalent to --with-parallelhdf5=no). for arg in $PARALLELHDF5_SHOW $PARALLELHDF5_tmp_flags ; do case "$arg" in -I*) echo $PARALLELHDF5_CPPFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || PARALLELHDF5_CPPFLAGS="$arg $PARALLELHDF5_CPPFLAGS" + || PARALLELHDF5_CPPFLAGS="$PARALLELHDF5_CPPFLAGS $arg" ;; -L*) echo $PARALLELHDF5_LDFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \ - || PARALLELHDF5_LDFLAGS="$arg $PARALLELHDF5_LDFLAGS" + || PARALLELHDF5_LDFLAGS="$PARALLELHDF5_LDFLAGS $arg" ;; -l*) echo $PARALLELHDF5_LIBS | $GREP -e "$arg" 2>&1 >/dev/null \ - || PARALLELHDF5_LIBS="$arg $PARALLELHDF5_LIBS" + || PARALLELHDF5_LIBS="$PARALLELHDF5_LIBS $arg" ;; esac done - PARALLELHDF5_LIBS="$PARALLELHDF5_LIBS -lhdf5" + PARALLELHDF5_LIBS="-lhdf5 $PARALLELHDF5_LIBS" AC_MSG_RESULT([yes (version $[PARALLELHDF5_VERSION])]) dnl See if we can compile @@ -225,7 +225,7 @@ HDF5 support is being disabled (equivalent to --with-parallelhdf5=no). AC_MSG_WARN([Unable to compile HDF5 test program]) fi dnl Look for HDF5's high level library - AC_HAVE_LIBRARY([hdf5_hl], [PARALLELHDF5_LIBS="$PARALLELHDF5_LIBS -lhdf5_hl"], [], []) + AC_HAVE_LIBRARY([hdf5_hl], [PARALLELHDF5_LIBS="-lhdf5_hl $PARALLELHDF5_LIBS"], [], []) CC=$ax_lib_parallelhdf5_save_CC CPPFLAGS=$ax_lib_parallelhdf5_save_CPPFLAGS From bdd81a170fe5d76b8bd40b6a47b01b53f63c6321 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 3 Oct 2018 11:49:00 +0100 Subject: [PATCH 02/69] Use input field/vector location for CELL_DEFAULT in vecops Now consistently treats CELL_DEFAULT --- src/field/vecops.cxx | 145 ++++++++++++++++++++++++++++--------------- 1 file changed, 96 insertions(+), 49 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 6699ba03ad..c69f50d0fa 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -34,69 +34,85 @@ * Gradient operators **************************************************************************/ -const Vector2D Grad(const Field2D &f, CELL_LOC UNUSED(outloc)) { +const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { Vector2D result(f.getMesh()); TRACE("Grad( Field2D )"); - result.x = DDX(f); - result.y = DDY(f); - result.z = DDZ(f); + if (outloc == CELL_DEFAULT) { + outloc = f.getLocation(); + } + + result.x = DDX(f, outloc); + result.y = DDY(f, outloc); + result.z = DDZ(f, outloc); result.covariant = true; return result; } -const Vector3D Grad(const Field3D &f, - CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z) { +const Vector3D Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z) { Vector3D result(f.getMesh()); TRACE("Grad( Field3D )"); - if(outloc_x == CELL_DEFAULT) + if (outloc_x == CELL_DEFAULT) { outloc_x = f.getLocation(); - if(outloc_y == CELL_DEFAULT) + } + if (outloc_y == CELL_DEFAULT) { outloc_y = f.getLocation(); - if(outloc_z == CELL_DEFAULT) + } + if (outloc_z == CELL_DEFAULT) { outloc_z = f.getLocation(); + } result.x = DDX(f, outloc_x); result.y = DDY(f, outloc_y); result.z = DDZ(f, outloc_z); result.covariant = true; - + return result; } const Vector3D Grad(const Field3D &f, CELL_LOC outloc) { - if(outloc == CELL_VSHIFT) + if (outloc == CELL_VSHIFT) { return Grad(f, CELL_XLOW, CELL_YLOW, CELL_ZLOW); - + } + + if (outloc == CELL_DEFAULT) { + outloc = f.getLocation(); + } + return Grad(f, outloc, outloc, outloc); } -const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, - CELL_LOC UNUSED(outloc_y), CELL_LOC outloc_z) { +const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC UNUSED(outloc_y), + CELL_LOC outloc_z) { Vector3D result(f.getMesh()); TRACE("Grad_perp( Field3D )"); - if(outloc_x == CELL_DEFAULT) + if (outloc_x == CELL_DEFAULT) { outloc_x = f.getLocation(); - if(outloc_z == CELL_DEFAULT) + } + if (outloc_z == CELL_DEFAULT) { outloc_z = f.getLocation(); + } - Coordinates* metric_x = mesh->coordinates(outloc_x); - Coordinates* metric_z = mesh->coordinates(outloc_z); + Coordinates *metric_x = mesh->coordinates(outloc_x); + Coordinates *metric_z = mesh->coordinates(outloc_z); - result.x = DDX(f, outloc_x) - metric_x->g_12*DDY(f, outloc_x) / SQ(metric_x->J * metric_x->Bxy); + result.x = DDX(f, outloc_x) - + metric_x->g_12 * DDY(f, outloc_x) / SQ(metric_x->J * metric_x->Bxy); result.y = 0.0; - result.z = DDZ(f, outloc_z) - metric_z->g_23*DDY(f, outloc_z) / SQ(metric_z->J * metric_z->Bxy); + result.z = DDZ(f, outloc_z) - + metric_z->g_23 * DDY(f, outloc_z) / SQ(metric_z->J * metric_z->Bxy); result.covariant = true; - + return result; } @@ -110,6 +126,10 @@ const Field2D Div(const Vector2D &v, CELL_LOC outloc) { Mesh *localmesh = v.x.getMesh(); Field2D result(localmesh); + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + } + Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v @@ -130,18 +150,19 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { Mesh *localmesh = v.x.getMesh(); Field3D result(localmesh); - Coordinates *metric = localmesh->coordinates(outloc); + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + } - if(outloc == CELL_DEFAULT) - outloc = CELL_CENTRE; + Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v Vector3D vcn = v; vcn.toContravariant(); - - result = DDX(metric->J*vcn.x, outloc); - result += DDY(metric->J*vcn.y, outloc); - result += DDZ(metric->J*vcn.z, outloc); + + result = DDX(metric->J * vcn.x, outloc); + result += DDY(metric->J * vcn.y, outloc); + result += DDZ(metric->J * vcn.z, outloc); result /= metric->J; return result; @@ -158,6 +179,10 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { Mesh *localmesh = f.getMesh(); + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + } + Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v @@ -165,34 +190,36 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { vcn.toContravariant(); Field2D result(localmesh); - result = FDDX(metric->J*vcn.x, f, outloc); - result += FDDY(metric->J*vcn.y, f, outloc); - result += FDDZ(metric->J*vcn.z, f, outloc); + result = FDDX(metric->J * vcn.x, f, outloc); + result += FDDY(metric->J * vcn.y, f, outloc); + result += FDDZ(metric->J * vcn.z, f, outloc); result /= metric->J; - + return result; } -const Field3D Div(const Vector3D &v, const Field3D &f, DIFF_METHOD method, CELL_LOC outloc) { +const Field3D Div(const Vector3D &v, const Field3D &f, DIFF_METHOD method, + CELL_LOC outloc) { TRACE("Div( Vector3D, Field3D )"); Mesh *localmesh = f.getMesh(); Field3D result(localmesh); - Coordinates *metric = localmesh->coordinates(outloc); + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + } - if(outloc == CELL_DEFAULT) - outloc = CELL_CENTRE; + Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v Vector3D vcn = v; vcn.toContravariant(); - - result = FDDX(metric->J*vcn.x, f, outloc, method); - result += FDDY(metric->J*vcn.y, f, outloc, method); - result += FDDZ(metric->J*vcn.z, f, outloc, method); + + result = FDDX(metric->J * vcn.x, f, outloc, method); + result += FDDY(metric->J * vcn.y, f, outloc, method); + result += FDDZ(metric->J * vcn.z, f, outloc, method); result /= metric->J; - + return result; } @@ -213,6 +240,11 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { TRACE("Curl( Vector2D )"); Mesh *localmesh = v.x.getMesh(); + + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + } + Coordinates *metric = localmesh->coordinates(outloc); // Get covariant components of v @@ -221,25 +253,35 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { // get components (curl(v))^j Vector2D result(localmesh); - result.x = (DDY(vco.z, outloc) - DDZ(vco.y, outloc))/metric->J; - result.y = (DDZ(vco.x, outloc) - DDX(vco.z, outloc))/metric->J; - result.z = (DDX(vco.y, outloc) - DDY(vco.x, outloc))/metric->J; + result.x = (DDY(vco.z, outloc) - DDZ(vco.y, outloc)) / metric->J; + result.y = (DDZ(vco.x, outloc) - DDX(vco.z, outloc)) / metric->J; + result.z = (DDX(vco.y, outloc) - DDY(vco.x, outloc)) / metric->J; /// Coordinate torsion - result.z -= metric->ShiftTorsion*vco.z / metric->J; + result.z -= metric->ShiftTorsion * vco.z / metric->J; result.covariant = false; // result is contravariant return result; } -const Vector3D Curl(const Vector3D &v, - CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z) { +const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z) { TRACE("Curl( Vector3D )"); Mesh *localmesh = v.x.getMesh(); + if (outloc_x == CELL_DEFAULT) { + outloc_x = v.getLocation(); + } + if (outloc_y == CELL_DEFAULT) { + outloc_y = v.getLocation(); + } + if (outloc_z == CELL_DEFAULT) { + outloc_z = v.getLocation(); + } + Coordinates* metric_z = localmesh->coordinates(outloc_z); // Get covariant components of v @@ -261,9 +303,14 @@ const Vector3D Curl(const Vector3D &v, } const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { - if(outloc == CELL_VSHIFT) + if (outloc == CELL_VSHIFT) { return Curl(v, CELL_XLOW, CELL_YLOW, CELL_ZLOW); - + } + + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + } + return Curl(v, outloc, outloc, outloc); } From a9fcbf92e9b8d61b4db676d20d743aeacdb80349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 8 Oct 2018 23:47:58 +0100 Subject: [PATCH 03/69] add simple test for squashoutput --- tests/integrated/test-squash/.gitignore | 2 + tests/integrated/test-squash/data/BOUT.inp | 21 ++++++++ tests/integrated/test-squash/makefile | 6 +++ tests/integrated/test-squash/runtest | 63 ++++++++++++++++++++++ tests/integrated/test-squash/squash.cxx | 30 +++++++++++ 5 files changed, 122 insertions(+) create mode 100644 tests/integrated/test-squash/.gitignore create mode 100644 tests/integrated/test-squash/data/BOUT.inp create mode 100644 tests/integrated/test-squash/makefile create mode 100755 tests/integrated/test-squash/runtest create mode 100644 tests/integrated/test-squash/squash.cxx diff --git a/tests/integrated/test-squash/.gitignore b/tests/integrated/test-squash/.gitignore new file mode 100644 index 0000000000..a12058acc2 --- /dev/null +++ b/tests/integrated/test-squash/.gitignore @@ -0,0 +1,2 @@ +*.nc +squash \ No newline at end of file diff --git a/tests/integrated/test-squash/data/BOUT.inp b/tests/integrated/test-squash/data/BOUT.inp new file mode 100644 index 0000000000..b9d7a3a236 --- /dev/null +++ b/tests/integrated/test-squash/data/BOUT.inp @@ -0,0 +1,21 @@ +timestep = 1. +nout = 10 + +MZ = 1 + +[mesh] + +nx = 12 +ny = 8 + +dx = 1. +dy = 1. + +[solver] + +[f2] +scale = 1. +function = 0. + +[f3] +function = 0. \ No newline at end of file diff --git a/tests/integrated/test-squash/makefile b/tests/integrated/test-squash/makefile new file mode 100644 index 0000000000..cecff798ec --- /dev/null +++ b/tests/integrated/test-squash/makefile @@ -0,0 +1,6 @@ + +BOUT_TOP = ../../.. + +SOURCEC = squash.cxx + +include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest new file mode 100755 index 0000000000..72834ee3b5 --- /dev/null +++ b/tests/integrated/test-squash/runtest @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 + +import netCDF4 as nc +import itertools as it +import os + + +def run(cmd): + s = os.system(cmd) + if s: + raise RuntimeError("%s exited with non-zero %d value" % (cmd, s)) + + +def verify(f1, f2): + org = nc.Dataset(f1) + para = nc.Dataset(f2) + for v in org.variables: + if org[v].shape != para[v].shape: + print(org[v]) + print(para[v]) + raise RuntimeError("shape mismatch in ", v) + if v in ["MXSUB","MYSUB","NXPE","NYPE","iteration"]: + continue + if (org[v][:] != para[v][:]).any(): + a=org[v] + b=para[v] + print(a) + print(b) + lst=[range(x) for x in org[v].shape] + for i in it.product(*lst): + if a[i] != b[i]: + print(i,":",a[i],"!=",b[i]) + # There are differences, but I think only guard cells are affected + raise RuntimeError("data mismatch in ", v) + +run("make") + +# Run once to get normal data +run("./squash -q -q -q nout=20") +run("mv data/BOUT.dmp.0.nc 20.nc") + +# Parallel test +run("rm -f para.nc") +run("mpirun -np 4 ./squash -q -q -q nout=20") +run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../para.nc") + +verify("20.nc", "para.nc") + +# Parallel and in two pieces +run("rm -f para.nc") +run("mpirun -np 4 ./squash -q -q -q") +run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../para.nc") +run("mpirun -np 4 ./squash -q -q -q restart") +run("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../para.nc") + +verify("20.nc", "para.nc") + +# Sequential test +run("rm -f seq.nc") +run("./squash -q -q -q nout=20") +run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../seq.nc") + +verify("20.nc", "seq.nc") diff --git a/tests/integrated/test-squash/squash.cxx b/tests/integrated/test-squash/squash.cxx new file mode 100644 index 0000000000..98528ba860 --- /dev/null +++ b/tests/integrated/test-squash/squash.cxx @@ -0,0 +1,30 @@ +/* + */ + +#include + +class SquashRun : public PhysicsModel { +protected: + // Initialisation + int init(bool restarting) { + solver->add(f2, "f2"); + solver->add(f3, "f3"); + return 0; + } + + // Calculate time-derivatives + int rhs(BoutReal t) { + ddt(f2) = 1; + ddt(f3) = -1; + f2.applyBoundary(); + f3.applyBoundary(); + return 0; + } + +private: + Field2D f2; + Field3D f3; +}; + +// Create a default main() +BOUTMAIN(SquashRun); From f7d5117c86df135df9dd744b9038525d64d179e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 8 Oct 2018 23:50:54 +0100 Subject: [PATCH 04/69] Fix append mode If the simulation is restarted (`restart`), and the old dump files have already been squashed, dump on restart is enabled by default. This patch checks whether the two times are the same, and if so, does not duplicate that time slice. --- tools/pylib/boutdata/squashoutput.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/pylib/boutdata/squashoutput.py b/tools/pylib/boutdata/squashoutput.py index 0c8ac48029..2b063f7c88 100644 --- a/tools/pylib/boutdata/squashoutput.py +++ b/tools/pylib/boutdata/squashoutput.py @@ -113,6 +113,15 @@ def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=N kwargs['complevel']=complevel if append: old=DataFile(oldfile) + # Check if dump on restart was enabled + # If so, we want to drop the duplicated entry + cropnew=0 + if old['t_array'][-1] == outputs['t_array'][0]: + cropnew=1 + # Make sure we don't end up with duplicated data: + for ot in old['t_array']: + if ot in outputs['t_array'][cropnew:]: + raise RuntimeError("For some reason t_array has some duplicated entries in the new and old file.") # Create single file for output and write data with DataFile(fullpath,create=True,write=True,format=format, **kwargs) as f: for varname in outputvars: @@ -123,6 +132,7 @@ def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=N if append: dims=old.dimensions(varname) if 't' in dims: + var=var[cropnew:,...] varold=old[varname] var=BoutArray(numpy.append(varold,var,axis=0),var.attributes) From de6ffadbbef712689387eefcf205d58160e837d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 8 Oct 2018 23:51:54 +0100 Subject: [PATCH 05/69] Fix for Field2D For some reason the time index is called `x2` - and thus this condition is not matched. This fixes this, as the newly created output should be more reliable in this regard. --- tools/pylib/boutdata/squashoutput.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/boutdata/squashoutput.py b/tools/pylib/boutdata/squashoutput.py index 2b063f7c88..10a90f0a8d 100644 --- a/tools/pylib/boutdata/squashoutput.py +++ b/tools/pylib/boutdata/squashoutput.py @@ -130,7 +130,7 @@ def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=N var = outputs[varname] if append: - dims=old.dimensions(varname) + dims=outputs.dimensions[varname] if 't' in dims: var=var[cropnew:,...] varold=old[varname] From 25cfad4418d949f1342e877528ecca478481546a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 8 Oct 2018 23:53:59 +0100 Subject: [PATCH 06/69] Fix: glob not correctly imported `glob` was previously not correctly imported, if append mode was disabled, but delete was enabled. --- tools/pylib/boutdata/squashoutput.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/pylib/boutdata/squashoutput.py b/tools/pylib/boutdata/squashoutput.py index 10a90f0a8d..e7c7639b42 100644 --- a/tools/pylib/boutdata/squashoutput.py +++ b/tools/pylib/boutdata/squashoutput.py @@ -20,6 +20,10 @@ from boututils.boutarray import BoutArray import numpy import os +import gc +import tempfile +import shutil +import glob def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=None, xind=None, yind=None, zind=None, singleprecision=False, compress=False, @@ -72,14 +76,9 @@ def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=N Delete the original files after squashing. """ - import gc - fullpath = os.path.join(datadir,outputname) if append: - import tempfile - import shutil - import glob datadirnew = tempfile.mkdtemp(dir=datadir) for f in glob.glob(datadir+"/BOUT.dmp.*.??"): if not quiet: From 5006006fc0dcd81b3e681a399c2c40768d3322d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 8 Oct 2018 23:56:41 +0100 Subject: [PATCH 07/69] add dump_on_restart=false sub test --- tests/integrated/test-squash/runtest | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index 72834ee3b5..62fbcabcf2 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -55,6 +55,15 @@ run("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../para.nc") verify("20.nc", "para.nc") +# Parallel and in two pieces without dump_on_restart +run("rm -f para.nc") +run("mpirun -np 4 ./squash -q -q -q") +run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../para.nc") +run("mpirun -np 4 ./squash -q -q -q restart dump_on_restart=false") +run("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../para.nc") + +verify("20.nc", "para.nc") + # Sequential test run("rm -f seq.nc") run("./squash -q -q -q nout=20") From a5553912608fee2e2b5f6665edcdf213bc511846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 8 Oct 2018 23:57:12 +0100 Subject: [PATCH 08/69] Fix formatting --- bin/bout-squashoutput | 31 +++++++++------- tests/integrated/test-squash/runtest | 10 ++--- tools/pylib/boutdata/squashoutput.py | 55 +++++++++++++++------------- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/bin/bout-squashoutput b/bin/bout-squashoutput index cfc6154710..cd3ccf5f92 100755 --- a/bin/bout-squashoutput +++ b/bin/bout-squashoutput @@ -9,37 +9,42 @@ from sys import exit try: import argcomplete except ImportError: - argcomplete=None + argcomplete = None import boutdata.squashoutput as squash # Parse command line arguments -parser = argparse.ArgumentParser(squash.__doc__+"\n\n"+squash.squashoutput.__doc__) +parser = argparse.ArgumentParser( + squash.__doc__ + "\n\n" + squash.squashoutput.__doc__) + def str_to_bool(string): - return string.lower()=="true" or string.lower()=="t" + return string.lower() == "true" or string.lower() == "t" + def int_or_none(string): try: return int(string) except ValueError: - if string.lower()=='none' or string.lower()=='n': + if string.lower() == 'none' or string.lower() == 'n': return None else: raise parser.add_argument("datadir", nargs='?', default=".") -parser.add_argument("--outputname",default="BOUT.dmp.nc") +parser.add_argument("--outputname", default="BOUT.dmp.nc") parser.add_argument("--tind", type=int_or_none, nargs='*', default=[None]) parser.add_argument("--xind", type=int_or_none, nargs='*', default=[None]) parser.add_argument("--yind", type=int_or_none, nargs='*', default=[None]) parser.add_argument("--zind", type=int_or_none, nargs='*', default=[None]) -parser.add_argument("-s","--singleprecision", action="store_true", default=False) -parser.add_argument("-c","--compress", action="store_true", default=False) -parser.add_argument("-l","--complevel", type=int_or_none, default=None) -parser.add_argument("-i","--least-significant-digit", type=int_or_none, default=None) -parser.add_argument("-q","--quiet", action="store_true", default=False) -parser.add_argument("-a","--append", action="store_true", default=False) -parser.add_argument("-d","--delete", action="store_true", default=False) +parser.add_argument("-s", "--singleprecision", + action="store_true", default=False) +parser.add_argument("-c", "--compress", action="store_true", default=False) +parser.add_argument("-l", "--complevel", type=int_or_none, default=None) +parser.add_argument("-i", "--least-significant-digit", + type=int_or_none, default=None) +parser.add_argument("-q", "--quiet", action="store_true", default=False) +parser.add_argument("-a", "--append", action="store_true", default=False) +parser.add_argument("-d", "--delete", action="store_true", default=False) if argcomplete: argcomplete.autocomplete(parser) @@ -49,7 +54,7 @@ args = parser.parse_args() # Late imports to not slow down bash completion for ind in "txyz": - args.__dict__[ind+"ind"]=slice(*args.__dict__[ind+"ind"]) + args.__dict__[ind + "ind"] = slice(*args.__dict__[ind + "ind"]) # Call the function, using command line arguments squash.squashoutput(**args.__dict__) diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index 62fbcabcf2..7b34ea5316 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -19,17 +19,17 @@ def verify(f1, f2): print(org[v]) print(para[v]) raise RuntimeError("shape mismatch in ", v) - if v in ["MXSUB","MYSUB","NXPE","NYPE","iteration"]: + if v in ["MXSUB", "MYSUB", "NXPE", "NYPE", "iteration"]: continue if (org[v][:] != para[v][:]).any(): - a=org[v] - b=para[v] + a = org[v] + b = para[v] print(a) print(b) - lst=[range(x) for x in org[v].shape] + lst = [range(x) for x in org[v].shape] for i in it.product(*lst): if a[i] != b[i]: - print(i,":",a[i],"!=",b[i]) + print(i, ":", a[i], "!=", b[i]) # There are differences, but I think only guard cells are affected raise RuntimeError("data mismatch in ", v) diff --git a/tools/pylib/boutdata/squashoutput.py b/tools/pylib/boutdata/squashoutput.py index e7c7639b42..52bcaa40d1 100644 --- a/tools/pylib/boutdata/squashoutput.py +++ b/tools/pylib/boutdata/squashoutput.py @@ -25,6 +25,7 @@ import shutil import glob + def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=None, xind=None, yind=None, zind=None, singleprecision=False, compress=False, least_significant_digit=None, quiet=False, complevel=None, append=False, @@ -76,64 +77,68 @@ def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=N Delete the original files after squashing. """ - fullpath = os.path.join(datadir,outputname) + fullpath = os.path.join(datadir, outputname) if append: datadirnew = tempfile.mkdtemp(dir=datadir) - for f in glob.glob(datadir+"/BOUT.dmp.*.??"): + for f in glob.glob(datadir + "/BOUT.dmp.*.??"): if not quiet: - print("moving",f) - shutil.move(f,datadirnew) - oldfile=datadirnew+"/"+outputname - datadir=datadirnew + print("moving", f) + shutil.move(f, datadirnew) + oldfile = datadirnew + "/" + outputname + datadir = datadirnew if os.path.isfile(fullpath) and not append: - raise ValueError(fullpath+" already exists. Collect may try to read from this file, which is presumably not desired behaviour.") + raise ValueError( + fullpath + " already exists. Collect may try to read from this file, which is presumably not desired behaviour.") # useful object from BOUT pylib to access output data - outputs = BoutOutputs(datadir, info=False, xguards=True, yguards=True, tind=tind, xind=xind, yind=yind, zind=zind) + outputs = BoutOutputs(datadir, info=False, xguards=True, + yguards=True, tind=tind, xind=xind, yind=yind, zind=zind) outputvars = outputs.keys() # Read a value to cache the files outputs[outputvars[0]] if append: # move only after the file list is cached - shutil.move(fullpath,oldfile) + shutil.move(fullpath, oldfile) t_array_index = outputvars.index("t_array") outputvars.append(outputvars.pop(t_array_index)) - kwargs={} + kwargs = {} if compress: - kwargs['zlib']=True + kwargs['zlib'] = True if least_significant_digit is not None: - kwargs['least_significant_digit']=least_significant_digit + kwargs['least_significant_digit'] = least_significant_digit if complevel is not None: - kwargs['complevel']=complevel + kwargs['complevel'] = complevel if append: - old=DataFile(oldfile) + old = DataFile(oldfile) # Check if dump on restart was enabled # If so, we want to drop the duplicated entry - cropnew=0 + cropnew = 0 if old['t_array'][-1] == outputs['t_array'][0]: - cropnew=1 + cropnew = 1 # Make sure we don't end up with duplicated data: for ot in old['t_array']: if ot in outputs['t_array'][cropnew:]: - raise RuntimeError("For some reason t_array has some duplicated entries in the new and old file.") + raise RuntimeError( + "For some reason t_array has some duplicated entries in the new and old file.") # Create single file for output and write data - with DataFile(fullpath,create=True,write=True,format=format, **kwargs) as f: + with DataFile(fullpath, create=True, write=True, format=format, **kwargs) as f: for varname in outputvars: if not quiet: print(varname) var = outputs[varname] if append: - dims=outputs.dimensions[varname] + dims = outputs.dimensions[varname] if 't' in dims: - var=var[cropnew:,...] - varold=old[varname] - var=BoutArray(numpy.append(varold,var,axis=0),var.attributes) + var = var[cropnew:, ...] + varold = old[varname] + var = BoutArray(numpy.append( + varold, var, axis=0), var.attributes) if singleprecision: if not isinstance(var, int): @@ -142,15 +147,15 @@ def squashoutput(datadir=".", outputname="BOUT.dmp.nc", format="NETCDF4", tind=N f.write(varname, var) # Write changes, free memory f.sync() - var=None + var = None gc.collect() if delete: if append: os.remove(oldfile) - for f in glob.glob(datadir+"/BOUT.dmp.*.??"): + for f in glob.glob(datadir + "/BOUT.dmp.*.??"): if not quiet: - print("Deleting",f) + print("Deleting", f) os.remove(f) if append: os.rmdir(datadir) From 291b9f65822230883ab336f9718edc9d94957d75 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 9 Oct 2018 14:50:38 +0100 Subject: [PATCH 09/69] Ensure CELL_DEFAULT and CELL_VSHIFT are forbidden in calls to coordinates. Replaces throw with ASSERT --- include/bout/mesh.hxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index f3682c9dbd..796805bf5f 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -431,10 +431,11 @@ class Mesh { /// Coordinate system Coordinates *coordinates(const CELL_LOC location = CELL_CENTRE) { + ASSERT1(location != CELL_DEFAULT); + ASSERT1(location != CELL_VSHIFT); + if (coords_map.count(location)) { // True branch most common, returns immediately return coords_map[location].get(); - } else if (location == CELL_DEFAULT) { - throw BoutException("Ambiguous location 'CELL_DEFAULT' passed to mesh::coordinates"); } else { // No coordinate system set. Create default // Note that this can't be allocated here due to incomplete type From f02880bb641a9f55df2e366f301346798ef986af Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 3 Oct 2018 15:52:52 +0100 Subject: [PATCH 10/69] Bump version number to 4.2.0 --- CITATION.cff | 6 +++--- configure | 22 +++++++++++----------- configure.ac | 2 +- manual/doxygen/Doxyfile | 2 +- manual/doxygen/Doxyfile_readthedocs | 2 +- manual/sphinx/conf.py | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 345fd55d06..ab96c9484b 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -139,11 +139,11 @@ authors: - family-names: Wang given-names: Zhanhui -version: 4.1.2 -date-released: 2017-12-01 +version: 4.2.0 +date-released: TBC repository-code: https://github.com/boutproject/BOUT-dev url: http://boutproject.github.io/ -doi: 10.5281/zenodo.1423213 +doi: TBC license: 'LGPL-3.0-or-later' references: - type: article diff --git a/configure b/configure index 81ee0d7f7a..dba763cd86 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for BOUT++ 4.1.2. +# Generated by GNU Autoconf 2.69 for BOUT++ 4.2.0. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='BOUT++' PACKAGE_TARNAME='bout--' -PACKAGE_VERSION='4.1.2' -PACKAGE_STRING='BOUT++ 4.1.2' +PACKAGE_VERSION='4.2.0' +PACKAGE_STRING='BOUT++ 4.2.0' PACKAGE_BUGREPORT='bd512@york.ac.uk' PACKAGE_URL='' @@ -1359,7 +1359,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures BOUT++ 4.1.2 to adapt to many kinds of systems. +\`configure' configures BOUT++ 4.2.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1421,7 +1421,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of BOUT++ 4.1.2:";; + short | recursive ) echo "Configuration of BOUT++ 4.2.0:";; esac cat <<\_ACEOF @@ -1550,7 +1550,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -BOUT++ configure 4.1.2 +BOUT++ configure 4.2.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2131,7 +2131,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by BOUT++ $as_me 4.1.2, which was +It was created by BOUT++ $as_me 4.2.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12705,7 +12705,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by BOUT++ $as_me 4.1.2, which was +This file was extended by BOUT++ $as_me 4.2.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12758,7 +12758,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -BOUT++ config.status 4.1.2 +BOUT++ config.status 4.2.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -13933,7 +13933,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by BOUT++ $as_me 4.1.2, which was +This file was extended by BOUT++ $as_me 4.2.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13986,7 +13986,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -BOUT++ config.status 4.1.2 +BOUT++ config.status 4.2.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 7cd03e2948..21dd288bbc 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ # AC_PREREQ([2.69]) -AC_INIT([BOUT++],[4.1.2],[bd512@york.ac.uk]) +AC_INIT([BOUT++],[4.2.0],[bd512@york.ac.uk]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/manual/doxygen/Doxyfile b/manual/doxygen/Doxyfile index d7067d0171..3271607d7a 100644 --- a/manual/doxygen/Doxyfile +++ b/manual/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = BOUT++ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.1.2 +PROJECT_NUMBER = 4.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/manual/doxygen/Doxyfile_readthedocs b/manual/doxygen/Doxyfile_readthedocs index 4249ec2ebd..7f3dfd8a94 100644 --- a/manual/doxygen/Doxyfile_readthedocs +++ b/manual/doxygen/Doxyfile_readthedocs @@ -38,7 +38,7 @@ PROJECT_NAME = BOUT++ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.1.2 +PROJECT_NUMBER = 4.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/manual/sphinx/conf.py b/manual/sphinx/conf.py index 5e514e3283..9c39c2ac27 100755 --- a/manual/sphinx/conf.py +++ b/manual/sphinx/conf.py @@ -131,9 +131,9 @@ def __getattr__(cls, name): # built documents. # # The short X.Y version. -version = '4.1' +version = '4.2' # The full version, including alpha/beta/rc tags. -release = '4.1.2' +release = '4.2.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 8d6844307af361e562839359d9f0cbd44e9d1c7e Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 3 Oct 2018 16:05:22 +0100 Subject: [PATCH 11/69] Include caveats on OpenMP parallelisation in documentation --- manual/sphinx/user_docs/advanced_install.rst | 29 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index ee6e80ecde..bf97738e56 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -53,7 +53,7 @@ control over how BOUT++ is built: - ``SUNDIALS_EXTRA_LIBS`` specifies additional libraries for linking to SUNDIALS, which are put at the end of the link command. - + It is possible to change flags for BOUT++ after running configure, by editing the ``make.config`` file. Note that this is not recommended, as e.g. PVODE will not be built with these flags. @@ -258,12 +258,27 @@ appropriately. OpenMP ------ -BOUT++ can make use of Single-Instruction Multiple-Data (SIMD) -parallelism through OpenMP. To enable OpenMP, use the +BOUT++ can make use of OpenMP parallelism. To enable OpenMP, use the ``--enable-openmp`` flag to configure:: ./configure --enable-openmp +OpenMP can be used to parallelise in more directions than can be +achieved with MPI alone. For example, it is currently difficult to +parallelise over the X, Z plane using pure MPI if FCI is used. + +OpenMP is in a large number of places now, such that a decent speed-up +can be achieved with OpenMP alone. Hybrid parallelisation with both +MPI and OpenMP can lead to more significant speed-ups, but it +sometimes requires some fine tuning of numerical parameters in order +to achieve this. This greatly depends on the details not just of your +system, but also your particular problem. We have tried to choose +"sensible" defaults that will work well for the most common cases, but +this is not always possible. You may need to perform some testing +yourself to find e.g. the optimum split of OpenMP threads and MPI +ranks. + + .. note:: If you want to use OpenMP with Clang, you will need Clang 3.7+, and either ``libomp`` or ``libiomp``. @@ -277,6 +292,14 @@ parallelism through OpenMP. To enable OpenMP, use the By default PVODE is built without OpenMP support. To enable this add ``--enable-pvode-openmp`` to the configure command. + +.. note:: + OpenMP will attempt to use all available threads by default. This + can cause oversubscription problems on certain systems. You can + limit the number of threads OpenMP uses with the + ``OMP_NUM_THREADS`` environment variable. See your system + documentation for more details. + .. _sec-sundials: SUNDIALS From e9e00088f635e4c33e05e8172f7d21e33d0caeff Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 May 2018 21:40:25 +0100 Subject: [PATCH 12/69] Remove mixed field-aligned/non-field-aligned derivatives Advective and flux derivatives, which take v and f as inputs, had cases using yup/ydown fields for one of v and f, but not the other. These do not make sense as multiplication of a field in field-aligned coordinates with another in non-field-aligned coordinates is incorrect. Delete last of these cases and fall back to converting both v and f to field-aligned if either does not have yup/ydown fields. Also add some comments where mixed cases were removed before. --- src/mesh/difops.cxx | 57 ++++----------------------------------- src/mesh/index_derivs.cxx | 22 +++++++-------- 2 files changed, 15 insertions(+), 64 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 58625c77d6..0199d991a7 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -342,60 +342,13 @@ const Field3D Vpar_Grad_par_LCtoC(const Field3D &v, const Field3D &f, REGION reg } } } - else if (vUseUpDown) { - // Only v has up/down fields - // f must shift to field aligned coordinates - Field3D f_fa = vMesh->toFieldAligned(f); - - BOUT_OMP(parallel) { - stencil fval, vval; - BOUT_FOR_INNER(i, vMesh->getRegion3D(region_str)) { - fval.mm = f_fa[i.ymm()]; - fval.m = f_fa[i.ym()]; - fval.c = f_fa[i]; - fval.p = f_fa[i.yp()]; - fval.pp = f_fa[i.ypp()]; - - vval.m = v.ydown()[i.ym()]; - vval.c = v[i]; - vval.p = v.yup()[i.yp()]; - - // Left side - result[i] = (vval.c >= 0.0) ? vval.c * fval.m : vval.c * fval.c; - // Right side - result[i] -= (vval.p >= 0.0) ? vval.p * fval.c : vval.p * fval.p; - } - } - } - else if (fUseUpDown) { - // Only f has up/down fields - // v must shift to field aligned coordinates - Field3D v_fa = vMesh->toFieldAligned(v); - - BOUT_OMP(parallel) { - stencil fval, vval; - BOUT_FOR_INNER(i, vMesh->getRegion3D(region_str)) { - fval.m = f.ydown()[i.ym()]; - fval.c = f[i]; - fval.p = f.yup()[i.yp()]; - - vval.mm = v_fa[i.ymm()]; - vval.m = v_fa[i.ym()]; - vval.c = v_fa[i]; - vval.p = v_fa[i.yp()]; - vval.pp = v_fa[i.ypp()]; - - // Left side - result[i] = (vval.c >= 0.0) ? vval.c * fval.m : vval.c * fval.c; - // Right side - result[i] -= (vval.p >= 0.0) ? vval.p * fval.c : vval.p * fval.p; - } - } - } else { // Both must shift to field aligned - Field3D v_fa = vMesh->toFieldAligned(v); - Field3D f_fa = vMesh->toFieldAligned(f); + // (even if one of v and f has yup/ydown fields, it doesn't make sense to + // multiply them with one in field-aligned and one in non-field-aligned + // coordinates) + Field3D v_fa = mesh->toFieldAligned(v); + Field3D f_fa = mesh->toFieldAligned(f); BOUT_OMP(parallel) { stencil fval, vval; diff --git a/src/mesh/index_derivs.cxx b/src/mesh/index_derivs.cxx index d872b70ab4..56db9871eb 100644 --- a/src/mesh/index_derivs.cxx +++ b/src/mesh/index_derivs.cxx @@ -2158,12 +2158,8 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo func = lookupFunc(table, method); } - // There are four cases, corresponding to whether or not f and v - // have yup, ydown fields. - - // If vUseUpDown is true, field "v" has distinct yup and ydown fields which - // will be used to calculate a derivative along - // the magnetic field + // If *UseUpDown is true, field "*" has distinct yup and ydown fields which + // will be used to calculate a derivative along the magnetic field bool vUseUpDown = (v.hasYupYdown() && ((&v.yup() != &v) || (&v.ydown() != &v))); bool fUseUpDown = (f.hasYupYdown() && ((&f.yup() != &f) || (&f.ydown() != &f))); @@ -2195,6 +2191,9 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo } } else { // Both must shift to field aligned + // (even if one of v and f has yup/ydown fields, it doesn't make sense to + // multiply them with one in field-aligned and one in non-field-aligned + // coordinates) Field3D v_fa = this->toFieldAligned(v); Field3D f_fa = this->toFieldAligned(f); BOUT_OMP(parallel) { @@ -2788,12 +2787,8 @@ const Field3D Mesh::indexFDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated - // There are four cases, corresponding to whether or not f and v - // have yup, ydown fields. - - // If vUseUpDown is true, field "v" has distinct yup and ydown fields which - // will be used to calculate a derivative along - // the magnetic field + // If *UseUpDown is true, field "*" has distinct yup and ydown fields which + // will be used to calculate a derivative along the magnetic field bool vUseUpDown = (v.hasYupYdown() && ((&v.yup() != &v) || (&v.ydown() != &v))); bool fUseUpDown = (f.hasYupYdown() && ((&f.yup() != &f) || (&f.ydown() != &f))); @@ -2830,6 +2825,9 @@ const Field3D Mesh::indexFDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo } } else { // Both must shift to field aligned + // (even if one of v and f has yup/ydown fields, it doesn't make sense to + // multiply them with one in field-aligned and one in non-field-aligned + // coordinates) Field3D v_fa = this->toFieldAligned(v); Field3D f_fa = this->toFieldAligned(f); BOUT_OMP(parallel) { From 90648ba8a4d7cafb248807f81300df8c9fa3e081 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 May 2018 21:31:39 +0100 Subject: [PATCH 13/69] Add missing fromFieldAligned calls In several y-derivatives where we have to convert the input to field-aligned coordinates, the result was not transformed back to the original coordinates. Also remove uses of global 'mesh' in Vpar_Grad_par_LCtoC() --- src/mesh/difops.cxx | 6 ++++-- src/mesh/index_derivs.cxx | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 0199d991a7..8b8ff649ce 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -347,8 +347,8 @@ const Field3D Vpar_Grad_par_LCtoC(const Field3D &v, const Field3D &f, REGION reg // (even if one of v and f has yup/ydown fields, it doesn't make sense to // multiply them with one in field-aligned and one in non-field-aligned // coordinates) - Field3D v_fa = mesh->toFieldAligned(v); - Field3D f_fa = mesh->toFieldAligned(f); + Field3D v_fa = vMesh->toFieldAligned(v); + Field3D f_fa = vMesh->toFieldAligned(f); BOUT_OMP(parallel) { stencil fval, vval; @@ -366,6 +366,8 @@ const Field3D Vpar_Grad_par_LCtoC(const Field3D &v, const Field3D &f, REGION reg // Right side result[i] -= (vval.p >= 0.0) ? vval.p * fval.c : vval.p * fval.p; } + + result = vMesh->fromFieldAligned(result); } } diff --git a/src/mesh/index_derivs.cxx b/src/mesh/index_derivs.cxx index 56db9871eb..886788ab3d 100644 --- a/src/mesh/index_derivs.cxx +++ b/src/mesh/index_derivs.cxx @@ -2224,6 +2224,8 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo result[i] = func(vval, fval); } } + + result = this->fromFieldAligned(result); } } else { // Non-staggered case @@ -2860,6 +2862,8 @@ const Field3D Mesh::indexFDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo result[i] = func(vval, fval); } } + + result = this->fromFieldAligned(result); } result.setLocation(outloc); From 54494d4cfcfb99f17b66963df80967da9b2285a2 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 3 Jul 2018 09:58:48 +0100 Subject: [PATCH 14/69] Fix f->f_fa Was previously a typo that resulted in using non-field-aligned f in VDDY, which is incorrect. --- src/mesh/index_derivs.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/index_derivs.cxx b/src/mesh/index_derivs.cxx index 886788ab3d..c05991520d 100644 --- a/src/mesh/index_derivs.cxx +++ b/src/mesh/index_derivs.cxx @@ -2207,7 +2207,7 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo fval.mm = f_fa[i.ymm()]; fval.m = f_fa[i.ym()]; - fval.c = f[i]; + fval.c = f_fa[i]; fval.p = f_fa[i.yp()]; fval.pp = f_fa[i.ypp()]; From 1342d874cbc3b00e6fd6fb64c1899d1ecb436a5c Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 3 Jul 2018 12:16:41 +0100 Subject: [PATCH 15/69] Set location of result as soon as it is declared in index_derivs.cxx The location of the result will in future need to be set before shifting it from field-aligned coordinates, if this is necessary. So it is safer to set the location to outloc as soon as 'Field3D result' is declared. Also in a couple of places just 'return apply*diff(...)' instead of creating an unneeded intermediate variable 'result'. --- src/mesh/index_derivs.cxx | 70 +++++++++++---------------------------- 1 file changed, 20 insertions(+), 50 deletions(-) diff --git a/src/mesh/index_derivs.cxx b/src/mesh/index_derivs.cxx index c05991520d..f684cce292 100644 --- a/src/mesh/index_derivs.cxx +++ b/src/mesh/index_derivs.cxx @@ -662,6 +662,7 @@ const Field2D Mesh::applyXdiff(const Field2D &var, Mesh::deriv_func func, Field2D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (this->StaggerGrids && (outloc != inloc)) { // Staggered differencing @@ -752,8 +753,6 @@ const Field2D Mesh::applyXdiff(const Field2D &var, Mesh::deriv_func func, } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -787,6 +786,7 @@ const Field3D Mesh::applyXdiff(const Field3D &var, Mesh::deriv_func func, Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (this->StaggerGrids && (outloc != inloc)) { // Staggered differencing @@ -877,8 +877,6 @@ const Field3D Mesh::applyXdiff(const Field3D &var, Mesh::deriv_func func, } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -912,6 +910,7 @@ const Field2D Mesh::applyYdiff(const Field2D &var, Mesh::deriv_func func, CELL_L Field2D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (this->ystart > 1) { // More than one guard cell, so set pp and mm values @@ -943,8 +942,6 @@ const Field2D Mesh::applyYdiff(const Field2D &var, Mesh::deriv_func func, CELL_L } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_yup = result.bndry_ydown = false; @@ -977,6 +974,7 @@ const Field3D Mesh::applyYdiff(const Field3D &var, Mesh::deriv_func func, CELL_L Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (var.hasYupYdown() && ((&var.yup() != &var) || (&var.ydown() != &var))) { // Field "var" has distinct yup and ydown fields which @@ -1122,8 +1120,6 @@ const Field3D Mesh::applyYdiff(const Field3D &var, Mesh::deriv_func func, CELL_L result = this->fromFieldAligned(result); } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -1156,6 +1152,7 @@ const Field3D Mesh::applyZdiff(const Field3D &var, Mesh::deriv_func func, CELL_L Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); // Check that the input variable has data ASSERT1(var.isAllocated()); @@ -1174,8 +1171,6 @@ const Field3D Mesh::applyZdiff(const Field3D &var, Mesh::deriv_func func, CELL_L } } - result.setLocation(outloc); - return result; } @@ -1197,8 +1192,6 @@ const Field3D Mesh::indexDDX(const Field3D &f, CELL_LOC outloc, DIFF_METHOD meth ASSERT1(outloc == inloc || (outloc == CELL_CENTRE && inloc == CELL_XLOW) || (outloc == CELL_XLOW && inloc == CELL_CENTRE)); - Field3D result(this); - if (this->StaggerGrids && (outloc != inloc)) { // Shifting in X. Centre -> Xlow, or Xlow -> Centre @@ -1213,9 +1206,7 @@ const Field3D Mesh::indexDDX(const Field3D &f, CELL_LOC outloc, DIFF_METHOD meth throw BoutException("Cannot use FFT for X derivatives"); } - result = applyXdiff(f, func, outloc, region); - - return result; + return applyXdiff(f, func, outloc, region); } const Field2D Mesh::indexDDX(const Field2D &f, CELL_LOC outloc, @@ -1239,8 +1230,6 @@ const Field3D Mesh::indexDDY(const Field3D &f, CELL_LOC outloc, DIFF_METHOD meth ASSERT1(outloc == inloc || (outloc == CELL_CENTRE && inloc == CELL_YLOW) || (outloc == CELL_YLOW && inloc == CELL_CENTRE)); - Field3D result(this); - if (this->StaggerGrids && (outloc != inloc)) { // Shifting in Y. Centre -> Ylow, or Ylow -> Centre func = sfDDY; // Set default @@ -1254,9 +1243,7 @@ const Field3D Mesh::indexDDY(const Field3D &f, CELL_LOC outloc, DIFF_METHOD meth throw BoutException("Cannot use FFT for Y derivatives"); } - result = applyYdiff(f, func, outloc, region); - - return result; + return applyYdiff(f, func, outloc, region); } const Field2D Mesh::indexDDY(const Field2D &f, CELL_LOC outloc, @@ -1420,8 +1407,6 @@ const Field3D Mesh::indexD2DX2(const Field3D &f, CELL_LOC outloc, ASSERT1(this == f.getMesh()); - Field3D result(this); - if (StaggerGrids && (outloc != inloc)) { // Shifting in X. Centre -> Xlow, or Xlow -> Centre func = sfD2DX2; // Set default @@ -1435,9 +1420,7 @@ const Field3D Mesh::indexD2DX2(const Field3D &f, CELL_LOC outloc, throw BoutException("Cannot use FFT for X derivatives"); } - result = applyXdiff(f, func, outloc, region); - - return result; + return applyXdiff(f, func, outloc, region); } /*! @@ -1483,8 +1466,6 @@ const Field3D Mesh::indexD2DY2(const Field3D &f, CELL_LOC outloc, ASSERT1(outloc == inloc || (outloc == CELL_CENTRE && inloc == CELL_YLOW) || (outloc == CELL_YLOW && inloc == CELL_CENTRE)); - Field3D result(this); - if (StaggerGrids && (outloc != inloc)) { // Shifting in Y. Centre -> Ylow, or Ylow -> Centre func = sfD2DY2; // Set default @@ -1498,9 +1479,7 @@ const Field3D Mesh::indexD2DY2(const Field3D &f, CELL_LOC outloc, throw BoutException("Cannot use FFT for Y derivatives"); } - result = applyYdiff(f, func, outloc, region); - - return result; + return applyYdiff(f, func, outloc, region); } /*! @@ -1726,6 +1705,7 @@ const Field2D Mesh::indexVDDX(const Field2D &v, const Field2D &f, CELL_LOC outlo Field2D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (this->xstart > 1) { // Two or more guard cells @@ -1761,8 +1741,6 @@ const Field2D Mesh::indexVDDX(const Field2D &v, const Field2D &f, CELL_LOC outlo result.bndry_xin = result.bndry_xout = false; #endif - result.setLocation(outloc); - return result; } @@ -1776,6 +1754,7 @@ const Field3D Mesh::indexVDDX(const Field3D &v, const Field3D &f, CELL_LOC outlo ASSERT1(this == v.getMesh()); ASSERT1(this == f.getMesh()); + CELL_LOC vloc = v.getLocation(); CELL_LOC inloc = f.getLocation(); // Input location if (outloc == CELL_DEFAULT) @@ -1787,6 +1766,7 @@ const Field3D Mesh::indexVDDX(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); /// Convert REGION enum to a Region string identifier const auto region_str = REGION_STRING(region); @@ -1926,8 +1906,6 @@ const Field3D Mesh::indexVDDX(const Field3D &v, const Field3D &f, CELL_LOC outlo } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -1957,10 +1935,10 @@ const Field2D Mesh::indexVDDY(const Field2D &v, const Field2D &f, CELL_LOC outlo Field2D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (this->LocalNy == 1){ result=0; - result.setLocation(outloc); return result; } @@ -2102,8 +2080,6 @@ const Field2D Mesh::indexVDDY(const Field2D &v, const Field2D &f, CELL_LOC outlo } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -2131,10 +2107,10 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); if (this->LocalNy == 1){ result=0; - result.setLocation(outloc); return result; } @@ -2287,8 +2263,6 @@ const Field3D Mesh::indexVDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -2318,6 +2292,7 @@ const Field3D Mesh::indexVDDZ(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); /// Convert REGION enum to a Region string identifier const auto region_str = REGION_STRING(region); @@ -2388,8 +2363,6 @@ const Field3D Mesh::indexVDDZ(const Field3D &v, const Field3D &f, CELL_LOC outlo } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -2427,6 +2400,7 @@ const Field2D Mesh::indexFDDX(const Field2D &v, const Field2D &f, CELL_LOC outlo Field2D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); ASSERT1(this == v.getMesh()); ASSERT1(this == f.getMesh()); @@ -2521,6 +2495,7 @@ const Field3D Mesh::indexFDDX(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); /// Convert REGION enum to a Region string identifier const auto region_str = REGION_STRING(region); @@ -2652,8 +2627,6 @@ const Field3D Mesh::indexFDDX(const Field3D &v, const Field3D &f, CELL_LOC outlo } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -2691,7 +2664,7 @@ const Field2D Mesh::indexFDDY(const Field2D &v, const Field2D &f, CELL_LOC outlo Field2D result(this); result.allocate(); // Make sure data allocated - result.setLocation(f.getLocation()); + result.setLocation(outloc); /// Convert REGION enum to a Region string identifier const auto region_str = REGION_STRING(region); @@ -2735,8 +2708,6 @@ const Field2D Mesh::indexFDDY(const Field2D &v, const Field2D &f, CELL_LOC outlo } } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = false; @@ -2788,6 +2759,7 @@ const Field3D Mesh::indexFDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); // If *UseUpDown is true, field "*" has distinct yup and ydown fields which // will be used to calculate a derivative along the magnetic field @@ -2866,8 +2838,6 @@ const Field3D Mesh::indexFDDY(const Field3D &v, const Field3D &f, CELL_LOC outlo result = this->fromFieldAligned(result); } - result.setLocation(outloc); - #if CHECK > 0 // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; @@ -2918,6 +2888,7 @@ const Field3D Mesh::indexFDDZ(const Field3D &v, const Field3D &f, CELL_LOC outlo Field3D result(this); result.allocate(); // Make sure data allocated + result.setLocation(outloc); /// Convert REGION enum to a Region string identifier const auto region_str = REGION_STRING(region); @@ -2953,7 +2924,6 @@ const Field3D Mesh::indexFDDZ(const Field3D &v, const Field3D &f, CELL_LOC outlo result[i] = func(vval, fval); } } - result.setLocation(outloc); #if CHECK > 0 // Mark boundaries as invalid From 791ebc708be7f2bdf6710ceefb00dcbd6f340e0e Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 9 Oct 2018 16:00:45 +0100 Subject: [PATCH 16/69] Add ASSERTs for checking requested location is unambigous/consistent. Ensure location of result set in vecops routines --- src/field/vecops.cxx | 209 ++++++++++++++++++++++++++----------------- 1 file changed, 127 insertions(+), 82 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index c69f50d0fa..4da570bc25 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -35,18 +35,16 @@ **************************************************************************/ const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { - Vector2D result(f.getMesh()); - TRACE("Grad( Field2D )"); - - if (outloc == CELL_DEFAULT) { - outloc = f.getLocation(); - } + + Vector2D result(f.getMesh()); result.x = DDX(f, outloc); result.y = DDY(f, outloc); result.z = DDZ(f, outloc); + result.setLocation(outloc); + result.covariant = true; return result; @@ -54,24 +52,25 @@ const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { const Vector3D Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z) { - Vector3D result(f.getMesh()); + // Note no Vector2D equivalent to this three location overload TRACE("Grad( Field3D )"); - if (outloc_x == CELL_DEFAULT) { - outloc_x = f.getLocation(); - } - if (outloc_y == CELL_DEFAULT) { - outloc_y = f.getLocation(); - } - if (outloc_z == CELL_DEFAULT) { - outloc_z = f.getLocation(); - } + Vector3D result(f.getMesh()); + + ASSERT1((outloc_x == outloc_y && outloc_x == outloc_z) || + (outloc_x == CELL_XLOW && outloc_y == CELL_YLOW && + outloc_z == CELL_ZLOW)); // CELL_VSHIFT result.x = DDX(f, outloc_x); result.y = DDY(f, outloc_y); result.z = DDZ(f, outloc_z); + CELL_LOC outloc = (outloc_x == outloc_y && outloc_x == outloc_z) + ? result.x.getLocation() + : CELL_VSHIFT; + result.setLocation(outloc); + result.covariant = true; return result; @@ -82,28 +81,21 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc) { return Grad(f, CELL_XLOW, CELL_YLOW, CELL_ZLOW); } - if (outloc == CELL_DEFAULT) { - outloc = f.getLocation(); - } - return Grad(f, outloc, outloc, outloc); } -const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC UNUSED(outloc_y), +const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z) { - Vector3D result(f.getMesh()); - TRACE("Grad_perp( Field3D )"); - if (outloc_x == CELL_DEFAULT) { - outloc_x = f.getLocation(); - } - if (outloc_z == CELL_DEFAULT) { - outloc_z = f.getLocation(); - } + Vector3D result(f.getMesh()); - Coordinates *metric_x = mesh->coordinates(outloc_x); - Coordinates *metric_z = mesh->coordinates(outloc_z); + ASSERT1((outloc_x == outloc_y && outloc_x == outloc_z) || + (outloc_x == CELL_XLOW && outloc_y == CELL_YLOW && + outloc_z == CELL_ZLOW)); // CELL_VSHIFT + + Coordinates *metric_x = f.getCoordinates(outloc_x); + Coordinates *metric_z = f.getCoordinates(outloc_z); result.x = DDX(f, outloc_x) - metric_x->g_12 * DDY(f, outloc_x) / SQ(metric_x->J * metric_x->Bxy); @@ -111,6 +103,11 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC UNUSED(ou result.z = DDZ(f, outloc_z) - metric_z->g_23 * DDY(f, outloc_z) / SQ(metric_z->J * metric_z->Bxy); + CELL_LOC outloc = (outloc_x == outloc_y && outloc_x == outloc_z) + ? result.x.getLocation() + : CELL_VSHIFT; + result.setLocation(outloc); + result.covariant = true; return result; @@ -123,13 +120,15 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC UNUSED(ou const Field2D Div(const Vector2D &v, CELL_LOC outloc) { TRACE("Div( Vector2D )"); - Mesh *localmesh = v.x.getMesh(); - Field2D result(localmesh); - if (outloc == CELL_DEFAULT) { outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + + Mesh *localmesh = v.x.getMesh(); + Field2D result(localmesh); + Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v @@ -140,20 +139,24 @@ const Field2D Div(const Vector2D &v, CELL_LOC outloc) { result += DDY(metric->J*vcn.y, outloc); result += DDZ(metric->J*vcn.z, outloc); result /= metric->J; - + + result.setLocation(outloc); + return result; } const Field3D Div(const Vector3D &v, CELL_LOC outloc) { TRACE("Div( Vector3D )"); - Mesh *localmesh = v.x.getMesh(); - Field3D result(localmesh); - if (outloc == CELL_DEFAULT) { outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + + Mesh *localmesh = v.x.getMesh(); + Field3D result(localmesh); + Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v @@ -165,6 +168,8 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { result += DDZ(metric->J * vcn.z, outloc); result /= metric->J; + result.setLocation(outloc); + return result; } @@ -175,14 +180,18 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { TRACE("Div( Vector2D, Field2D )"); - ASSERT1(v.getLocation() == f.getLocation()); - - Mesh *localmesh = f.getMesh(); - if (outloc == CELL_DEFAULT) { outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + + // The following probably belongs in the FDD? routines rather than here + // as we don't directly interact v and f. Note also no equivalent in Field3D + // version of this routine. + ASSERT1(outloc == f.getLocation()); + + Mesh *localmesh = f.getMesh(); Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v @@ -195,6 +204,8 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { result += FDDZ(metric->J * vcn.z, f, outloc); result /= metric->J; + result.setLocation(outloc); + return result; } @@ -202,32 +213,36 @@ const Field3D Div(const Vector3D &v, const Field3D &f, DIFF_METHOD method, CELL_LOC outloc) { TRACE("Div( Vector3D, Field3D )"); - Mesh *localmesh = f.getMesh(); - Field3D result(localmesh); - if (outloc == CELL_DEFAULT) { outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + Mesh *localmesh = f.getMesh(); Coordinates *metric = localmesh->coordinates(outloc); // get contravariant components of v Vector3D vcn = v; vcn.toContravariant(); + Field3D result(localmesh); result = FDDX(metric->J * vcn.x, f, outloc, method); result += FDDY(metric->J * vcn.y, f, outloc, method); result += FDDZ(metric->J * vcn.z, f, outloc, method); result /= metric->J; + result.setLocation(outloc); + return result; } const Field3D Div(const Vector3D &v, const Field3D &f, CELL_LOC outloc, DIFF_METHOD method) { + TRACE("Div( Vector3D, Field3D)"); return Div(v, f, method, outloc); } const Field3D Div(const Vector3D &v, const Field3D &f) { + TRACE("Div( Vector3D, Field3D)"); return Div(v, f, DIFF_DEFAULT, CELL_DEFAULT); } @@ -239,12 +254,13 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { TRACE("Curl( Vector2D )"); - Mesh *localmesh = v.x.getMesh(); - if (outloc == CELL_DEFAULT) { outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + + Mesh *localmesh = v.x.getMesh(); Coordinates *metric = localmesh->coordinates(outloc); // Get covariant components of v @@ -260,6 +276,8 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { /// Coordinate torsion result.z -= metric->ShiftTorsion * vco.z / metric->J; + result.setLocation(outloc); + result.covariant = false; // result is contravariant return result; @@ -270,19 +288,11 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, TRACE("Curl( Vector3D )"); - Mesh *localmesh = v.x.getMesh(); - - if (outloc_x == CELL_DEFAULT) { - outloc_x = v.getLocation(); - } - if (outloc_y == CELL_DEFAULT) { - outloc_y = v.getLocation(); - } - if (outloc_z == CELL_DEFAULT) { - outloc_z = v.getLocation(); - } + ASSERT1((outloc_x == outloc_y && outloc_x == outloc_z) || + (outloc_x == CELL_XLOW && outloc_y == CELL_YLOW && + outloc_z == CELL_ZLOW)); // CELL_VSHIFT - Coordinates* metric_z = localmesh->coordinates(outloc_z); + Mesh *localmesh = v.x.getMesh(); // Get covariant components of v Vector3D vco = v; @@ -292,11 +302,18 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, Vector3D result(localmesh); result.x = (DDY(vco.z, outloc_x) - DDZ(vco.y, outloc_x))/localmesh->coordinates(outloc_x)->J; result.y = (DDZ(vco.x, outloc_y) - DDX(vco.z, outloc_y))/localmesh->coordinates(outloc_y)->J; - result.z = (DDX(vco.y, outloc_z) - DDY(vco.x, outloc_z))/metric_z->J; + result.z = + (DDX(vco.y, outloc_z) - DDY(vco.x, outloc_z)) / localmesh->coordinates(outloc_z)->J; + CELL_LOC outloc = (outloc_x == outloc_y && outloc_x == outloc_z) + ? result.x.getLocation() + : CELL_VSHIFT; // Coordinate torsion + auto metric_z = localmesh->coordinates(outloc_z); result.z -= metric_z->ShiftTorsion*vco.z / metric_z->J; + result.setLocation(outloc); + result.covariant = false; // result is contravariant return result; @@ -307,10 +324,6 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { return Curl(v, CELL_XLOW, CELL_YLOW, CELL_ZLOW); } - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - } - return Curl(v, outloc, outloc, outloc); } @@ -319,10 +332,10 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { **************************************************************************/ const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f) { - Field2D result(f.getMesh()); - TRACE("V_dot_Grad( Vector2D , Field2D )"); + Field2D result(f.getMesh()); + // Get contravariant components of v Vector2D vcn = v; vcn.toContravariant(); @@ -333,10 +346,10 @@ const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f) { } const Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { - Field3D result(f.getMesh()); - TRACE("V_dot_Grad( Vector2D , Field3D )"); + Field3D result(f.getMesh()); + // Get contravariant components of v Vector2D vcn = v; vcn.toContravariant(); @@ -347,10 +360,10 @@ const Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { } const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { - Field3D result(f.getMesh()); - TRACE("V_dot_Grad( Vector3D , Field2D )"); + Field3D result(f.getMesh()); + // Get contravariant components of v Vector3D vcn = v; vcn.toContravariant(); @@ -361,10 +374,10 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { } const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { - Field3D result(f.getMesh()); - TRACE("V_dot_Grad( Vector3D , Field3D )"); + Field3D result(f.getMesh()); + // Get contravariant components of v Vector3D vcn = v; vcn.toContravariant(); @@ -374,9 +387,15 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { return result; } -const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, const CELL_LOC outloc) { +const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, CELL_LOC outloc) { TRACE("V_dot_Grad( Vector2D , Vector2D )"); + ASSERT1(outloc != CELL_VSHIFT); + if (outloc == CELL_DEFAULT) { + ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); + outloc = v.getLocation(); + } + Mesh *localmesh = v.x.getMesh(); Vector2D result(localmesh); @@ -423,15 +442,23 @@ const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, const CELL_LOC o result.covariant = false; } + result.setLocation(outloc); + return result; } -const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, const CELL_LOC outloc) { +const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, CELL_LOC outloc) { + TRACE("V_dot_Grad( Vector2D , Vector3D )"); + + ASSERT1(outloc != CELL_VSHIFT); + if (outloc == CELL_DEFAULT) { + ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); + outloc = v.getLocation(); + } + Mesh *localmesh = v.x.getMesh(); Vector3D result(localmesh); - TRACE("V_dot_Grad( Vector2D , Vector3D )"); - Coordinates *metric = localmesh->coordinates(outloc); Vector2D vcn = v; @@ -473,15 +500,23 @@ const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, const CELL_LOC o result.covariant = false; } + result.setLocation(outloc); + return result; } -const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, const CELL_LOC outloc) { +const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, CELL_LOC outloc) { + TRACE("V_dot_Grad( Vector3D , Vector2D )"); + + ASSERT1(outloc != CELL_VSHIFT); + if (outloc == CELL_DEFAULT) { + ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); + outloc = v.getLocation(); + } + Mesh *localmesh = v.x.getMesh(); Vector3D result(localmesh); - TRACE("V_dot_Grad( Vector3D , Vector2D )"); - Coordinates *metric = localmesh->coordinates(outloc); Vector3D vcn = v; @@ -523,15 +558,23 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, const CELL_LOC o result.covariant = false; } + result.setLocation(outloc); + return result; } -const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, const CELL_LOC outloc) { +const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, CELL_LOC outloc) { + TRACE("V_dot_Grad( Vector3D , Vector3D )"); + + ASSERT1(outloc != CELL_VSHIFT); + if (outloc == CELL_DEFAULT) { + ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); + outloc = v.getLocation(); + } + Mesh *localmesh = v.x.getMesh(); Vector3D result(localmesh); - TRACE("V_dot_Grad( Vector3D , Vector3D )"); - Coordinates *metric = localmesh->coordinates(outloc); Vector3D vcn = v; @@ -573,6 +616,8 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, const CELL_LOC o result.covariant = false; } + result.setLocation(outloc); + return result; } From 5a079d4e4ddbfa99a045906c5236ef530b16274a Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 9 Oct 2018 16:47:15 +0100 Subject: [PATCH 17/69] Ensure Vector copy and assignment copies the location --- src/field/vector2d.cxx | 5 ++++- src/field/vector3d.cxx | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index e94e26b512..cbd00eb0e5 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -39,7 +39,8 @@ Vector2D::Vector2D(Mesh *localmesh) : x(localmesh), y(localmesh), z(localmesh), covariant(true), deriv(nullptr), location(CELL_CENTRE) {} Vector2D::Vector2D(const Vector2D &f) - : x(f.x), y(f.y), z(f.z), covariant(f.covariant), deriv(nullptr), location(CELL_CENTRE) {} + : x(f.x), y(f.y), z(f.z), covariant(f.covariant), deriv(nullptr), + location(f.getLocation()) {} Vector2D::~Vector2D() { if (deriv != nullptr) { @@ -151,6 +152,8 @@ Vector2D & Vector2D::operator=(const Vector2D &rhs) { y = rhs.y; z = rhs.z; + setLocation(rhs.getLocation()); + covariant = rhs.covariant; return *this; diff --git a/src/field/vector3d.cxx b/src/field/vector3d.cxx index c7df254d0e..adcd510aac 100644 --- a/src/field/vector3d.cxx +++ b/src/field/vector3d.cxx @@ -40,7 +40,8 @@ Vector3D::Vector3D(Mesh *localmesh) : x(localmesh), y(localmesh), z(localmesh), covariant(true), deriv(nullptr), location(CELL_CENTRE) {} Vector3D::Vector3D(const Vector3D &f) - : x(f.x), y(f.y), z(f.z), covariant(f.covariant), deriv(nullptr), location(CELL_CENTRE) {} + : x(f.x), y(f.y), z(f.z), covariant(f.covariant), deriv(nullptr), + location(f.getLocation()) {} Vector3D::~Vector3D() { if (deriv != nullptr) { @@ -154,6 +155,7 @@ Vector3D & Vector3D::operator=(const Vector3D &rhs) { covariant = rhs.covariant; + setLocation(rhs.getLocation()); return *this; } @@ -164,6 +166,8 @@ Vector3D & Vector3D::operator=(const Vector2D &rhs) { covariant = rhs.covariant; + setLocation(rhs.getLocation()); + return *this; } From 2f3930624218fe387f6fd5b9dc0eb5bcf8d3631b Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 09:04:08 +0100 Subject: [PATCH 18/69] Expand unit tests to check that vector copy/assignment copies location --- tests/unit/field/test_vector2d.cxx | 10 ++++++++++ tests/unit/field/test_vector3d.cxx | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/tests/unit/field/test_vector2d.cxx b/tests/unit/field/test_vector2d.cxx index ffeda89eaf..4643ade391 100644 --- a/tests/unit/field/test_vector2d.cxx +++ b/tests/unit/field/test_vector2d.cxx @@ -123,28 +123,38 @@ TEST_F(Vector2DTest, AssignFromBoutReal) { TEST_F(Vector2DTest, AssignFromVector2D) { Vector2D vector1, vector2; + + vector1.x.getMesh()->StaggerGrids = true; + vector1.x = 1.0; vector1.y = 2.0; vector1.z = 3.0; + vector1.setLocation(CELL_XLOW); vector2 = vector1; EXPECT_TRUE(IsField2DEqualBoutReal(vector2.x, 1.0)); EXPECT_TRUE(IsField2DEqualBoutReal(vector2.y, 2.0)); EXPECT_TRUE(IsField2DEqualBoutReal(vector2.z, 3.0)); + EXPECT_EQ(vector1.getLocation(), vector2.getLocation()); } TEST_F(Vector2DTest, CreateFromVector2D) { Vector2D vector1; + + vector1.x.getMesh()->StaggerGrids = true; + vector1.x = 4.0; vector1.y = 5.0; vector1.z = 6.0; + vector1.setLocation(CELL_YLOW); Vector2D vector2{vector1}; EXPECT_TRUE(IsField2DEqualBoutReal(vector2.x, 4.0)); EXPECT_TRUE(IsField2DEqualBoutReal(vector2.y, 5.0)); EXPECT_TRUE(IsField2DEqualBoutReal(vector2.z, 6.0)); + EXPECT_EQ(vector1.getLocation(), vector2.getLocation()); } TEST_F(Vector2DTest, UnaryMinus) { diff --git a/tests/unit/field/test_vector3d.cxx b/tests/unit/field/test_vector3d.cxx index a60157bd9d..6a2181f169 100644 --- a/tests/unit/field/test_vector3d.cxx +++ b/tests/unit/field/test_vector3d.cxx @@ -120,30 +120,59 @@ TEST_F(Vector3DTest, AssignFromBoutReal) { EXPECT_TRUE(IsField3DEqualBoutReal(vector.z, 0.0)); } +TEST_F(Vector3DTest, AssignFromVector2D) { + Vector2D vector1; + Vector3D vector2; + + vector1.x.getMesh()->StaggerGrids = true; + + vector1.x = 1.0; + vector1.y = 2.0; + vector1.z = 3.0; + vector1.setLocation(CELL_XLOW); + + vector2 = vector1; + + EXPECT_TRUE(IsField3DEqualBoutReal(vector2.x, 1.0)); + EXPECT_TRUE(IsField3DEqualBoutReal(vector2.y, 2.0)); + EXPECT_TRUE(IsField3DEqualBoutReal(vector2.z, 3.0)); + EXPECT_EQ(vector1.getLocation(), vector2.getLocation()); +} + TEST_F(Vector3DTest, AssignFromVector3D) { Vector3D vector1, vector2; + + vector1.x.getMesh()->StaggerGrids = true; + vector1.x = 1.0; vector1.y = 2.0; vector1.z = 3.0; + vector1.setLocation(CELL_XLOW); vector2 = vector1; EXPECT_TRUE(IsField3DEqualBoutReal(vector2.x, 1.0)); EXPECT_TRUE(IsField3DEqualBoutReal(vector2.y, 2.0)); EXPECT_TRUE(IsField3DEqualBoutReal(vector2.z, 3.0)); + EXPECT_EQ(vector1.getLocation(), vector2.getLocation()); } TEST_F(Vector3DTest, CreateFromVector3D) { Vector3D vector1; + + vector1.x.getMesh()->StaggerGrids = true; + vector1.x = 4.0; vector1.y = 5.0; vector1.z = 6.0; + vector1.setLocation(CELL_YLOW); Vector3D vector2{vector1}; EXPECT_TRUE(IsField3DEqualBoutReal(vector2.x, 4.0)); EXPECT_TRUE(IsField3DEqualBoutReal(vector2.y, 5.0)); EXPECT_TRUE(IsField3DEqualBoutReal(vector2.z, 6.0)); + EXPECT_EQ(vector1.getLocation(), vector2.getLocation()); } TEST_F(Vector3DTest, UnaryMinus) { From b3b756ee4caf71359f6638804a89223bdd2f78cd Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 09:43:36 +0100 Subject: [PATCH 19/69] Handle CELL_DEFAULT in vector setLocation --- src/field/vector2d.cxx | 5 +++++ src/field/vector3d.cxx | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index cbd00eb0e5..ad8e5ac4cf 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -391,6 +391,11 @@ CELL_LOC Vector2D::getLocation() const { } void Vector2D::setLocation(CELL_LOC loc) { + TRACE("Vector2D::setLocation"); + if (loc == CELL_DEFAULT) { + loc = CELL_CENTRE; + } + location = loc; if(loc == CELL_VSHIFT) { x.setLocation(CELL_XLOW); diff --git a/src/field/vector3d.cxx b/src/field/vector3d.cxx index adcd510aac..c338583ace 100644 --- a/src/field/vector3d.cxx +++ b/src/field/vector3d.cxx @@ -519,6 +519,11 @@ CELL_LOC Vector3D::getLocation() const { } void Vector3D::setLocation(CELL_LOC loc) { + TRACE("Vector3D::setLocation"); + if (loc == CELL_DEFAULT) { + loc = CELL_CENTRE; + } + location = loc; if(loc == CELL_VSHIFT) { x.setLocation(CELL_XLOW); From 04f0ecade42930c96ca4f25bf5ba03ee4f744824 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 09:44:02 +0100 Subject: [PATCH 20/69] Add unit tests for vector setLocation --- tests/unit/field/test_vector2d.cxx | 67 ++++++++++++++++++++++++++++++ tests/unit/field/test_vector3d.cxx | 67 ++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/tests/unit/field/test_vector2d.cxx b/tests/unit/field/test_vector2d.cxx index 4643ade391..b4e54d5a5e 100644 --- a/tests/unit/field/test_vector2d.cxx +++ b/tests/unit/field/test_vector2d.cxx @@ -111,6 +111,73 @@ TEST_F(Vector2DTest, TimeDeriv) { EXPECT_EQ(&(ddt(vector)), deriv); } +TEST_F(Vector2DTest, SetLocationNonStaggered) { + Vector2D vector; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(CELL_CENTRE)); + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_THROW(vector.setLocation(CELL_XLOW), BoutException); +} + +TEST_F(Vector2DTest, SetLocationXLOW) { + Vector2D vector; + CELL_LOC targetLoc = CELL_XLOW; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(targetLoc)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + +TEST_F(Vector2DTest, SetLocationYLOW) { + Vector2D vector; + CELL_LOC targetLoc = CELL_YLOW; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(targetLoc)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + +TEST_F(Vector2DTest, SetLocationZLOW) { + Vector2D vector; + CELL_LOC targetLoc = CELL_ZLOW; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(targetLoc)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + +TEST_F(Vector2DTest, SetLocationVSHIFT) { + Vector2D vector; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(CELL_VSHIFT)); + EXPECT_EQ(vector.getLocation(), CELL_VSHIFT); + EXPECT_EQ(vector.x.getLocation(), CELL_XLOW); + EXPECT_EQ(vector.y.getLocation(), CELL_YLOW); + EXPECT_EQ(vector.z.getLocation(), CELL_ZLOW); +} + +TEST_F(Vector2DTest, SetLocationDEFAULT) { + Vector2D vector; + CELL_LOC targetLoc = CELL_CENTRE; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(CELL_DEFAULT)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + TEST_F(Vector2DTest, AssignFromBoutReal) { Vector2D vector; diff --git a/tests/unit/field/test_vector3d.cxx b/tests/unit/field/test_vector3d.cxx index 6a2181f169..eb8425889d 100644 --- a/tests/unit/field/test_vector3d.cxx +++ b/tests/unit/field/test_vector3d.cxx @@ -110,6 +110,73 @@ TEST_F(Vector3DTest, TimeDeriv) { EXPECT_EQ(&(ddt(vector)), deriv); } +TEST_F(Vector3DTest, SetLocationNonStaggered) { + Vector3D vector; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(CELL_CENTRE)); + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_THROW(vector.setLocation(CELL_XLOW), BoutException); +} + +TEST_F(Vector3DTest, SetLocationXLOW) { + Vector3D vector; + CELL_LOC targetLoc = CELL_XLOW; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(targetLoc)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + +TEST_F(Vector3DTest, SetLocationYLOW) { + Vector3D vector; + CELL_LOC targetLoc = CELL_YLOW; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(targetLoc)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + +TEST_F(Vector3DTest, SetLocationZLOW) { + Vector3D vector; + CELL_LOC targetLoc = CELL_ZLOW; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(targetLoc)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + +TEST_F(Vector3DTest, SetLocationVSHIFT) { + Vector3D vector; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(CELL_VSHIFT)); + EXPECT_EQ(vector.getLocation(), CELL_VSHIFT); + EXPECT_EQ(vector.x.getLocation(), CELL_XLOW); + EXPECT_EQ(vector.y.getLocation(), CELL_YLOW); + EXPECT_EQ(vector.z.getLocation(), CELL_ZLOW); +} + +TEST_F(Vector3DTest, SetLocationDEFAULT) { + Vector3D vector; + CELL_LOC targetLoc = CELL_CENTRE; + vector.x.getMesh()->StaggerGrids = true; + EXPECT_EQ(vector.getLocation(), CELL_CENTRE); + EXPECT_NO_THROW(vector.setLocation(CELL_DEFAULT)); + EXPECT_EQ(vector.getLocation(), targetLoc); + EXPECT_EQ(vector.x.getLocation(), targetLoc); + EXPECT_EQ(vector.y.getLocation(), targetLoc); + EXPECT_EQ(vector.z.getLocation(), targetLoc); +} + TEST_F(Vector3DTest, AssignFromBoutReal) { Vector3D vector; From 96dc8ab69fed012d9765a8d2a3837430032d8bb7 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 10:05:23 +0100 Subject: [PATCH 21/69] Fix for vector non-staggered setLocation unit tests --- tests/unit/field/test_vector2d.cxx | 2 ++ tests/unit/field/test_vector3d.cxx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/unit/field/test_vector2d.cxx b/tests/unit/field/test_vector2d.cxx index b4e54d5a5e..7824f2b2cf 100644 --- a/tests/unit/field/test_vector2d.cxx +++ b/tests/unit/field/test_vector2d.cxx @@ -116,7 +116,9 @@ TEST_F(Vector2DTest, SetLocationNonStaggered) { EXPECT_EQ(vector.getLocation(), CELL_CENTRE); EXPECT_NO_THROW(vector.setLocation(CELL_CENTRE)); EXPECT_EQ(vector.getLocation(), CELL_CENTRE); +#if CHECK > 0 EXPECT_THROW(vector.setLocation(CELL_XLOW), BoutException); +#endif } TEST_F(Vector2DTest, SetLocationXLOW) { diff --git a/tests/unit/field/test_vector3d.cxx b/tests/unit/field/test_vector3d.cxx index eb8425889d..fb77078781 100644 --- a/tests/unit/field/test_vector3d.cxx +++ b/tests/unit/field/test_vector3d.cxx @@ -115,7 +115,9 @@ TEST_F(Vector3DTest, SetLocationNonStaggered) { EXPECT_EQ(vector.getLocation(), CELL_CENTRE); EXPECT_NO_THROW(vector.setLocation(CELL_CENTRE)); EXPECT_EQ(vector.getLocation(), CELL_CENTRE); +#if CHECK > 0 EXPECT_THROW(vector.setLocation(CELL_XLOW), BoutException); +#endif } TEST_F(Vector3DTest, SetLocationXLOW) { From ba80a082d06e48be463bb7b7cca2a6f5a47b98aa Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 10:05:51 +0100 Subject: [PATCH 22/69] Add staggered flag check in vector setLocation --- src/field/vector2d.cxx | 27 +++++++++++++++++++-------- src/field/vector3d.cxx | 27 +++++++++++++++++++-------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index ad8e5ac4cf..c3cac4bf00 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -396,16 +396,27 @@ void Vector2D::setLocation(CELL_LOC loc) { loc = CELL_CENTRE; } - location = loc; - if(loc == CELL_VSHIFT) { - x.setLocation(CELL_XLOW); - y.setLocation(CELL_YLOW); - z.setLocation(CELL_ZLOW); + if (x.getMesh()->StaggerGrids) { + if (loc == CELL_VSHIFT) { + x.setLocation(CELL_XLOW); + y.setLocation(CELL_YLOW); + z.setLocation(CELL_ZLOW); + } else { + x.setLocation(loc); + y.setLocation(loc); + z.setLocation(loc); + } } else { - x.setLocation(loc); - y.setLocation(loc); - z.setLocation(loc); +#if CHECK > 0 + if (loc != CELL_CENTRE) { + throw BoutException("Vector2D: Trying to set off-centre location on " + "non-staggered grid\n" + " Did you mean to enable staggered grids?"); + } +#endif } + + location = loc; } /*************************************************************** diff --git a/src/field/vector3d.cxx b/src/field/vector3d.cxx index c338583ace..dd4f2f8f25 100644 --- a/src/field/vector3d.cxx +++ b/src/field/vector3d.cxx @@ -524,16 +524,27 @@ void Vector3D::setLocation(CELL_LOC loc) { loc = CELL_CENTRE; } - location = loc; - if(loc == CELL_VSHIFT) { - x.setLocation(CELL_XLOW); - y.setLocation(CELL_YLOW); - z.setLocation(CELL_ZLOW); + if (x.getMesh()->StaggerGrids) { + if (loc == CELL_VSHIFT) { + x.setLocation(CELL_XLOW); + y.setLocation(CELL_YLOW); + z.setLocation(CELL_ZLOW); + } else { + x.setLocation(loc); + y.setLocation(loc); + z.setLocation(loc); + } } else { - x.setLocation(loc); - y.setLocation(loc); - z.setLocation(loc); +#if CHECK > 0 + if (loc != CELL_CENTRE) { + throw BoutException("Vector3D: Trying to set off-centre location on " + "non-staggered grid\n" + " Did you mean to enable staggered grids?"); + } +#endif } + + location = loc; } /*************************************************************** From 546ca7843ec4a309af75d515a22d066173238290 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 11:01:34 +0100 Subject: [PATCH 23/69] Remove duplicated ASSERT --- src/field/vecops.cxx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 4da570bc25..b5e37f2069 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -186,11 +186,6 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { ASSERT1(outloc != CELL_VSHIFT); - // The following probably belongs in the FDD? routines rather than here - // as we don't directly interact v and f. Note also no equivalent in Field3D - // version of this routine. - ASSERT1(outloc == f.getLocation()); - Mesh *localmesh = f.getMesh(); Coordinates *metric = localmesh->coordinates(outloc); From 8c571e977a7128617055b553ba15a50d59a1b321 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 11:13:53 +0100 Subject: [PATCH 24/69] Remove setLocation calls that are not required --- src/field/vecops.cxx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index b5e37f2069..1c2fa0eb48 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -140,8 +140,6 @@ const Field2D Div(const Vector2D &v, CELL_LOC outloc) { result += DDZ(metric->J*vcn.z, outloc); result /= metric->J; - result.setLocation(outloc); - return result; } @@ -168,8 +166,6 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { result += DDZ(metric->J * vcn.z, outloc); result /= metric->J; - result.setLocation(outloc); - return result; } @@ -199,8 +195,6 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { result += FDDZ(metric->J * vcn.z, f, outloc); result /= metric->J; - result.setLocation(outloc); - return result; } @@ -226,8 +220,6 @@ const Field3D Div(const Vector3D &v, const Field3D &f, DIFF_METHOD method, result += FDDZ(metric->J * vcn.z, f, outloc, method); result /= metric->J; - result.setLocation(outloc); - return result; } From fce307db020c332fa954b83f53caffa30f90892b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 10 Oct 2018 15:23:02 +0100 Subject: [PATCH 25/69] Improvements after feedback --- tests/integrated/test-squash/data/BOUT.inp | 9 +- tests/integrated/test-squash/runtest | 116 ++++++++++++--------- 2 files changed, 72 insertions(+), 53 deletions(-) diff --git a/tests/integrated/test-squash/data/BOUT.inp b/tests/integrated/test-squash/data/BOUT.inp index b9d7a3a236..e5af938f53 100644 --- a/tests/integrated/test-squash/data/BOUT.inp +++ b/tests/integrated/test-squash/data/BOUT.inp @@ -1,12 +1,13 @@ timestep = 1. -nout = 10 +nout = 2 MZ = 1 [mesh] - -nx = 12 -ny = 8 +MXG=1 +MYG=1 +nx = 4 +ny = 2 dx = 1. dy = 1. diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index 7b34ea5316..f0aecfcee9 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -1,72 +1,90 @@ #!/usr/bin/env python3 -import netCDF4 as nc +from boututils.datafile import DataFile import itertools as it import os +import time +import numpy as np +from boututils.run_wrapper import shell_safe as _shell_safe +#requires: all_tests +#requires: netcdf -def run(cmd): - s = os.system(cmd) - if s: - raise RuntimeError("%s exited with non-zero %d value" % (cmd, s)) +class timer(object): + + def __init__(self, msg): + self.msg = msg + + def __enter__(self): + self.start = time.time() + + def __exit__(self, a, b, c): + end = time.time() + print("%12.8f %s" % (end - self.start, self.msg)) + + +def shell_safe(cmd): + with timer(cmd): + _shell_safe(cmd) def verify(f1, f2): - org = nc.Dataset(f1) - para = nc.Dataset(f2) - for v in org.variables: - if org[v].shape != para[v].shape: - print(org[v]) - print(para[v]) - raise RuntimeError("shape mismatch in ", v) - if v in ["MXSUB", "MYSUB", "NXPE", "NYPE", "iteration"]: - continue - if (org[v][:] != para[v][:]).any(): - a = org[v] - b = para[v] - print(a) - print(b) - lst = [range(x) for x in org[v].shape] - for i in it.product(*lst): - if a[i] != b[i]: - print(i, ":", a[i], "!=", b[i]) - # There are differences, but I think only guard cells are affected - raise RuntimeError("data mismatch in ", v) - -run("make") + with timer("verify %s %s" % (f1, f2)): + d1 = DataFile(f1) + d2 = DataFile(f2) + for v in d1.keys(): + if d1[v].shape != d2[v].shape: + raise RuntimeError("shape mismatch in ", v, d1[v], d2[v]) + if v in ["MXSUB", "MYSUB", "NXPE", "NYPE", "iteration"]: + continue + if not np.allclose(d1[v], d2[v]): + # continue + a = d1[v] + b = d2[v] + err = "" + lst = [range(x) for x in d1[v].shape] + for i in it.product(*lst): + if a[i] != b[i]: + err += str(i) + ":" + str(a[i]) + "!=" + str( b[i]) + """ +""" + # There are differences, but I think only guard cells are + # affected + raise RuntimeError("data mismatch in ", v, err, a, b) + +shell_safe("make") # Run once to get normal data -run("./squash -q -q -q nout=20") -run("mv data/BOUT.dmp.0.nc 20.nc") +shell_safe("./squash -q -q -q nout=4") +shell_safe("mv data/BOUT.dmp.0.nc f1.nc") # Parallel test -run("rm -f para.nc") -run("mpirun -np 4 ./squash -q -q -q nout=20") -run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../para.nc") +shell_safe("rm -f f2.nc") +shell_safe("mpirun -np 4 ./squash -q -q -q nout=4") +shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") -verify("20.nc", "para.nc") +verify("f1.nc", "f2.nc") # Parallel and in two pieces -run("rm -f para.nc") -run("mpirun -np 4 ./squash -q -q -q") -run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../para.nc") -run("mpirun -np 4 ./squash -q -q -q restart") -run("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../para.nc") +shell_safe("rm -f f2.nc") +shell_safe("mpirun -np 4 ./squash -q -q -q") +shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") +shell_safe("mpirun -np 4 ./squash -q -q -q restart") +shell_safe("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../f2.nc") -verify("20.nc", "para.nc") +verify("f1.nc", "f2.nc") # Parallel and in two pieces without dump_on_restart -run("rm -f para.nc") -run("mpirun -np 4 ./squash -q -q -q") -run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../para.nc") -run("mpirun -np 4 ./squash -q -q -q restart dump_on_restart=false") -run("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../para.nc") +shell_safe("rm -f f2.nc") +shell_safe("mpirun -np 4 ./squash -q -q -q") +shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") +shell_safe("mpirun -np 4 ./squash -q -q -q restart dump_on_restart=false") +shell_safe("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../f2.nc") -verify("20.nc", "para.nc") +verify("f1.nc", "f2.nc") # Sequential test -run("rm -f seq.nc") -run("./squash -q -q -q nout=20") -run("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../seq.nc") +shell_safe("rm -f f2.nc") +shell_safe("./squash -q -q -q nout=4") +shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") -verify("20.nc", "seq.nc") +verify("f1.nc", "f2.nc") From 1c4f9b98b135445d26c57bd2c638b06b15bc698c Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 15:38:11 +0100 Subject: [PATCH 26/69] Adding support for CELL_VSHIFT to Grad(Field2D) --- src/field/vecops.cxx | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 1c2fa0eb48..d51371eeca 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -37,13 +37,26 @@ const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { TRACE("Grad( Field2D )"); + CELL_LOC outloc_x, outloc_y, outloc_z; + if (outloc == CELL_VSHIFT) { + outloc_x = CELL_XLOW; + outloc_y = CELL_YLOW; + outloc_z = CELL_ZLOW; + } else { + outloc_x = outloc_y = outloc_z = outloc; + } + Vector2D result(f.getMesh()); - result.x = DDX(f, outloc); - result.y = DDY(f, outloc); - result.z = DDZ(f, outloc); + result.x = DDX(f, outloc_x); + result.y = DDY(f, outloc_y); + result.z = DDZ(f, outloc_z); - result.setLocation(outloc); + if (outloc == CELL_DEFAULT) { + result.setLocation(result.x.getLocation()); + } else { + result.setLocation(outloc); + } result.covariant = true; From 83d6b82e04c5fec5c81ea0e5302c9955281bbcfb Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 15:38:46 +0100 Subject: [PATCH 27/69] Deprecating three arg version of Grad(Field3D) --- src/field/vecops.cxx | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index d51371eeca..ba0b388675 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -63,40 +63,49 @@ const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { return result; } -const Vector3D Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, - CELL_LOC outloc_z) { +const Vector3D DEPRECATED(Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z)) { // Note no Vector2D equivalent to this three location overload - TRACE("Grad( Field3D )"); - Vector3D result(f.getMesh()); - ASSERT1((outloc_x == outloc_y && outloc_x == outloc_z) || (outloc_x == CELL_XLOW && outloc_y == CELL_YLOW && outloc_z == CELL_ZLOW)); // CELL_VSHIFT + CELL_LOC outloc = + (outloc_x == outloc_y && outloc_x == outloc_z) ? outloc_x : CELL_VSHIFT; + return Grad(f, outloc); +} + +const Vector3D Grad(const Field3D &f, CELL_LOC outloc) { + TRACE("Grad( Field3D )"); + + CELL_LOC outloc_x, outloc_y, outloc_z; + if (outloc == CELL_VSHIFT) { + outloc_x = CELL_XLOW; + outloc_y = CELL_YLOW; + outloc_z = CELL_ZLOW; + } else { + outloc_x = outloc_y = outloc_z = outloc; + } + + Vector3D result(f.getMesh()); + result.x = DDX(f, outloc_x); result.y = DDY(f, outloc_y); result.z = DDZ(f, outloc_z); - CELL_LOC outloc = (outloc_x == outloc_y && outloc_x == outloc_z) - ? result.x.getLocation() - : CELL_VSHIFT; - result.setLocation(outloc); + if (outloc == CELL_DEFAULT) { + result.setLocation(result.x.getLocation()); + } else { + result.setLocation(outloc); + } result.covariant = true; return result; } -const Vector3D Grad(const Field3D &f, CELL_LOC outloc) { - if (outloc == CELL_VSHIFT) { - return Grad(f, CELL_XLOW, CELL_YLOW, CELL_ZLOW); - } - - return Grad(f, outloc, outloc, outloc); -} - const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z) { TRACE("Grad_perp( Field3D )"); From 993968c225e7970fb2be32c9142a7e3caf0b13cb Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 15:47:27 +0100 Subject: [PATCH 28/69] Ensure Grad_perp only works at location of input field --- src/field/vecops.cxx | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index ba0b388675..24ac0fa192 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -106,29 +106,28 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc) { return result; } -const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, - CELL_LOC outloc_z) { +const Vector3D DEPRECATED(Grad_perp(const Field3D &f, CELL_LOC outloc_x, + CELL_LOC outloc_y, CELL_LOC outloc_z)) { TRACE("Grad_perp( Field3D )"); + ASSERT1(outloc_x == outloc_y && outloc_x == outloc_z); + ASSERT1(outloc_x == CELL_DEFAULT || outloc_x == f.getLocation()); + return Grad_perp(f, outloc_x); +} - Vector3D result(f.getMesh()); +const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc) { + TRACE("Grad_perp( Field3D )"); - ASSERT1((outloc_x == outloc_y && outloc_x == outloc_z) || - (outloc_x == CELL_XLOW && outloc_y == CELL_YLOW && - outloc_z == CELL_ZLOW)); // CELL_VSHIFT + ASSERT1(outloc == CELL_DEFAULT || outloc == f.getLocation()); - Coordinates *metric_x = f.getCoordinates(outloc_x); - Coordinates *metric_z = f.getCoordinates(outloc_z); + Coordinates *metric = f.getCoordinates(outloc); - result.x = DDX(f, outloc_x) - - metric_x->g_12 * DDY(f, outloc_x) / SQ(metric_x->J * metric_x->Bxy); + Vector3D result(f.getMesh()); + + result.x = DDX(f, outloc) - metric->g_12 * DDY(f, outloc) / SQ(metric->J * metric->Bxy); result.y = 0.0; - result.z = DDZ(f, outloc_z) - - metric_z->g_23 * DDY(f, outloc_z) / SQ(metric_z->J * metric_z->Bxy); + result.z = DDZ(f, outloc) - metric->g_23 * DDY(f, outloc) / SQ(metric->J * metric->Bxy); - CELL_LOC outloc = (outloc_x == outloc_y && outloc_x == outloc_z) - ? result.x.getLocation() - : CELL_VSHIFT; - result.setLocation(outloc); + result.setLocation(result.x.getLocation()); result.covariant = true; From 93330d078fa6ec3df8641c7ebf0b1f17b392da75 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 16:05:48 +0100 Subject: [PATCH 29/69] Updating treatment of location in Curl. Forbid use of CELL_VSHIFT --- src/field/vecops.cxx | 49 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 24ac0fa192..2cdb575853 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -266,10 +266,13 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { outloc = v.getLocation(); } + // We can't support VSHIFT here as, e.g. DDY can't produce an output at CELL_XLOW + // unless the input field is at CELL_XLOW, but then that field will also be needed + // at CELL_YLOW, for example for another component. ASSERT1(outloc != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); - Coordinates *metric = localmesh->coordinates(outloc); + auto metric = localmesh->coordinates(outloc); // Get covariant components of v Vector2D vco = v; @@ -291,16 +294,27 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { return result; } -const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, - CELL_LOC outloc_z) { +const Vector3D DEPRECATED(Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z)) { + TRACE("Curl( Vector3D )"); + ASSERT1(outloc_x == outloc_y && outloc_x == outloc_z); + return Curl(v, outloc_x); +} +const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { TRACE("Curl( Vector3D )"); - ASSERT1((outloc_x == outloc_y && outloc_x == outloc_z) || - (outloc_x == CELL_XLOW && outloc_y == CELL_YLOW && - outloc_z == CELL_ZLOW)); // CELL_VSHIFT + if (outloc == CELL_DEFAULT) { + outloc = v.getLocation(); + }; + + // We can't support VSHIFT here as, e.g. DDY can't produce an output at CELL_XLOW + // unless the input field is at CELL_XLOW, but then that field will also be needed + // at CELL_YLOW, for example for another component. + ASSERT1(outloc != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); + auto metric = v.x.getCoordinates(outloc); // Get covariant components of v Vector3D vco = v; @@ -308,17 +322,12 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, // get components (curl(v))^j Vector3D result(localmesh); - result.x = (DDY(vco.z, outloc_x) - DDZ(vco.y, outloc_x))/localmesh->coordinates(outloc_x)->J; - result.y = (DDZ(vco.x, outloc_y) - DDX(vco.z, outloc_y))/localmesh->coordinates(outloc_y)->J; - result.z = - (DDX(vco.y, outloc_z) - DDY(vco.x, outloc_z)) / localmesh->coordinates(outloc_z)->J; - - CELL_LOC outloc = (outloc_x == outloc_y && outloc_x == outloc_z) - ? result.x.getLocation() - : CELL_VSHIFT; + result.x = (DDY(vco.z, outloc) - DDZ(vco.y, outloc)) / metric->J; + result.y = (DDZ(vco.x, outloc) - DDX(vco.z, outloc)) / metric->J; + result.z = (DDX(vco.y, outloc) - DDY(vco.x, outloc)) / metric->J; + // Coordinate torsion - auto metric_z = localmesh->coordinates(outloc_z); - result.z -= metric_z->ShiftTorsion*vco.z / metric_z->J; + result.z -= metric->ShiftTorsion * vco.z / metric->J; result.setLocation(outloc); @@ -327,14 +336,6 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, return result; } -const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { - if (outloc == CELL_VSHIFT) { - return Curl(v, CELL_XLOW, CELL_YLOW, CELL_ZLOW); - } - - return Curl(v, outloc, outloc, outloc); -} - /************************************************************************** * Upwinding operators **************************************************************************/ From 06699412e9d06c652d6b30712b92143004acc05e Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 16:11:33 +0100 Subject: [PATCH 30/69] Attempt to fix asserts in V_dot_grad --- src/field/vecops.cxx | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 2cdb575853..10dda46e14 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -399,12 +399,15 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, CELL_LOC outloc) { TRACE("V_dot_Grad( Vector2D , Vector2D )"); - ASSERT1(outloc != CELL_VSHIFT); if (outloc == CELL_DEFAULT) { - ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + ASSERT1(v.getLocation() == a.getLocation()); + // Note the following assert means the outloc argument is pointless + ASSERT1(v.getLocation() == outloc); + Mesh *localmesh = v.x.getMesh(); Vector2D result(localmesh); @@ -459,12 +462,15 @@ const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, CELL_LOC outloc) const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, CELL_LOC outloc) { TRACE("V_dot_Grad( Vector2D , Vector3D )"); - ASSERT1(outloc != CELL_VSHIFT); if (outloc == CELL_DEFAULT) { - ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + ASSERT1(v.getLocation() == a.getLocation()); + // Note the following assert means the outloc argument is pointless + ASSERT1(v.getLocation() == outloc); + Mesh *localmesh = v.x.getMesh(); Vector3D result(localmesh); @@ -517,12 +523,15 @@ const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, CELL_LOC outloc) const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, CELL_LOC outloc) { TRACE("V_dot_Grad( Vector3D , Vector2D )"); - ASSERT1(outloc != CELL_VSHIFT); if (outloc == CELL_DEFAULT) { - ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + ASSERT1(v.getLocation() == a.getLocation()); + // Note the following assert means the outloc argument is pointless + ASSERT1(v.getLocation() == outloc); + Mesh *localmesh = v.x.getMesh(); Vector3D result(localmesh); @@ -575,12 +584,15 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, CELL_LOC outloc) const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, CELL_LOC outloc) { TRACE("V_dot_Grad( Vector3D , Vector3D )"); - ASSERT1(outloc != CELL_VSHIFT); if (outloc == CELL_DEFAULT) { - ASSERT1(outloc == v.getLocation() && outloc == a.getLocation()); outloc = v.getLocation(); } + ASSERT1(outloc != CELL_VSHIFT); + ASSERT1(v.getLocation() == a.getLocation()); + // Note the following assert means the outloc argument is pointless + ASSERT1(v.getLocation() == outloc); + Mesh *localmesh = v.x.getMesh(); Vector3D result(localmesh); From db34fd64ef2b864123967f0f231d6d9ae8a8ffc4 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 16:18:11 +0100 Subject: [PATCH 31/69] Move depecrated into header --- include/vecops.hxx | 27 +++++++++++++++++++-------- src/field/vecops.cxx | 12 ++++++------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 14b021ef67..4ba38b96ce 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -48,8 +48,19 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// @param[in] outloc_x The cell location where the X component should be defined /// @param[in] outloc_y The cell location where the Y component should be defined /// @param[in] outloc_z The cell location where the Z component should be defined -const Vector3D Grad(const Field3D &f, - CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z = CELL_DEFAULT); +const Vector3D DEPRECATED(Grad(const Field3D &f, + CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z)); + +/// Perpendicular gradient of scalar field \p f +/// +/// result.x = df/dx - g_12/(JB)^2 df/dy +/// result.y = 0 +/// result.z = df/dz - g_23/(JB)^2 df/dy +/// +/// @param[in] f The field to differentiate +/// @param[in] outloc The cell location where the result is desired +/// +const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// Perpendicular gradient of scalar field \p f /// @@ -62,10 +73,10 @@ const Vector3D Grad(const Field3D &f, /// @param[in] outloc_y The cell location where the Y component should be defined /// @param[in] outloc_z The cell location where the Z component should be defined /// -const Vector3D Grad_perp(const Field3D &f, - CELL_LOC outloc_x = CELL_DEFAULT, - CELL_LOC outloc_y = CELL_DEFAULT, - CELL_LOC outloc_z = CELL_DEFAULT); +const Vector3D DEPRECATED(Grad_perp(const Field3D &f, + CELL_LOC outloc_x, + CELL_LOC outloc_y, + CELL_LOC outloc_z)); /// Divergence of a vector \p v, returning a scalar /// @@ -87,8 +98,8 @@ const Field3D Div(const Vector3D &v, const Field3D &f); /// const Vector2D Curl(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); const Vector3D Curl(const Vector3D &v, CELL_LOC outloc = CELL_DEFAULT); -const Vector3D Curl(const Vector3D &v, - CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z); +const Vector3D DEPRECATED(Curl(const Vector3D &v, + CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z)); // Upwinding routines diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 10dda46e14..852d5e2103 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -63,8 +63,8 @@ const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { return result; } -const Vector3D DEPRECATED(Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, - CELL_LOC outloc_z)) { +const Vector3D Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z) { // Note no Vector2D equivalent to this three location overload TRACE("Grad( Field3D )"); @@ -106,8 +106,8 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc) { return result; } -const Vector3D DEPRECATED(Grad_perp(const Field3D &f, CELL_LOC outloc_x, - CELL_LOC outloc_y, CELL_LOC outloc_z)) { +const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z) { TRACE("Grad_perp( Field3D )"); ASSERT1(outloc_x == outloc_y && outloc_x == outloc_z); ASSERT1(outloc_x == CELL_DEFAULT || outloc_x == f.getLocation()); @@ -294,8 +294,8 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { return result; } -const Vector3D DEPRECATED(Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, - CELL_LOC outloc_z)) { +const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z) { TRACE("Curl( Vector3D )"); ASSERT1(outloc_x == outloc_y && outloc_x == outloc_z); return Curl(v, outloc_x); From 2c863fa88cf43fdc2ef85effd92a390826da998e Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 10 Oct 2018 16:20:57 +0100 Subject: [PATCH 32/69] Clear up language about parallelisation directions --- manual/sphinx/user_docs/advanced_install.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index bf97738e56..6f024075a3 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -265,7 +265,8 @@ BOUT++ can make use of OpenMP parallelism. To enable OpenMP, use the OpenMP can be used to parallelise in more directions than can be achieved with MPI alone. For example, it is currently difficult to -parallelise over the X, Z plane using pure MPI if FCI is used. +parallelise in X using pure MPI if FCI is used, and impossible to +parallelise at all in Z with pure MPI. OpenMP is in a large number of places now, such that a decent speed-up can be achieved with OpenMP alone. Hybrid parallelisation with both From f9ea8babc9fee7b6429c3e3870ee7edd93a96b87 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 10 Oct 2018 16:45:32 +0100 Subject: [PATCH 33/69] Rename Mesh::coordinates -> Mesh::getCoordinates; deprecate old name More consistent naming --- .../bout_runners_example/diffusion_3D.cxx | 4 +-- examples/laplacexy/alfven-wave/alfven.cxx | 2 +- examples/laplacexy/laplace_perp/test.cxx | 2 +- examples/orszag-tang/mhd.cxx | 2 +- examples/tokamak-2fluid/2fluid.cxx | 2 +- include/bout/mesh.hxx | 6 +++- src/field/field.cxx | 4 +-- src/field/fieldgenerators.cxx | 2 +- src/field/vecops.cxx | 28 +++++++++---------- src/field/vector2d.cxx | 26 ++++++++--------- src/field/vector3d.cxx | 28 +++++++++---------- .../laplace/impls/cyclic/cyclic_laplace.cxx | 4 +-- .../impls/multigrid/multigrid_laplace.cxx | 4 +-- .../laplace/impls/naulin/naulin_laplace.cxx | 2 +- src/invert/laplace/impls/pdd/pdd.cxx | 2 +- .../laplace/impls/petsc/petsc_laplace.cxx | 4 +-- .../laplace/impls/serial_band/serial_band.cxx | 2 +- .../laplace/impls/serial_tri/serial_tri.cxx | 2 +- .../laplace/impls/shoot/shoot_laplace.cxx | 2 +- src/invert/laplace/impls/spt/spt.cxx | 2 +- src/invert/laplace/invert_laplace.cxx | 10 +++---- src/invert/laplacexy/laplacexy.cxx | 2 +- .../impls/cyclic/laplacexz-cyclic.cxx | 2 +- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 2 +- src/invert/parderiv/impls/cyclic/cyclic.cxx | 2 +- src/invert/parderiv/impls/serial/serial.cxx | 2 +- src/mesh/boundary_standard.cxx | 2 +- src/mesh/data/gridfromfile.cxx | 2 +- src/mesh/impls/bout/boutmesh.cxx | 2 +- src/mesh/mesh.cxx | 2 +- src/mesh/parallel/fci.cxx | 2 +- src/mesh/parallel/shiftedmetric.cxx | 4 +-- tests/MMS/GBS/gbs.cxx | 2 +- tests/MMS/advection/advection.cxx | 2 +- tests/MMS/diffusion/diffusion.cxx | 2 +- tests/MMS/diffusion2/diffusion.cxx | 2 +- tests/MMS/elm-pb/elm_pb.cxx | 4 +-- tests/MMS/fieldalign/fieldalign.cxx | 2 +- tests/MMS/hw/hw.cxx | 4 +-- tests/MMS/laplace/laplace.cxx | 4 +-- tests/MMS/spatial/advection/advection.cxx | 2 +- tests/MMS/spatial/diffusion/diffusion.cxx | 2 +- tests/MMS/tokamak/tokamak.cxx | 4 +-- tests/MMS/wave-1d/wave.cxx | 4 +-- .../test-drift-instability/2fluid.cxx | 2 +- tests/integrated/test-fci-slab/fci_slab.cxx | 4 +-- .../test-interchange-instability/2fluid.cxx | 2 +- .../test_multigrid_laplace.cxx | 22 +++++++-------- .../test_naulin_laplace.cxx | 16 +++++------ 49 files changed, 124 insertions(+), 120 deletions(-) diff --git a/examples/bout_runners_example/diffusion_3D.cxx b/examples/bout_runners_example/diffusion_3D.cxx index cd96607715..670472eb99 100644 --- a/examples/bout_runners_example/diffusion_3D.cxx +++ b/examples/bout_runners_example/diffusion_3D.cxx @@ -60,8 +60,8 @@ int physics_init(bool restarting) { // The boundary lies (1/2)*dx away from the last point As there // are 2 boundaries there will effectively add one more line // segment in the domain. Hence - mesh->coordinates()->dx = Lx/(internal_x_points); - mesh->coordinates()->dy = Ly/(internal_y_points); + mesh->getCoordinates()->dx = Lx/(internal_x_points); + mesh->getCoordinates()->dy = Ly/(internal_y_points); } // ************************************************************************ diff --git a/examples/laplacexy/alfven-wave/alfven.cxx b/examples/laplacexy/alfven-wave/alfven.cxx index 92a0b267b6..8bac88f844 100644 --- a/examples/laplacexy/alfven-wave/alfven.cxx +++ b/examples/laplacexy/alfven-wave/alfven.cxx @@ -170,7 +170,7 @@ class Alfven : public PhysicsModel { Field2D Rxy, Bpxy, Btxy, hthe, sinty; GRID_LOAD5(Rxy, Bpxy, Btxy, hthe, sinty); // Load metrics - Coordinates *coord = mesh->coordinates(); // Metric tensor + Coordinates *coord = mesh->getCoordinates(); // Metric tensor // Checking for dpsi and qinty used in BOUT grids Field2D dx; diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index a4b561d027..0ed64932b6 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -20,7 +20,7 @@ int main(int argc, char** argv) { mesh->get(hthe, "hthe"); // m mesh->get(I, "sinty");// m^-2 T^-1 - Coordinates *coord = mesh->coordinates(); + Coordinates *coord = mesh->getCoordinates(); // Calculate metrics coord->g11 = SQ(Rxy * Bpxy); diff --git a/examples/orszag-tang/mhd.cxx b/examples/orszag-tang/mhd.cxx index 60870bac4a..eee6c16205 100644 --- a/examples/orszag-tang/mhd.cxx +++ b/examples/orszag-tang/mhd.cxx @@ -47,7 +47,7 @@ class MHD : public PhysicsModel { B.covariant = false; // evolve contravariant components bout_solve(B, "B"); - Coordinates *coord = mesh->coordinates(); + Coordinates *coord = mesh->getCoordinates(); output.write("dx[0,0] = %e, dy[0,0] = %e, dz = %e\n", coord->dx(0, 0), coord->dy(0, 0), coord->dz); diff --git a/examples/tokamak-2fluid/2fluid.cxx b/examples/tokamak-2fluid/2fluid.cxx index 7b95ddcca3..93f55fa3e2 100644 --- a/examples/tokamak-2fluid/2fluid.cxx +++ b/examples/tokamak-2fluid/2fluid.cxx @@ -101,7 +101,7 @@ class TwoFluid : public PhysicsModel { Field2D I; // Shear factor // Get the coordinate system - coord = mesh->coordinates(); + coord = mesh->getCoordinates(); output.write("Solving 6-variable 2-fluid equations\n"); diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index f3682c9dbd..08860857e0 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -430,7 +430,7 @@ class Mesh { bool IncIntShear; ///< Include integrated shear (if shifting X) /// Coordinate system - Coordinates *coordinates(const CELL_LOC location = CELL_CENTRE) { + Coordinates *getCoordinates(const CELL_LOC location = CELL_CENTRE) { if (coords_map.count(location)) { // True branch most common, returns immediately return coords_map[location].get(); } else if (location == CELL_DEFAULT) { @@ -444,6 +444,10 @@ class Mesh { } } + Coordinates *DEPRECATED(coordinates(const CELL_LOC location = CELL_CENTRE)) { + return getCoordinates(location); + } + // First derivatives in index space // Implemented in src/mesh/index_derivs.hxx diff --git a/src/field/field.cxx b/src/field/field.cxx index e3aa850248..365294d8df 100644 --- a/src/field/field.cxx +++ b/src/field/field.cxx @@ -60,14 +60,14 @@ Coordinates *Field::getCoordinates() const { if (fieldCoordinates) { return fieldCoordinates; } else { - fieldCoordinates = getMesh()->coordinates(getLocation()); + fieldCoordinates = getMesh()->getCoordinates(getLocation()); return fieldCoordinates; } } Coordinates *Field::getCoordinates(CELL_LOC loc) const { if (loc == CELL_DEFAULT) return getCoordinates(); - return getMesh()->coordinates(loc); + return getMesh()->getCoordinates(loc); } int Field::getNx() const{ diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 2eaeacbc2a..f2d7ecf430 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -160,7 +160,7 @@ BoutReal FieldBallooning::generate(double x, double y, double z, double t) { throw BoutException("ballooning function ball_n less than 1"); BoutReal ts; // Twist-shift angle - Coordinates* coords = mesh->coordinates(); + Coordinates* coords = mesh->getCoordinates(); // Need to find the nearest flux surface (x index) // This assumes that mesh->GlobalX is linear in x index diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 6699ba03ad..f8f97f9af7 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -88,8 +88,8 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc_x, if(outloc_z == CELL_DEFAULT) outloc_z = f.getLocation(); - Coordinates* metric_x = mesh->coordinates(outloc_x); - Coordinates* metric_z = mesh->coordinates(outloc_z); + Coordinates* metric_x = mesh->getCoordinates(outloc_x); + Coordinates* metric_z = mesh->getCoordinates(outloc_z); result.x = DDX(f, outloc_x) - metric_x->g_12*DDY(f, outloc_x) / SQ(metric_x->J * metric_x->Bxy); result.y = 0.0; @@ -110,7 +110,7 @@ const Field2D Div(const Vector2D &v, CELL_LOC outloc) { Mesh *localmesh = v.x.getMesh(); Field2D result(localmesh); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); // get contravariant components of v Vector2D vcn = v; @@ -130,7 +130,7 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { Mesh *localmesh = v.x.getMesh(); Field3D result(localmesh); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); if(outloc == CELL_DEFAULT) outloc = CELL_CENTRE; @@ -158,7 +158,7 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { Mesh *localmesh = f.getMesh(); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); // get contravariant components of v Vector2D vcn = v; @@ -179,7 +179,7 @@ const Field3D Div(const Vector3D &v, const Field3D &f, DIFF_METHOD method, CELL_ Mesh *localmesh = f.getMesh(); Field3D result(localmesh); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); if(outloc == CELL_DEFAULT) outloc = CELL_CENTRE; @@ -213,7 +213,7 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { TRACE("Curl( Vector2D )"); Mesh *localmesh = v.x.getMesh(); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); // Get covariant components of v Vector2D vco = v; @@ -240,7 +240,7 @@ const Vector3D Curl(const Vector3D &v, Mesh *localmesh = v.x.getMesh(); - Coordinates* metric_z = localmesh->coordinates(outloc_z); + Coordinates* metric_z = localmesh->getCoordinates(outloc_z); // Get covariant components of v Vector3D vco = v; @@ -248,8 +248,8 @@ const Vector3D Curl(const Vector3D &v, // get components (curl(v))^j Vector3D result(localmesh); - result.x = (DDY(vco.z, outloc_x) - DDZ(vco.y, outloc_x))/localmesh->coordinates(outloc_x)->J; - result.y = (DDZ(vco.x, outloc_y) - DDX(vco.z, outloc_y))/localmesh->coordinates(outloc_y)->J; + result.x = (DDY(vco.z, outloc_x) - DDZ(vco.y, outloc_x))/localmesh->getCoordinates(outloc_x)->J; + result.y = (DDZ(vco.x, outloc_y) - DDX(vco.z, outloc_y))/localmesh->getCoordinates(outloc_y)->J; result.z = (DDX(vco.y, outloc_z) - DDY(vco.x, outloc_z))/metric_z->J; // Coordinate torsion @@ -333,7 +333,7 @@ const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, const CELL_LOC o Mesh *localmesh = v.x.getMesh(); Vector2D result(localmesh); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); Vector2D vcn = v; vcn.toContravariant(); @@ -385,7 +385,7 @@ const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, const CELL_LOC o TRACE("V_dot_Grad( Vector2D , Vector3D )"); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); Vector2D vcn = v; vcn.toContravariant(); @@ -435,7 +435,7 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, const CELL_LOC o TRACE("V_dot_Grad( Vector3D , Vector2D )"); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); Vector3D vcn = v; vcn.toContravariant(); @@ -485,7 +485,7 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, const CELL_LOC o TRACE("V_dot_Grad( Vector3D , Vector3D )"); - Coordinates *metric = localmesh->coordinates(outloc); + Coordinates *metric = localmesh->getCoordinates(outloc); Vector3D vcn = v; vcn.toContravariant(); diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index e94e26b512..606208a17c 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -61,13 +61,13 @@ void Vector2D::toCovariant() { Coordinates *metric_x, *metric_y, *metric_z; if (location == CELL_VSHIFT) { - metric_x = localmesh->coordinates(CELL_XLOW); - metric_y = localmesh->coordinates(CELL_YLOW); - metric_z = localmesh->coordinates(CELL_ZLOW); + metric_x = localmesh->getCoordinates(CELL_XLOW); + metric_y = localmesh->getCoordinates(CELL_YLOW); + metric_z = localmesh->getCoordinates(CELL_ZLOW); } else { - metric_x = localmesh->coordinates(location); - metric_y = localmesh->coordinates(location); - metric_z = localmesh->coordinates(location); + metric_x = localmesh->getCoordinates(location); + metric_y = localmesh->getCoordinates(location); + metric_z = localmesh->getCoordinates(location); } // multiply by g_{ij} @@ -91,13 +91,13 @@ void Vector2D::toContravariant() { Coordinates *metric_x, *metric_y, *metric_z; if (location == CELL_VSHIFT) { - metric_x = localmesh->coordinates(CELL_XLOW); - metric_y = localmesh->coordinates(CELL_YLOW); - metric_z = localmesh->coordinates(CELL_ZLOW); + metric_x = localmesh->getCoordinates(CELL_XLOW); + metric_y = localmesh->getCoordinates(CELL_YLOW); + metric_z = localmesh->getCoordinates(CELL_ZLOW); } else { - metric_x = localmesh->coordinates(location); - metric_y = localmesh->coordinates(location); - metric_z = localmesh->coordinates(location); + metric_x = localmesh->getCoordinates(location); + metric_y = localmesh->getCoordinates(location); + metric_z = localmesh->getCoordinates(location); } // multiply by g_{ij} @@ -336,7 +336,7 @@ const Field2D Vector2D::operator*(const Vector2D &rhs) const { result = x*rhs.x + y*rhs.y + z*rhs.z; }else { // Both are covariant or contravariant - Coordinates *metric = localmesh->coordinates(location); + Coordinates *metric = localmesh->getCoordinates(location); if(covariant) { // Both covariant diff --git a/src/field/vector3d.cxx b/src/field/vector3d.cxx index c7df254d0e..0451c91a35 100644 --- a/src/field/vector3d.cxx +++ b/src/field/vector3d.cxx @@ -62,13 +62,13 @@ void Vector3D::toCovariant() { Coordinates *metric_x, *metric_y, *metric_z; if (location == CELL_VSHIFT) { - metric_x = localmesh->coordinates(CELL_XLOW); - metric_y = localmesh->coordinates(CELL_YLOW); - metric_z = localmesh->coordinates(CELL_ZLOW); + metric_x = localmesh->getCoordinates(CELL_XLOW); + metric_y = localmesh->getCoordinates(CELL_YLOW); + metric_z = localmesh->getCoordinates(CELL_ZLOW); } else { - metric_x = localmesh->coordinates(location); - metric_y = localmesh->coordinates(location); - metric_z = localmesh->coordinates(location); + metric_x = localmesh->getCoordinates(location); + metric_y = localmesh->getCoordinates(location); + metric_z = localmesh->getCoordinates(location); } // multiply by g_{ij} @@ -91,13 +91,13 @@ void Vector3D::toContravariant() { Coordinates *metric_x, *metric_y, *metric_z; if (location == CELL_VSHIFT) { - metric_x = localmesh->coordinates(CELL_XLOW); - metric_y = localmesh->coordinates(CELL_YLOW); - metric_z = localmesh->coordinates(CELL_ZLOW); + metric_x = localmesh->getCoordinates(CELL_XLOW); + metric_y = localmesh->getCoordinates(CELL_YLOW); + metric_z = localmesh->getCoordinates(CELL_ZLOW); } else { - metric_x = localmesh->coordinates(location); - metric_y = localmesh->coordinates(location); - metric_z = localmesh->coordinates(location); + metric_x = localmesh->getCoordinates(location); + metric_y = localmesh->getCoordinates(location); + metric_z = localmesh->getCoordinates(location); } // multiply by g_{ij} @@ -325,7 +325,7 @@ Vector3D & Vector3D::operator/=(const Field3D &rhs) v1 lco = lhs; \ lco.toCovariant(); \ \ - Coordinates *metric = localmesh->coordinates(lhs.getLocation()); \ + Coordinates *metric = localmesh->getCoordinates(lhs.getLocation()); \ \ /* calculate contravariant components of cross-product */ \ result.x = (lco.y * rco.z - lco.z * rco.y) / metric->J; \ @@ -436,7 +436,7 @@ const Field3D Vector3D::operator*(const Vector3D &rhs) const { }else { // Both are covariant or contravariant - Coordinates *metric = mesh->coordinates(location); + Coordinates *metric = mesh->getCoordinates(location); if(covariant) { // Both covariant diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index 7070232f85..223617de3c 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -94,7 +94,7 @@ const FieldPerp LaplaceCyclic::solve(const FieldPerp &rhs, const FieldPerp &x0) FieldPerp x(mesh); // Result x.allocate(); - Coordinates *coord = mesh->coordinates(location); + Coordinates *coord = mesh->getCoordinates(location); int jy = rhs.getIndex(); // Get the Y index x.setIndex(jy); @@ -257,7 +257,7 @@ const Field3D LaplaceCyclic::solve(const Field3D &rhs, const Field3D &x0) { Field3D x(mesh); // Result x.allocate(); - Coordinates *coord = mesh->coordinates(); + Coordinates *coord = mesh->getCoordinates(); // Get the width of the boundary diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index 5170c0d031..17e0e6b127 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -208,7 +208,7 @@ const FieldPerp LaplaceMultigrid::solve(const FieldPerp &b_in, const FieldPerp & Mesh *mesh = b_in.getMesh(); BoutReal t0,t1; - Coordinates *coords = mesh->coordinates(location); + Coordinates *coords = mesh->getCoordinates(location); yindex = b_in.getIndex(); int level = kMG->mglevel-1; @@ -554,7 +554,7 @@ void LaplaceMultigrid::generateMatrixF(int level) { // Set (fine-level) matrix entries - Coordinates *coords = mesh->coordinates(location); + Coordinates *coords = mesh->getCoordinates(location); BoutReal *mat; mat = kMG->matmg[level]; int llx = kMG->lnx[level]; diff --git a/src/invert/laplace/impls/naulin/naulin_laplace.cxx b/src/invert/laplace/impls/naulin/naulin_laplace.cxx index faad970129..fa065b0f12 100644 --- a/src/invert/laplace/impls/naulin/naulin_laplace.cxx +++ b/src/invert/laplace/impls/naulin/naulin_laplace.cxx @@ -172,7 +172,7 @@ const Field3D LaplaceNaulin::solve(const Field3D &rhs, const Field3D &x0) { ASSERT1(Acoef.getLocation() == location); Mesh *mesh = rhs.getMesh(); - Coordinates *coords = mesh->coordinates(location); + Coordinates *coords = mesh->getCoordinates(location); Field3D x(x0); // Result Field3D rhsOverD = rhs/Dcoef; diff --git a/src/invert/laplace/impls/pdd/pdd.cxx b/src/invert/laplace/impls/pdd/pdd.cxx index 2fe65814f8..f71b551ccb 100644 --- a/src/invert/laplace/impls/pdd/pdd.cxx +++ b/src/invert/laplace/impls/pdd/pdd.cxx @@ -160,7 +160,7 @@ void LaplacePDD::start(const FieldPerp &b, PDD_data &data) { /// Create the matrices to be inverted (one for each z point) - BoutReal kwaveFactor = 2.0 * PI / mesh->coordinates(location)->zlength(); + BoutReal kwaveFactor = 2.0 * PI / mesh->getCoordinates(location)->zlength(); /// Set matrix elements for (int kz = 0; kz <= maxmode; kz++) { diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index e7bff57309..27f01a3161 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -361,7 +361,7 @@ const FieldPerp LaplacePetsc::solve(const FieldPerp &b, const FieldPerp &x0) { #endif // Get the metric tensor - Coordinates* coord = mesh->coordinates(location); + Coordinates* coord = mesh->getCoordinates(location); int y = b.getIndex(); // Get the Y index sol.setIndex(y); // Initialize the solution field. @@ -935,7 +935,7 @@ void LaplacePetsc::Element(int i, int x, int z, */ void LaplacePetsc::Coeffs( int x, int y, int z, BoutReal &coef1, BoutReal &coef2, BoutReal &coef3, BoutReal &coef4, BoutReal &coef5 ) { - Coordinates *coord = mesh->coordinates(location); // Get metric tensor + Coordinates *coord = mesh->getCoordinates(location); // Get metric tensor coef1 = coord->g11(x,y); // X 2nd derivative coefficient coef2 = coord->g33(x,y); // Z 2nd derivative coefficient diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index d4871d38ec..f2dfa04a66 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -86,7 +86,7 @@ const FieldPerp LaplaceSerialBand::solve(const FieldPerp &b, const FieldPerp &x0 int jy = b.getIndex(); x.setIndex(jy); - Coordinates *coord = mesh->coordinates(location); + Coordinates *coord = mesh->getCoordinates(location); int ncz = mesh->LocalNz; int ncx = mesh->LocalNx-1; diff --git a/src/invert/laplace/impls/serial_tri/serial_tri.cxx b/src/invert/laplace/impls/serial_tri/serial_tri.cxx index 8f36b14e8e..7080f18b31 100644 --- a/src/invert/laplace/impls/serial_tri/serial_tri.cxx +++ b/src/invert/laplace/impls/serial_tri/serial_tri.cxx @@ -82,7 +82,7 @@ const FieldPerp LaplaceSerialTri::solve(const FieldPerp &b, const FieldPerp &x0) int ncz = mesh->LocalNz; // No of z pnts int ncx = mesh->LocalNx; // No of x pnts - BoutReal kwaveFactor = 2.0 * PI / mesh->coordinates(location)->zlength(); + BoutReal kwaveFactor = 2.0 * PI / mesh->getCoordinates(location)->zlength(); // Setting the width of the boundary. // NOTE: The default is a width of 2 guard cells diff --git a/src/invert/laplace/impls/shoot/shoot_laplace.cxx b/src/invert/laplace/impls/shoot/shoot_laplace.cxx index 2470b0ab52..0db36a3c65 100644 --- a/src/invert/laplace/impls/shoot/shoot_laplace.cxx +++ b/src/invert/laplace/impls/shoot/shoot_laplace.cxx @@ -76,7 +76,7 @@ const FieldPerp LaplaceShoot::solve(const FieldPerp &rhs) { int jy = rhs.getIndex(); // Get the Y index x.setIndex(jy); - Coordinates *coord = mesh->coordinates(location); + Coordinates *coord = mesh->getCoordinates(location); // Get the width of the boundary diff --git a/src/invert/laplace/impls/spt/spt.cxx b/src/invert/laplace/impls/spt/spt.cxx index 5c5b019186..b7867a87d5 100644 --- a/src/invert/laplace/impls/spt/spt.cxx +++ b/src/invert/laplace/impls/spt/spt.cxx @@ -288,7 +288,7 @@ int LaplaceSPT::start(const FieldPerp &b, SPT_data &data) { data.bk(kz, ix) = dc1d[kz]; } - BoutReal kwaveFactor = 2.0 * PI / mesh->coordinates(location)->zlength(); + BoutReal kwaveFactor = 2.0 * PI / mesh->getCoordinates(location)->zlength(); /// Set matrix elements for (int kz = 0; kz <= maxmode; kz++) { diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index 4853b9f501..c9478eb20d 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -80,7 +80,7 @@ Laplacian::Laplacian(Options *options, const CELL_LOC loc) : location(loc) { OPTION(options, low_mem, false); OPTION(options, nonuniform, - mesh->coordinates(location)->non_uniform); // Default is the mesh setting + mesh->getCoordinates(location)->non_uniform); // Default is the mesh setting OPTION(options, all_terms, true); // Include first derivative terms @@ -249,7 +249,7 @@ void Laplacian::tridagCoefs(int jx, int jy, int jz, ASSERT1(ccoef == nullptr || ccoef->getLocation() == loc); ASSERT1(d == nullptr || d->getLocation() == loc); - Coordinates *coord = mesh->coordinates(loc); + Coordinates *coord = mesh->getCoordinates(loc); BoutReal kwave=jz*2.0*PI/coord->zlength(); // wave number is 1/[rad] @@ -296,7 +296,7 @@ void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, BoutReal coef1, coef2, coef3, coef4, coef5; - Coordinates *coord = mesh->coordinates(loc); + Coordinates *coord = mesh->getCoordinates(loc); coef1=coord->g11(jx,jy); ///< X 2nd derivative coefficient coef2=coord->g33(jx,jy); ///< Z 2nd derivative coefficient @@ -361,7 +361,7 @@ void Laplacian::tridagMatrix(dcomplex **avec, dcomplex **bvec, dcomplex **cvec, ASSERT1(ccoef->getLocation() == location); ASSERT1(d->getLocation() == location); - Coordinates *coord = mesh->coordinates(location); + Coordinates *coord = mesh->getCoordinates(location); BOUT_OMP(parallel for) for(int kz = 0; kz <= maxmode; kz++) { @@ -426,7 +426,7 @@ void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, int xs = 0; // xstart set to the start of x on this processor (including ghost points) int xe = mesh->LocalNx-1; // xend set to the end of x on this processor (including ghost points) - Coordinates *coord = mesh->coordinates(location); + Coordinates *coord = mesh->getCoordinates(location); // Do not want boundary cells if x is periodic for cyclic solver. Only other solver which // works with periodicX is serial_tri, which uses includeguards==true, so the below isn't called. diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index 966d78508d..6793880b8d 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -291,7 +291,7 @@ LaplaceXY::LaplaceXY(Mesh *m, Options *opt, const CELL_LOC loc) : mesh(m), locat void LaplaceXY::setCoefs(const Field2D &A, const Field2D &B) { Timer timer("invert"); - Coordinates *coords = mesh->coordinates(location); + Coordinates *coords = mesh->getCoordinates(location); ////////////////////////////////////////////////// // Set Matrix elements diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 6d98fba3e2..8567b0c740 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -62,7 +62,7 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { // Set coefficients - Coordinates *coord = mesh->coordinates(location); + Coordinates *coord = mesh->getCoordinates(location); // NOTE: For now the X-Z terms are omitted, so check that they are small ASSERT2(max(abs(coord->g13)) < 1e-5); diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index dbe916b7fe..6095919064 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -368,7 +368,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // // (1/J) d/dx ( A * J * g11 d/dx ) + (1/J) d/dz ( A * J * g33 d/dz ) + B - Coordinates *coords = mesh->coordinates(location); + Coordinates *coords = mesh->getCoordinates(location); // NOTE: For now the X-Z terms are omitted, so check that they are small ASSERT2(max(abs(coords->g13)) < 1e-5); diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index bedfb8367d..29d4bc8dde 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -89,7 +89,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { result.allocate(); result.setLocation(f.getLocation()); - Coordinates *coord = mesh->coordinates(f.getLocation()); + Coordinates *coord = mesh->getCoordinates(f.getLocation()); // Create cyclic reduction object CyclicReduce *cr = diff --git a/src/invert/parderiv/impls/serial/serial.cxx b/src/invert/parderiv/impls/serial/serial.cxx index 1ba7b5b36c..7cc0fd128e 100644 --- a/src/invert/parderiv/impls/serial/serial.cxx +++ b/src/invert/parderiv/impls/serial/serial.cxx @@ -67,7 +67,7 @@ const Field3D InvertParSerial::solve(const Field3D &f) { result.allocate(); result.setLocation(f.getLocation()); - Coordinates *coord = mesh->coordinates(f.getLocation()); + Coordinates *coord = mesh->getCoordinates(f.getLocation()); // Loop over flux-surfaces SurfaceIter surf(mesh); diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index c82d8f7c0f..44f910d74d 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -2686,7 +2686,7 @@ void BoundaryDivCurl::apply(Vector3D &var) { int jx, jy, jz, jzp, jzm; BoutReal tmp; - Coordinates *metric = mesh->coordinates(var.getLocation()); + Coordinates *metric = mesh->getCoordinates(var.getLocation()); int ncz = mesh->LocalNz; diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index 2a2758525e..59fb515271 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -407,7 +407,7 @@ bool GridFile::readgrid_3dvar_fft(Mesh *m, const string &name, /// but don't do it yet as we don't assert that m == var.getMesh() /// Expect the assertion to be true, in which case we probably don't /// need to pass m as can just use var.getMesh() - BoutReal zlength = m->coordinates(var.getLocation())->zlength(); + BoutReal zlength = m->getCoordinates(var.getLocation())->zlength(); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi diff --git a/src/mesh/impls/bout/boutmesh.cxx b/src/mesh/impls/bout/boutmesh.cxx index 1ebbed117d..e4f3c487a0 100644 --- a/src/mesh/impls/bout/boutmesh.cxx +++ b/src/mesh/impls/bout/boutmesh.cxx @@ -2553,5 +2553,5 @@ void BoutMesh::outputVars(Datafile &file) { file.add(jyseps2_1, "jyseps2_1", false); file.add(jyseps2_2, "jyseps2_2", false); - coordinates()->outputVars(file); + getCoordinates()->outputVars(file); } diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index 34b1c7709f..9e5fa92170 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -331,7 +331,7 @@ std::shared_ptr Mesh::createDefaultCoordinates(const CELL_LOC locat return std::make_shared(this); else // Interpolate coordinates from CELL_CENTRE version - return std::make_shared(this, location, coordinates(CELL_CENTRE)); + return std::make_shared(this, location, getCoordinates(CELL_CENTRE)); } diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 63f53856a7..25002ffed3 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -137,7 +137,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) int ncz = mesh.LocalNz; BoutReal t_x, t_z; - Coordinates &coord = *(mesh.coordinates()); + Coordinates &coord = *(mesh.getCoordinates()); for (int x = mesh.xstart; x <= mesh.xend; x++) { for (int y = mesh.ystart; y <= mesh.yend; y++) { diff --git a/src/mesh/parallel/shiftedmetric.cxx b/src/mesh/parallel/shiftedmetric.cxx index 13067fe07c..45355dfdcc 100644 --- a/src/mesh/parallel/shiftedmetric.cxx +++ b/src/mesh/parallel/shiftedmetric.cxx @@ -33,7 +33,7 @@ ShiftedMetric::ShiftedMetric(Mesh &m) : mesh(m), zShift(&m) { //not change once we've been created so precalculate the complex //phases used in transformations int nmodes = mesh.LocalNz/2 + 1; - BoutReal zlength = mesh.coordinates()->zlength(); + BoutReal zlength = mesh.getCoordinates()->zlength(); //Allocate storage for complex intermediate cmplx.resize(nmodes); @@ -195,7 +195,7 @@ void ShiftedMetric::shiftZ(const BoutReal *in, int len, BoutReal zangle, BoutRe rfft(in, len, &cmplxLoc[0]); // Apply phase shift - BoutReal zlength = mesh.coordinates()->zlength(); + BoutReal zlength = mesh.getCoordinates()->zlength(); for(int jz=1;jzcoordinates(); + coords = mesh->getCoordinates(); // Switches in model section Options *optgbs = opt->getSection("GBS"); diff --git a/tests/MMS/advection/advection.cxx b/tests/MMS/advection/advection.cxx index 178bd94961..ee6d93ff34 100644 --- a/tests/MMS/advection/advection.cxx +++ b/tests/MMS/advection/advection.cxx @@ -18,7 +18,7 @@ class AdvectMMS : public PhysicsModel { } int rhs(BoutReal time) { mesh->communicate(f); - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); g = FieldFactory::get()->create3D("g:solution", Options::getRoot(), mesh, CELL_CENTRE, time); diff --git a/tests/MMS/diffusion/diffusion.cxx b/tests/MMS/diffusion/diffusion.cxx index dba3b21515..b89a0b0e6a 100644 --- a/tests/MMS/diffusion/diffusion.cxx +++ b/tests/MMS/diffusion/diffusion.cxx @@ -28,7 +28,7 @@ int physics_init(bool restarting) { // Get the options Options *meshoptions = Options::getRoot()->getSection("mesh"); - coord = mesh->coordinates(); + coord = mesh->getCoordinates(); meshoptions->get("Lx",Lx,1.0); meshoptions->get("Ly",Ly,1.0); diff --git a/tests/MMS/diffusion2/diffusion.cxx b/tests/MMS/diffusion2/diffusion.cxx index 1071ab5f85..4a0fffbd45 100644 --- a/tests/MMS/diffusion2/diffusion.cxx +++ b/tests/MMS/diffusion2/diffusion.cxx @@ -13,7 +13,7 @@ BoutReal Lx, Ly, Lz; int physics_init(bool restarting) { // Get the options Options *meshoptions = Options::getRoot()->getSection("mesh"); - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); meshoptions->get("Lx",Lx,1.0); meshoptions->get("Ly",Ly,1.0); diff --git a/tests/MMS/elm-pb/elm_pb.cxx b/tests/MMS/elm-pb/elm_pb.cxx index c0750e018d..3ae0e27594 100644 --- a/tests/MMS/elm-pb/elm_pb.cxx +++ b/tests/MMS/elm-pb/elm_pb.cxx @@ -153,7 +153,7 @@ int physics_init(bool restarting) { mesh->get(hthe, "hthe"); // m mesh->get(I, "sinty");// m^-2 T^-1 - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); ////////////////////////////////////////////////////////////// // Read parameters from the options file @@ -505,7 +505,7 @@ int physics_run(BoutReal t) { // Perform communications mesh->communicate(comms); - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); //////////////////////////////////////////// // Transitions from 0 in core to 1 in vacuum diff --git a/tests/MMS/fieldalign/fieldalign.cxx b/tests/MMS/fieldalign/fieldalign.cxx index 48f84b3857..ccd20ca7fa 100644 --- a/tests/MMS/fieldalign/fieldalign.cxx +++ b/tests/MMS/fieldalign/fieldalign.cxx @@ -13,7 +13,7 @@ class FieldAlign : public PhysicsModel { } int rhs(BoutReal t) { - Coordinates *metric = mesh->coordinates(); + Coordinates *metric = mesh->getCoordinates(); mesh->communicate(f); f.applyBoundary(t); diff --git a/tests/MMS/hw/hw.cxx b/tests/MMS/hw/hw.cxx index 5e79e7ea7f..20ca7d6c8c 100644 --- a/tests/MMS/hw/hw.cxx +++ b/tests/MMS/hw/hw.cxx @@ -36,8 +36,8 @@ int physics_init(bool restart) { /*this assumes equidistant grid*/ int nguard = mesh->xstart; - mesh->coordinates()->dx = Lx/(mesh->GlobalNx - 2*nguard); - mesh->coordinates()->dz = TWOPI*Lx/(mesh->LocalNz); + mesh->getCoordinates()->dx = Lx/(mesh->GlobalNx - 2*nguard); + mesh->getCoordinates()->dz = TWOPI*Lx/(mesh->LocalNz); ///// SOLVE_FOR2(n, vort); diff --git a/tests/MMS/laplace/laplace.cxx b/tests/MMS/laplace/laplace.cxx index 49a2d57bf5..e762637af1 100644 --- a/tests/MMS/laplace/laplace.cxx +++ b/tests/MMS/laplace/laplace.cxx @@ -20,8 +20,8 @@ int main(int argc, char **argv) { /*this assumes equidistant grid*/ int nguard = mesh->xstart; - mesh->coordinates()->dx = Lx/(mesh->GlobalNx - 2*nguard); - mesh->coordinates()->dz = TWOPI*Lx/(mesh->LocalNz); + mesh->getCoordinates()->dx = Lx/(mesh->GlobalNx - 2*nguard); + mesh->getCoordinates()->dz = TWOPI*Lx/(mesh->LocalNz); ///// // Create a Laplacian inversion solver diff --git a/tests/MMS/spatial/advection/advection.cxx b/tests/MMS/spatial/advection/advection.cxx index 178bd94961..ee6d93ff34 100644 --- a/tests/MMS/spatial/advection/advection.cxx +++ b/tests/MMS/spatial/advection/advection.cxx @@ -18,7 +18,7 @@ class AdvectMMS : public PhysicsModel { } int rhs(BoutReal time) { mesh->communicate(f); - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); g = FieldFactory::get()->create3D("g:solution", Options::getRoot(), mesh, CELL_CENTRE, time); diff --git a/tests/MMS/spatial/diffusion/diffusion.cxx b/tests/MMS/spatial/diffusion/diffusion.cxx index 13aa3089f9..ca673fa8c5 100644 --- a/tests/MMS/spatial/diffusion/diffusion.cxx +++ b/tests/MMS/spatial/diffusion/diffusion.cxx @@ -14,7 +14,7 @@ int physics_init(bool restarting) { // Get the options Options *meshoptions = Options::getRoot()->getSection("mesh"); - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); meshoptions->get("Lx",Lx,1.0); meshoptions->get("Ly",Ly,1.0); diff --git a/tests/MMS/tokamak/tokamak.cxx b/tests/MMS/tokamak/tokamak.cxx index 6e5dbb5386..a917afe960 100644 --- a/tests/MMS/tokamak/tokamak.cxx +++ b/tests/MMS/tokamak/tokamak.cxx @@ -29,7 +29,7 @@ class TokamakMMS : public PhysicsModel { // Test bracket advection operator ddt(advect) = -1e-3*bracket(drive, advect, BRACKET_ARAKAWA) - - 10.*(SQ(SQ(mesh->coordinates()->dx))*D4DX4(advect) + SQ(SQ(mesh->coordinates()->dz))*D4DZ4(advect)); + - 10.*(SQ(SQ(mesh->getCoordinates()->dx))*D4DX4(advect) + SQ(SQ(mesh->getCoordinates()->dz))*D4DZ4(advect)); // Test perpendicular diffusion operator ddt(delp2) = 1e-5*Delp2(delp2); @@ -44,7 +44,7 @@ class TokamakMMS : public PhysicsModel { Field2D Rxy, Bpxy, Btxy, hthe, sinty; GRID_LOAD5(Rxy, Bpxy, Btxy, hthe, sinty); // Load metrics - Coordinates *coords = mesh->coordinates(); + Coordinates *coords = mesh->getCoordinates(); // Checking for dpsi used in BOUT grids Field2D dx; diff --git a/tests/MMS/wave-1d/wave.cxx b/tests/MMS/wave-1d/wave.cxx index 188f1bebdd..d2543a98b1 100644 --- a/tests/MMS/wave-1d/wave.cxx +++ b/tests/MMS/wave-1d/wave.cxx @@ -23,7 +23,7 @@ const Field3D HLL(const Field3D &f, const Field3D &u, BoutReal SL, BoutReal SR) Field3D result; result.allocate(); - Coordinates *coord = mesh->coordinates(); + Coordinates *coord = mesh->getCoordinates(); for(int i=mesh->xstart;i<=mesh->xend;i++) for(int j=mesh->ystart; j<=mesh->yend; j++) @@ -52,7 +52,7 @@ class Wave1D : public PhysicsModel { protected: int init(bool restarting) { // Coordinate system - coord = mesh->coordinates(); + coord = mesh->getCoordinates(); // Get the options Options *meshoptions = Options::getRoot()->getSection("mesh"); diff --git a/tests/integrated/test-drift-instability/2fluid.cxx b/tests/integrated/test-drift-instability/2fluid.cxx index ee0e1faa84..3e55a2c6fb 100644 --- a/tests/integrated/test-drift-instability/2fluid.cxx +++ b/tests/integrated/test-drift-instability/2fluid.cxx @@ -86,7 +86,7 @@ int physics_init(bool restarting) { mesh->get(b0xcv, "bxcv"); // b0xkappa terms // Coordinate system - coord = mesh->coordinates(); + coord = mesh->getCoordinates(); // Load metrics GRID_LOAD(Rxy); diff --git a/tests/integrated/test-fci-slab/fci_slab.cxx b/tests/integrated/test-fci-slab/fci_slab.cxx index d5841a89e4..84ba090355 100644 --- a/tests/integrated/test-fci-slab/fci_slab.cxx +++ b/tests/integrated/test-fci-slab/fci_slab.cxx @@ -12,7 +12,7 @@ class FCISlab : public PhysicsModel { D = 10; - Coordinates *coord = mesh->coordinates(); + Coordinates *coord = mesh->getCoordinates(); mesh->get(coord->g_22, "g_22"); @@ -40,7 +40,7 @@ BOUTMAIN(FCISlab); int FCISlab::rhs(BoutReal time) { mesh->communicate(f,g); - Coordinates *coord = mesh->coordinates(); + Coordinates *coord = mesh->getCoordinates(); f.applyParallelBoundary(time); g.applyParallelBoundary(time); diff --git a/tests/integrated/test-interchange-instability/2fluid.cxx b/tests/integrated/test-interchange-instability/2fluid.cxx index 1376bf1e38..ff1fd8524b 100644 --- a/tests/integrated/test-interchange-instability/2fluid.cxx +++ b/tests/integrated/test-interchange-instability/2fluid.cxx @@ -54,7 +54,7 @@ class Interchange : public PhysicsModel { b0xcv *= -1.0; // NOTE: THIS IS FOR 'OLD' GRID FILES ONLY // Coordinate system - coord = mesh->coordinates(); + coord = mesh->getCoordinates(); // Load metrics GRID_LOAD(Rxy); diff --git a/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx b/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx index e538d6e5e5..0f5f107c5c 100644 --- a/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx +++ b/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx @@ -52,8 +52,8 @@ int main(int argc, char** argv) { BoutReal nx = mesh->GlobalNx-2*mesh->xstart; BoutReal nz = mesh->GlobalNz; - dump.add(mesh->coordinates()->G1,"G1"); - dump.add(mesh->coordinates()->G3,"G3"); + dump.add(mesh->getCoordinates()->G1,"G1"); + dump.add(mesh->getCoordinates()->G3,"G3"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Test 1: zero-value Dirichlet boundaries @@ -231,13 +231,13 @@ int main(int argc, char** argv) { if (mesh->firstX()) for (int k=0;kLocalNz;k++) x0(mesh->xstart-1,mesh->ystart,k) = (f4(mesh->xstart,mesh->ystart,k)-f4(mesh->xstart-1,mesh->ystart,k)) - /mesh->coordinates()->dx(mesh->xstart,mesh->ystart) - /sqrt(mesh->coordinates()->g_11(mesh->xstart,mesh->ystart)); + /mesh->getCoordinates()->dx(mesh->xstart,mesh->ystart) + /sqrt(mesh->getCoordinates()->g_11(mesh->xstart,mesh->ystart)); if (mesh->lastX()) for (int k=0;kLocalNz;k++) x0(mesh->xend+1,mesh->ystart,k) = (f4(mesh->xend+1,mesh->ystart,k)-f4(mesh->xend,mesh->ystart,k)) - /mesh->coordinates()->dx(mesh->xend,mesh->ystart) - /sqrt(mesh->coordinates()->g_11(mesh->xend,mesh->ystart)); + /mesh->getCoordinates()->dx(mesh->xend,mesh->ystart) + /sqrt(mesh->getCoordinates()->g_11(mesh->xend,mesh->ystart)); try { sol4 = invert->solve(sliceXZ(b4, mesh->ystart), sliceXZ(x0, mesh->ystart)); @@ -283,16 +283,16 @@ int main(int argc, char** argv) { // Delp2 uses FFT z-derivatives and Laplace includes y-derivatives, so can't use those // The function is a copy of Laplace() with the y-derivatives deleted Field3D this_Grad_perp2(const Field3D &f) { - Field3D result = mesh->coordinates()->G1 * ::DDX(f) + mesh->coordinates()->G3 * ::DDZ(f) + - mesh->coordinates()->g11 * ::D2DX2(f) + mesh->coordinates()->g33 * ::D2DZ2(f) + - 2.0 * mesh->coordinates()->g13 * ::D2DXDZ(f); + Field3D result = mesh->getCoordinates()->G1 * ::DDX(f) + mesh->getCoordinates()->G3 * ::DDZ(f) + + mesh->getCoordinates()->g11 * ::D2DX2(f) + mesh->getCoordinates()->g33 * ::D2DZ2(f) + + 2.0 * mesh->getCoordinates()->g13 * ::D2DXDZ(f); return result; } Field3D this_Grad_perp_dot_Grad_perp(const Field3D &f, const Field3D &g) { - Field3D result = mesh->coordinates()->g11 * ::DDX(f) * ::DDX(g) + mesh->coordinates()->g33 * ::DDZ(f) * ::DDZ(g) - + mesh->coordinates()->g13 * (DDX(f)*DDZ(g) + DDZ(f)*DDX(g)); + Field3D result = mesh->getCoordinates()->g11 * ::DDX(f) * ::DDX(g) + mesh->getCoordinates()->g33 * ::DDZ(f) * ::DDZ(g) + + mesh->getCoordinates()->g13 * (DDX(f)*DDZ(g) + DDZ(f)*DDX(g)); return result; } diff --git a/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx b/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx index 3dde5d5d12..8a5f1f8103 100644 --- a/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx +++ b/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx @@ -54,8 +54,8 @@ int main(int argc, char** argv) { BoutReal nx = mesh->GlobalNx-2*mesh->xstart; BoutReal nz = mesh->GlobalNz; - dump.add(mesh->coordinates()->G1,"G1"); - dump.add(mesh->coordinates()->G3,"G3"); + dump.add(mesh->getCoordinates()->G1,"G1"); + dump.add(mesh->getCoordinates()->G3,"G3"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Test 1: zero-value Dirichlet boundaries @@ -238,13 +238,13 @@ int main(int argc, char** argv) { if (mesh->firstX()) for (int k=0;kLocalNz;k++) x0(mesh->xstart-1,mesh->ystart,k) = (f4(mesh->xstart,mesh->ystart,k)-f4(mesh->xstart-1,mesh->ystart,k)) - /mesh->coordinates()->dx(mesh->xstart,mesh->ystart) - /sqrt(mesh->coordinates()->g_11(mesh->xstart,mesh->ystart)); + /mesh->getCoordinates()->dx(mesh->xstart,mesh->ystart) + /sqrt(mesh->getCoordinates()->g_11(mesh->xstart,mesh->ystart)); if (mesh->lastX()) for (int k=0;kLocalNz;k++) x0(mesh->xend+1,mesh->ystart,k) = (f4(mesh->xend+1,mesh->ystart,k)-f4(mesh->xend,mesh->ystart,k)) - /mesh->coordinates()->dx(mesh->xend,mesh->ystart) - /sqrt(mesh->coordinates()->g_11(mesh->xend,mesh->ystart)); + /mesh->getCoordinates()->dx(mesh->xend,mesh->ystart) + /sqrt(mesh->getCoordinates()->g_11(mesh->xend,mesh->ystart)); try { sol4 = invert->solve(b4, x0); @@ -289,8 +289,8 @@ int main(int argc, char** argv) { } Field3D this_Grad_perp_dot_Grad_perp(const Field3D &f, const Field3D &g) { - Field3D result = mesh->coordinates()->g11 * ::DDX(f) * ::DDX(g) + mesh->coordinates()->g33 * ::DDZ(f) * ::DDZ(g) - + mesh->coordinates()->g13 * (DDX(f)*DDZ(g) + DDZ(f)*DDX(g)); + Field3D result = mesh->getCoordinates()->g11 * ::DDX(f) * ::DDX(g) + mesh->getCoordinates()->g33 * ::DDZ(f) * ::DDZ(g) + + mesh->getCoordinates()->g13 * (DDX(f)*DDZ(g) + DDZ(f)*DDX(g)); return result; } From a11951c739c0ff4fcc4666d4a0d18e0792295ebf Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 10 Oct 2018 16:55:46 +0100 Subject: [PATCH 34/69] Adding some Doxygen comments to mention allowed locations --- include/vecops.hxx | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 4ba38b96ce..75834f0ac4 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -36,6 +36,8 @@ /// Gradient of scalar field \p f, returning a covariant vector /// +/// All locations supported +/// /// @param[in] f The field to differentiate /// @param[in] outloc The location where the result is desired (if staggered meshes are enabled) /// By default this is the same location as the input \p f @@ -44,6 +46,8 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// Gradient of scalar field \p f, returning a covariant vector /// +/// All locations supported +/// /// @param[in] f The field to differentiate /// @param[in] outloc_x The cell location where the X component should be defined /// @param[in] outloc_y The cell location where the Y component should be defined @@ -53,6 +57,8 @@ const Vector3D DEPRECATED(Grad(const Field3D &f, /// Perpendicular gradient of scalar field \p f /// +/// outloc must be either CELL_DEFAULT or f.getLocation() --> argument can be removed +/// /// result.x = df/dx - g_12/(JB)^2 df/dy /// result.y = 0 /// result.z = df/dz - g_23/(JB)^2 df/dy @@ -64,6 +70,9 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// Perpendicular gradient of scalar field \p f /// +/// +/// outloc must all be the same and must be either CELL_DEFAULT or f.getLocation() --> arguments can be removed +/// /// result.x = df/dx - g_12/(JB)^2 df/dy /// result.y = 0 /// result.z = df/dz - g_23/(JB)^2 df/dy @@ -80,6 +89,8 @@ const Vector3D DEPRECATED(Grad_perp(const Field3D &f, /// Divergence of a vector \p v, returning a scalar /// +/// All locations except CELL_VSHIFT supported +/// /// @param[in] v The vector to differentiate /// @param[in] outloc The cell location where the result is desired /// @@ -93,6 +104,8 @@ const Field3D Div(const Vector3D &v, const Field3D &f); /// Curl of a vector /// +/// All locations except CELL_VSHIFT supported +/// /// @param[in] v The vector to differentiate /// @param[in] outloc The cell location where the result is desired /// @@ -110,9 +123,11 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f); const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f); /// Advection of a vector field \p a by a velocity vector \p v -const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a); -const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a); -const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a); -const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a); +/// +/// Both vectors must be at the same location, which cannot be CELL_VSHIFT +const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, CELL_LOC outloc); +const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, CELL_LOC outloc); +const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, CELL_LOC outloc); +const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, CELL_LOC outloc); #endif // __VECOPS_H__ From 573b1aabaf10be4f2a5dc0f02c396521c39419a2 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 13:27:21 +0100 Subject: [PATCH 35/69] Remove output location argument from V_dot_Grad Currently impossible to handle --- include/vecops.hxx | 10 +- src/field/vecops.cxx | 302 +++++++++++++++++++------------------------ 2 files changed, 138 insertions(+), 174 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 75834f0ac4..b85bf26d66 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -123,11 +123,9 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f); const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f); /// Advection of a vector field \p a by a velocity vector \p v -/// -/// Both vectors must be at the same location, which cannot be CELL_VSHIFT -const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, CELL_LOC outloc); -const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, CELL_LOC outloc); -const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, CELL_LOC outloc); -const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, CELL_LOC outloc); +const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a); +const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a); +const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a); +const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a); #endif // __VECOPS_H__ diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 852d5e2103..6294854dd1 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -396,250 +396,216 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { return result; } -const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a, CELL_LOC outloc) { +const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { TRACE("V_dot_Grad( Vector2D , Vector2D )"); - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - } - - ASSERT1(outloc != CELL_VSHIFT); ASSERT1(v.getLocation() == a.getLocation()); - // Note the following assert means the outloc argument is pointless - ASSERT1(v.getLocation() == outloc); - Mesh *localmesh = v.x.getMesh(); - Vector2D result(localmesh); + Vector2D result{v.x.getMesh()}; - Coordinates *metric = localmesh->coordinates(outloc); + auto metric_x = v.x.getCoordinates(); + auto metric_y = v.y.getCoordinates(); + auto metric_z = v.z.getCoordinates(); Vector2D vcn = v; vcn.toContravariant(); - if(a.covariant) { - - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x -= vcn.x*(metric->G1_11*a.x + metric->G2_11*a.y + metric->G3_11*a.z); - result.x -= vcn.y*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.x -= vcn.z*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); + if (a.covariant) { + + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); + result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y -= vcn.x*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.y -= vcn.y*(metric->G1_22*a.x + metric->G2_22*a.y + metric->G3_22*a.z); - result.y -= vcn.z*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); + result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z -= vcn.x*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); - result.z -= vcn.y*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); - result.z -= vcn.z*(metric->G1_33*a.x + metric->G2_33*a.y + metric->G3_33*a.z); + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); result.covariant = true; - }else { - - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x += vcn.x*(metric->G1_11*a.x + metric->G1_12*a.y + metric->G1_13*a.z); - result.x += vcn.y*(metric->G1_12*a.x + metric->G1_22*a.y + metric->G1_23*a.z); - result.x += vcn.z*(metric->G1_13*a.x + metric->G1_23*a.y + metric->G1_33*a.z); - - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y += vcn.x*(metric->G2_11*a.x + metric->G2_12*a.y + metric->G2_13*a.z); - result.y += vcn.y*(metric->G2_12*a.x + metric->G2_22*a.y + metric->G2_23*a.z); - result.y += vcn.z*(metric->G2_13*a.x + metric->G2_23*a.y + metric->G2_33*a.z); - - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z += vcn.x*(metric->G3_11*a.x + metric->G3_12*a.y + metric->G3_13*a.z); - result.z += vcn.y*(metric->G3_12*a.x + metric->G3_22*a.y + metric->G3_23*a.z); - result.z += vcn.z*(metric->G3_13*a.x + metric->G3_23*a.y + metric->G3_33*a.z); + } else { + + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); + result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); + result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); + result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); + result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); + result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); + result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); result.covariant = false; } - result.setLocation(outloc); - return result; } -const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a, CELL_LOC outloc) { +const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { TRACE("V_dot_Grad( Vector2D , Vector3D )"); - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - } - - ASSERT1(outloc != CELL_VSHIFT); ASSERT1(v.getLocation() == a.getLocation()); - // Note the following assert means the outloc argument is pointless - ASSERT1(v.getLocation() == outloc); - Mesh *localmesh = v.x.getMesh(); - Vector3D result(localmesh); + Vector3D result{v.x.getMesh()}; - Coordinates *metric = localmesh->coordinates(outloc); + auto metric_x = v.x.getCoordinates(); + auto metric_y = v.y.getCoordinates(); + auto metric_z = v.z.getCoordinates(); Vector2D vcn = v; vcn.toContravariant(); - if(a.covariant) { - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x -= vcn.x*(metric->G1_11*a.x + metric->G2_11*a.y + metric->G3_11*a.z); - result.x -= vcn.y*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.x -= vcn.z*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); + if (a.covariant) { + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); + result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y -= vcn.x*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.y -= vcn.y*(metric->G1_22*a.x + metric->G2_22*a.y + metric->G3_22*a.z); - result.y -= vcn.z*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); + result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z -= vcn.x*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); - result.z -= vcn.y*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); - result.z -= vcn.z*(metric->G1_33*a.x + metric->G2_33*a.y + metric->G3_33*a.z); + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); result.covariant = true; - }else { - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x += vcn.x*(metric->G1_11*a.x + metric->G1_12*a.y + metric->G1_13*a.z); - result.x += vcn.y*(metric->G1_12*a.x + metric->G1_22*a.y + metric->G1_23*a.z); - result.x += vcn.z*(metric->G1_13*a.x + metric->G1_23*a.y + metric->G1_33*a.z); - - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y += vcn.x*(metric->G2_11*a.x + metric->G2_12*a.y + metric->G2_13*a.z); - result.y += vcn.y*(metric->G2_12*a.x + metric->G2_22*a.y + metric->G2_23*a.z); - result.y += vcn.z*(metric->G2_13*a.x + metric->G2_23*a.y + metric->G2_33*a.z); - - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z += vcn.x*(metric->G3_11*a.x + metric->G3_12*a.y + metric->G3_13*a.z); - result.z += vcn.y*(metric->G3_12*a.x + metric->G3_22*a.y + metric->G3_23*a.z); - result.z += vcn.z*(metric->G3_13*a.x + metric->G3_23*a.y + metric->G3_33*a.z); + } else { + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); + result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); + result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); + result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); + result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); + result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); + result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); result.covariant = false; } - result.setLocation(outloc); - return result; } -const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a, CELL_LOC outloc) { +const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a) { TRACE("V_dot_Grad( Vector3D , Vector2D )"); - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - } - - ASSERT1(outloc != CELL_VSHIFT); ASSERT1(v.getLocation() == a.getLocation()); - // Note the following assert means the outloc argument is pointless - ASSERT1(v.getLocation() == outloc); - Mesh *localmesh = v.x.getMesh(); - Vector3D result(localmesh); + Vector3D result{v.x.getMesh()}; - Coordinates *metric = localmesh->coordinates(outloc); + auto metric_x = v.x.getCoordinates(); + auto metric_y = v.y.getCoordinates(); + auto metric_z = v.z.getCoordinates(); Vector3D vcn = v; vcn.toContravariant(); - if(a.covariant) { - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x -= vcn.x*(metric->G1_11*a.x + metric->G2_11*a.y + metric->G3_11*a.z); - result.x -= vcn.y*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.x -= vcn.z*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); + if (a.covariant) { + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); + result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y -= vcn.x*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.y -= vcn.y*(metric->G1_22*a.x + metric->G2_22*a.y + metric->G3_22*a.z); - result.y -= vcn.z*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); + result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z -= vcn.x*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); - result.z -= vcn.y*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); - result.z -= vcn.z*(metric->G1_33*a.x + metric->G2_33*a.y + metric->G3_33*a.z); + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); result.covariant = true; - }else { - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x += vcn.x*(metric->G1_11*a.x + metric->G1_12*a.y + metric->G1_13*a.z); - result.x += vcn.y*(metric->G1_12*a.x + metric->G1_22*a.y + metric->G1_23*a.z); - result.x += vcn.z*(metric->G1_13*a.x + metric->G1_23*a.y + metric->G1_33*a.z); - - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y += vcn.x*(metric->G2_11*a.x + metric->G2_12*a.y + metric->G2_13*a.z); - result.y += vcn.y*(metric->G2_12*a.x + metric->G2_22*a.y + metric->G2_23*a.z); - result.y += vcn.z*(metric->G2_13*a.x + metric->G2_23*a.y + metric->G2_33*a.z); - - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z += vcn.x*(metric->G3_11*a.x + metric->G3_12*a.y + metric->G3_13*a.z); - result.z += vcn.y*(metric->G3_12*a.x + metric->G3_22*a.y + metric->G3_23*a.z); - result.z += vcn.z*(metric->G3_13*a.x + metric->G3_23*a.y + metric->G3_33*a.z); + } else { + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); + result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); + result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); + result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); + result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); + result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); + result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); result.covariant = false; } - result.setLocation(outloc); - return result; } -const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a, CELL_LOC outloc) { +const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a) { TRACE("V_dot_Grad( Vector3D , Vector3D )"); - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - } - - ASSERT1(outloc != CELL_VSHIFT); ASSERT1(v.getLocation() == a.getLocation()); - // Note the following assert means the outloc argument is pointless - ASSERT1(v.getLocation() == outloc); - Mesh *localmesh = v.x.getMesh(); - Vector3D result(localmesh); + Vector3D result{v.x.getMesh()}; - Coordinates *metric = localmesh->coordinates(outloc); + auto metric_x = v.x.getCoordinates(); + auto metric_y = v.y.getCoordinates(); + auto metric_z = v.z.getCoordinates(); Vector3D vcn = v; vcn.toContravariant(); - if(a.covariant) { - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x -= vcn.x*(metric->G1_11*a.x + metric->G2_11*a.y + metric->G3_11*a.z); - result.x -= vcn.y*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.x -= vcn.z*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); + if (a.covariant) { + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); + result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y -= vcn.x*(metric->G1_12*a.x + metric->G2_12*a.y + metric->G3_12*a.z); - result.y -= vcn.y*(metric->G1_22*a.x + metric->G2_22*a.y + metric->G3_22*a.z); - result.y -= vcn.z*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); + result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); + result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z -= vcn.x*(metric->G1_13*a.x + metric->G2_13*a.y + metric->G3_13*a.z); - result.z -= vcn.y*(metric->G1_23*a.x + metric->G2_23*a.y + metric->G3_23*a.z); - result.z -= vcn.z*(metric->G1_33*a.x + metric->G2_33*a.y + metric->G3_33*a.z); + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); result.covariant = true; - }else { - result.x = VDDX(vcn.x, a.x, outloc) + VDDY(vcn.y, a.x, outloc) + VDDZ(vcn.z, a.x, outloc); - result.x += vcn.x*(metric->G1_11*a.x + metric->G1_12*a.y + metric->G1_13*a.z); - result.x += vcn.y*(metric->G1_12*a.x + metric->G1_22*a.y + metric->G1_23*a.z); - result.x += vcn.z*(metric->G1_13*a.x + metric->G1_23*a.y + metric->G1_33*a.z); - - result.y = VDDX(vcn.x, a.y, outloc) + VDDY(vcn.y, a.y, outloc) + VDDZ(vcn.z, a.y, outloc); - result.y += vcn.x*(metric->G2_11*a.x + metric->G2_12*a.y + metric->G2_13*a.z); - result.y += vcn.y*(metric->G2_12*a.x + metric->G2_22*a.y + metric->G2_23*a.z); - result.y += vcn.z*(metric->G2_13*a.x + metric->G2_23*a.y + metric->G2_33*a.z); - - result.z = VDDX(vcn.x, a.z, outloc) + VDDY(vcn.y, a.z, outloc) + VDDZ(vcn.z, a.z, outloc); - result.z += vcn.x*(metric->G3_11*a.x + metric->G3_12*a.y + metric->G3_13*a.z); - result.z += vcn.y*(metric->G3_12*a.x + metric->G3_22*a.y + metric->G3_23*a.z); - result.z += vcn.z*(metric->G3_13*a.x + metric->G3_23*a.y + metric->G3_33*a.z); + } else { + result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); + result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); + result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); + result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + + result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); + result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); + result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); + result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + + result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); + result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); + result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); + result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); result.covariant = false; } - result.setLocation(outloc); - return result; } - - From cbe468809c7acfc4ad57666ab23456a68274acf2 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 14:10:29 +0100 Subject: [PATCH 36/69] Use launch_safe in order set nproc and mthread Also rename timer wrappers with timed_ prefix --- tests/integrated/test-squash/runtest | 55 +++++++++++++++++----------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index f0aecfcee9..9e5e2d5e06 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -5,7 +5,7 @@ import itertools as it import os import time import numpy as np -from boututils.run_wrapper import shell_safe as _shell_safe +from boututils.run_wrapper import launch_safe, shell_safe #requires: all_tests #requires: netcdf @@ -23,9 +23,20 @@ class timer(object): print("%12.8f %s" % (end - self.start, self.msg)) -def shell_safe(cmd): +def timed_shell_safe(cmd, *args, **kwargs): + """Wraps shell_safe in a timer + + """ + with timer(cmd): + shell_safe(cmd, *args, **kwargs) + + +def timed_launch_safe(cmd, *args, **kwargs): + """Wraps launch_safe in a timer + + """ with timer(cmd): - _shell_safe(cmd) + launch_safe(cmd, *args, **kwargs) def verify(f1, f2): @@ -51,40 +62,40 @@ def verify(f1, f2): # affected raise RuntimeError("data mismatch in ", v, err, a, b) -shell_safe("make") +timed_shell_safe("make") # Run once to get normal data -shell_safe("./squash -q -q -q nout=4") -shell_safe("mv data/BOUT.dmp.0.nc f1.nc") +timed_shell_safe("./squash -q -q -q nout=2") +timed_shell_safe("mv data/BOUT.dmp.0.nc f1.nc") # Parallel test -shell_safe("rm -f f2.nc") -shell_safe("mpirun -np 4 ./squash -q -q -q nout=4") -shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") +timed_shell_safe("rm -f f2.nc") +timed_launch_safe("./squash -q -q -q nout=2", nproc=4, mthread=1) +timed_shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") verify("f1.nc", "f2.nc") # Parallel and in two pieces -shell_safe("rm -f f2.nc") -shell_safe("mpirun -np 4 ./squash -q -q -q") -shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") -shell_safe("mpirun -np 4 ./squash -q -q -q restart") -shell_safe("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../f2.nc") +timed_shell_safe("rm -f f2.nc") +timed_launch_safe("./squash -q -q -q", nproc=4, mthread=1) +timed_shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") +timed_launch_safe("./squash -q -q -q restart", nproc=4, mthread=1) +timed_shell_safe("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../f2.nc") verify("f1.nc", "f2.nc") # Parallel and in two pieces without dump_on_restart -shell_safe("rm -f f2.nc") -shell_safe("mpirun -np 4 ./squash -q -q -q") -shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") -shell_safe("mpirun -np 4 ./squash -q -q -q restart dump_on_restart=false") -shell_safe("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../f2.nc") +timed_shell_safe("rm -f f2.nc") +timed_launch_safe("./squash -q -q -q", nproc=4, mthread=1) +timed_shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") +timed_launch_safe("./squash -q -q -q restart dump_on_restart=false", nproc=4, mthread=1) +timed_shell_safe("../../../bin/bout-squashoutput -qdcal 9 data --outputname ../f2.nc") verify("f1.nc", "f2.nc") # Sequential test -shell_safe("rm -f f2.nc") -shell_safe("./squash -q -q -q nout=4") -shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") +timed_shell_safe("rm -f f2.nc") +timed_shell_safe("./squash -q -q -q nout=2") +timed_shell_safe("../../../bin/bout-squashoutput -qdcl 9 data --outputname ../f2.nc") verify("f1.nc", "f2.nc") From 627179a0f6ee88d71512d4ba943206918ba6c07a Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 14:11:59 +0100 Subject: [PATCH 37/69] Use minimal number of timesteps --- tests/integrated/test-squash/data/BOUT.inp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integrated/test-squash/data/BOUT.inp b/tests/integrated/test-squash/data/BOUT.inp index e5af938f53..3253314f8d 100644 --- a/tests/integrated/test-squash/data/BOUT.inp +++ b/tests/integrated/test-squash/data/BOUT.inp @@ -1,5 +1,5 @@ timestep = 1. -nout = 2 +nout = 1 MZ = 1 @@ -19,4 +19,4 @@ scale = 1. function = 0. [f3] -function = 0. \ No newline at end of file +function = 0. From ef396a16131e6fed075077581c410eea19d8efde Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 14:13:41 +0100 Subject: [PATCH 38/69] Add docstrings, simplify error message handling --- tests/integrated/test-squash/runtest | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index 9e5e2d5e06..cc440597bf 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -1,8 +1,7 @@ #!/usr/bin/env python3 from boututils.datafile import DataFile -import itertools as it -import os +import itertools import time import numpy as np from boututils.run_wrapper import launch_safe, shell_safe @@ -10,17 +9,20 @@ from boututils.run_wrapper import launch_safe, shell_safe #requires: all_tests #requires: netcdf + class timer(object): + """Context manager for printing how long a command took + """ def __init__(self, msg): self.msg = msg def __enter__(self): self.start = time.time() - def __exit__(self, a, b, c): + def __exit__(self, exc_type, exc_value, traceback): end = time.time() - print("%12.8f %s" % (end - self.start, self.msg)) + print("{:12.8f}s {}".format(end - self.start, self.msg)) def timed_shell_safe(cmd, *args, **kwargs): @@ -40,6 +42,9 @@ def timed_launch_safe(cmd, *args, **kwargs): def verify(f1, f2): + """Verifies that two BOUT++ files are identical + + """ with timer("verify %s %s" % (f1, f2)): d1 = DataFile(f1) d2 = DataFile(f2) @@ -49,18 +54,13 @@ def verify(f1, f2): if v in ["MXSUB", "MYSUB", "NXPE", "NYPE", "iteration"]: continue if not np.allclose(d1[v], d2[v]): - # continue - a = d1[v] - b = d2[v] err = "" - lst = [range(x) for x in d1[v].shape] - for i in it.product(*lst): - if a[i] != b[i]: - err += str(i) + ":" + str(a[i]) + "!=" + str( b[i]) + """ -""" - # There are differences, but I think only guard cells are - # affected - raise RuntimeError("data mismatch in ", v, err, a, b) + dimensions = [range(x) for x in d1[v].shape] + for i in itertools.product(*dimensions): + if d1[v][i] != d2[v][i]: + err += "{}: {} != {}\n".format(i, d1[v][i], d2[v][i]) + raise RuntimeError("data mismatch in ", v, err, d1[v], d2[v]) + timed_shell_safe("make") From 3c7f80631b635aba593861eb120349eb7ea73a11 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 14:26:44 +0100 Subject: [PATCH 39/69] Throw error messages for non-python collect routines Someone nice who knows IDL, Matlab/Octave and/or Mathematica could maybe actually fix these routines and submit pull requests :) --- tools/idllib/collect.pro | 2 ++ tools/mathematicalib/BoutCollect.m | 2 ++ tools/matlablib/import_data_netcdf.m | 2 ++ tools/matlablib/import_dmp.m | 2 ++ tools/octave/bcollect.m | 1 + 5 files changed, 9 insertions(+) diff --git a/tools/idllib/collect.pro b/tools/idllib/collect.pro index 6fcc78fb90..7c30b22bb5 100644 --- a/tools/idllib/collect.pro +++ b/tools/idllib/collect.pro @@ -20,6 +20,8 @@ FUNCTION collect, arg, xind=xind, yind=yind, zind=zind, tind=tind, $ path=path, var=var, t_array=t_array, use=use, old=old, $ quiet=quiet, debug=debug, prefix=prefix + MESSAGE, "This is currently broken for BOUT++ > v4.0.0. See issue #394" + IF NOT KEYWORD_SET(prefix) THEN prefix="BOUT.dmp" IF NOT KEYWORD_SET(debug) THEN BEGIN diff --git a/tools/mathematicalib/BoutCollect.m b/tools/mathematicalib/BoutCollect.m index b664812092..ae92fde2ed 100644 --- a/tools/mathematicalib/BoutCollect.m +++ b/tools/mathematicalib/BoutCollect.m @@ -7,6 +7,8 @@ {Xind,Yind,Zind,Tind,Path,Yguards,Info,Prefix, varnameissymbol,vars,position,dimensions,nxpe,nype,mxsub,mysub,mxg,myg,mz,tarray,files,nfiles,data,tempdata,ts,te,xs,xe,ys,ye,zs,ze,localx,localy,import,lxs,lxe,lys,lye}, + Throw["This is currently broken for BOUT++ > v4.0.0. See issue #394"] + Xind=OptionValue[xind]; Yind=OptionValue[yind]; Zind=OptionValue[zind]; diff --git a/tools/matlablib/import_data_netcdf.m b/tools/matlablib/import_data_netcdf.m index 31795f0d19..c3c3772840 100644 --- a/tools/matlablib/import_data_netcdf.m +++ b/tools/matlablib/import_data_netcdf.m @@ -21,6 +21,8 @@ % Last two variables important only for [X,Y,Z,T] format and any number % will be ok if we wish to plot [X,Y,Z] and [X,Y] type data. +error("This is currently broken for BOUT++ > v4.0.0. See issue #394") + % Check input arguments if ( nargin < 4 ) fprintf('\tBoth dump file path and variable name are requisite input arguments.\n'); diff --git a/tools/matlablib/import_dmp.m b/tools/matlablib/import_dmp.m index adadd93e8b..e5baa7f416 100644 --- a/tools/matlablib/import_dmp.m +++ b/tools/matlablib/import_dmp.m @@ -9,6 +9,8 @@ % % Coded by Minwoo Kim(Mar. 2012) +error("This is currently broken for BOUT++ > v4.0.0. See issue #394") + % Check input arguments if ( nargin < 2 ) fprintf('\tBoth dump file path and variable name are requisite input arguments.\n'); diff --git a/tools/octave/bcollect.m b/tools/octave/bcollect.m index 0005f4c726..d1128daf19 100644 --- a/tools/octave/bcollect.m +++ b/tools/octave/bcollect.m @@ -17,6 +17,7 @@ # Collect metadata from collection of data files function desc = bcollect(path) + error("This is currently broken for BOUT++ > v4.0.0. See issue #394") narg = nargin(); if (narg < 1) # No path specified, so use current directory From 7fd82e965628e4a59aba160f111431641cad0822 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 16:23:13 +0100 Subject: [PATCH 40/69] Remove support for CELL_VSHIFT in V_dot_Grad --- include/vecops.hxx | 4 + src/field/vecops.cxx | 172 ++++++++++++++++++++++--------------------- 2 files changed, 92 insertions(+), 84 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index b85bf26d66..b9376298b7 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -117,12 +117,16 @@ const Vector3D DEPRECATED(Curl(const Vector3D &v, // Upwinding routines /// Advection of a scalar field \p f by a velocity vector \p v +/// +/// Both vectors must be at the same location, which cannot be CELL_VSHIFT const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f); const Field3D V_dot_Grad(const Vector2D &v, const Field3D &f); const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f); const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f); /// Advection of a vector field \p a by a velocity vector \p v +/// +/// Both vectors must be at the same location, which cannot be CELL_VSHIFT const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a); const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a); const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a); diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 6294854dd1..46f520418b 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -400,12 +400,11 @@ const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { TRACE("V_dot_Grad( Vector2D , Vector2D )"); ASSERT1(v.getLocation() == a.getLocation()); + ASSERT1(v.getLocation() != CELL_VSHIFT); Vector2D result{v.x.getMesh()}; - auto metric_x = v.x.getCoordinates(); - auto metric_y = v.y.getCoordinates(); - auto metric_z = v.z.getCoordinates(); + auto metric = v.x.getCoordinates(); Vector2D vcn = v; vcn.toContravariant(); @@ -413,41 +412,43 @@ const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { if (a.covariant) { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); - result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.x -= vcn.x * (metric->G1_11 * a.x + metric->G2_11 * a.y + metric->G3_11 * a.z); + result.x -= vcn.y * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.x -= vcn.z * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); - result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.y -= vcn.x * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.y -= vcn.y * (metric->G1_22 * a.x + metric->G2_22 * a.y + metric->G3_22 * a.z); + result.y -= vcn.z * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); + result.z -= vcn.x * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); + result.z -= vcn.y * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); + result.z -= vcn.z * (metric->G1_33 * a.x + metric->G2_33 * a.y + metric->G3_33 * a.z); result.covariant = true; } else { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); - result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); - result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + result.x += vcn.x * (metric->G1_11 * a.x + metric->G1_12 * a.y + metric->G1_13 * a.z); + result.x += vcn.y * (metric->G1_12 * a.x + metric->G1_22 * a.y + metric->G1_23 * a.z); + result.x += vcn.z * (metric->G1_13 * a.x + metric->G1_23 * a.y + metric->G1_33 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); - result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); - result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + result.y += vcn.x * (metric->G2_11 * a.x + metric->G2_12 * a.y + metric->G2_13 * a.z); + result.y += vcn.y * (metric->G2_12 * a.x + metric->G2_22 * a.y + metric->G2_23 * a.z); + result.y += vcn.z * (metric->G2_13 * a.x + metric->G2_23 * a.y + metric->G2_33 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); - result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); - result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); + result.z += vcn.x * (metric->G3_11 * a.x + metric->G3_12 * a.y + metric->G3_13 * a.z); + result.z += vcn.y * (metric->G3_12 * a.x + metric->G3_22 * a.y + metric->G3_23 * a.z); + result.z += vcn.z * (metric->G3_13 * a.x + metric->G3_23 * a.y + metric->G3_33 * a.z); result.covariant = false; } + result.setLocation(v.getLocation()); + return result; } @@ -455,52 +456,53 @@ const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { TRACE("V_dot_Grad( Vector2D , Vector3D )"); ASSERT1(v.getLocation() == a.getLocation()); + ASSERT1(v.getLocation() != CELL_VSHIFT); Vector3D result{v.x.getMesh()}; - auto metric_x = v.x.getCoordinates(); - auto metric_y = v.y.getCoordinates(); - auto metric_z = v.z.getCoordinates(); + auto metric = v.x.getCoordinates(); Vector2D vcn = v; vcn.toContravariant(); if (a.covariant) { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); - result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.x -= vcn.x * (metric->G1_11 * a.x + metric->G2_11 * a.y + metric->G3_11 * a.z); + result.x -= vcn.y * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.x -= vcn.z * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); - result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.y -= vcn.x * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.y -= vcn.y * (metric->G1_22 * a.x + metric->G2_22 * a.y + metric->G3_22 * a.z); + result.y -= vcn.z * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); + result.z -= vcn.x * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); + result.z -= vcn.y * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); + result.z -= vcn.z * (metric->G1_33 * a.x + metric->G2_33 * a.y + metric->G3_33 * a.z); result.covariant = true; } else { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); - result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); - result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + result.x += vcn.x * (metric->G1_11 * a.x + metric->G1_12 * a.y + metric->G1_13 * a.z); + result.x += vcn.y * (metric->G1_12 * a.x + metric->G1_22 * a.y + metric->G1_23 * a.z); + result.x += vcn.z * (metric->G1_13 * a.x + metric->G1_23 * a.y + metric->G1_33 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); - result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); - result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + result.y += vcn.x * (metric->G2_11 * a.x + metric->G2_12 * a.y + metric->G2_13 * a.z); + result.y += vcn.y * (metric->G2_12 * a.x + metric->G2_22 * a.y + metric->G2_23 * a.z); + result.y += vcn.z * (metric->G2_13 * a.x + metric->G2_23 * a.y + metric->G2_33 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); - result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); - result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); + result.z += vcn.x * (metric->G3_11 * a.x + metric->G3_12 * a.y + metric->G3_13 * a.z); + result.z += vcn.y * (metric->G3_12 * a.x + metric->G3_22 * a.y + metric->G3_23 * a.z); + result.z += vcn.z * (metric->G3_13 * a.x + metric->G3_23 * a.y + metric->G3_33 * a.z); result.covariant = false; } + result.setLocation(v.getLocation()); + return result; } @@ -508,52 +510,53 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a) { TRACE("V_dot_Grad( Vector3D , Vector2D )"); ASSERT1(v.getLocation() == a.getLocation()); + ASSERT1(v.getLocation() != CELL_VSHIFT); Vector3D result{v.x.getMesh()}; - auto metric_x = v.x.getCoordinates(); - auto metric_y = v.y.getCoordinates(); - auto metric_z = v.z.getCoordinates(); + auto metric = v.x.getCoordinates(); Vector3D vcn = v; vcn.toContravariant(); if (a.covariant) { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); - result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.x -= vcn.x * (metric->G1_11 * a.x + metric->G2_11 * a.y + metric->G3_11 * a.z); + result.x -= vcn.y * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.x -= vcn.z * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); - result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.y -= vcn.x * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.y -= vcn.y * (metric->G1_22 * a.x + metric->G2_22 * a.y + metric->G3_22 * a.z); + result.y -= vcn.z * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); + result.z -= vcn.x * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); + result.z -= vcn.y * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); + result.z -= vcn.z * (metric->G1_33 * a.x + metric->G2_33 * a.y + metric->G3_33 * a.z); result.covariant = true; } else { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); - result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); - result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + result.x += vcn.x * (metric->G1_11 * a.x + metric->G1_12 * a.y + metric->G1_13 * a.z); + result.x += vcn.y * (metric->G1_12 * a.x + metric->G1_22 * a.y + metric->G1_23 * a.z); + result.x += vcn.z * (metric->G1_13 * a.x + metric->G1_23 * a.y + metric->G1_33 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); - result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); - result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + result.y += vcn.x * (metric->G2_11 * a.x + metric->G2_12 * a.y + metric->G2_13 * a.z); + result.y += vcn.y * (metric->G2_12 * a.x + metric->G2_22 * a.y + metric->G2_23 * a.z); + result.y += vcn.z * (metric->G2_13 * a.x + metric->G2_23 * a.y + metric->G2_33 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); - result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); - result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); + result.z += vcn.x * (metric->G3_11 * a.x + metric->G3_12 * a.y + metric->G3_13 * a.z); + result.z += vcn.y * (metric->G3_12 * a.x + metric->G3_22 * a.y + metric->G3_23 * a.z); + result.z += vcn.z * (metric->G3_13 * a.x + metric->G3_23 * a.y + metric->G3_33 * a.z); result.covariant = false; } + result.setLocation(v.getLocation()); + return result; } @@ -561,51 +564,52 @@ const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a) { TRACE("V_dot_Grad( Vector3D , Vector3D )"); ASSERT1(v.getLocation() == a.getLocation()); + ASSERT1(v.getLocation() != CELL_VSHIFT); Vector3D result{v.x.getMesh()}; - auto metric_x = v.x.getCoordinates(); - auto metric_y = v.y.getCoordinates(); - auto metric_z = v.z.getCoordinates(); + auto metric = v.x.getCoordinates(); Vector3D vcn = v; vcn.toContravariant(); if (a.covariant) { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x -= vcn.x * (metric_x->G1_11 * a.x + metric_y->G2_11 * a.y + metric_z->G3_11 * a.z); - result.x -= vcn.y * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.x -= vcn.z * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); + result.x -= vcn.x * (metric->G1_11 * a.x + metric->G2_11 * a.y + metric->G3_11 * a.z); + result.x -= vcn.y * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.x -= vcn.z * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y -= vcn.x * (metric_x->G1_12 * a.x + metric_y->G2_12 * a.y + metric_z->G3_12 * a.z); - result.y -= vcn.y * (metric_x->G1_22 * a.x + metric_y->G2_22 * a.y + metric_z->G3_22 * a.z); - result.y -= vcn.z * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); + result.y -= vcn.x * (metric->G1_12 * a.x + metric->G2_12 * a.y + metric->G3_12 * a.z); + result.y -= vcn.y * (metric->G1_22 * a.x + metric->G2_22 * a.y + metric->G3_22 * a.z); + result.y -= vcn.z * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z -= vcn.x * (metric_x->G1_13 * a.x + metric_y->G2_13 * a.y + metric_z->G3_13 * a.z); - result.z -= vcn.y * (metric_x->G1_23 * a.x + metric_y->G2_23 * a.y + metric_z->G3_23 * a.z); - result.z -= vcn.z * (metric_x->G1_33 * a.x + metric_y->G2_33 * a.y + metric_z->G3_33 * a.z); + result.z -= vcn.x * (metric->G1_13 * a.x + metric->G2_13 * a.y + metric->G3_13 * a.z); + result.z -= vcn.y * (metric->G1_23 * a.x + metric->G2_23 * a.y + metric->G3_23 * a.z); + result.z -= vcn.z * (metric->G1_33 * a.x + metric->G2_33 * a.y + metric->G3_33 * a.z); result.covariant = true; } else { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - result.x += vcn.x * (metric_x->G1_11 * a.x + metric_y->G1_12 * a.y + metric_z->G1_13 * a.z); - result.x += vcn.y * (metric_x->G1_12 * a.x + metric_y->G1_22 * a.y + metric_z->G1_23 * a.z); - result.x += vcn.z * (metric_x->G1_13 * a.x + metric_y->G1_23 * a.y + metric_z->G1_33 * a.z); + result.x += vcn.x * (metric->G1_11 * a.x + metric->G1_12 * a.y + metric->G1_13 * a.z); + result.x += vcn.y * (metric->G1_12 * a.x + metric->G1_22 * a.y + metric->G1_23 * a.z); + result.x += vcn.z * (metric->G1_13 * a.x + metric->G1_23 * a.y + metric->G1_33 * a.z); result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - result.y += vcn.x * (metric_x->G2_11 * a.x + metric_y->G2_12 * a.y + metric_z->G2_13 * a.z); - result.y += vcn.y * (metric_x->G2_12 * a.x + metric_y->G2_22 * a.y + metric_z->G2_23 * a.z); - result.y += vcn.z * (metric_x->G2_13 * a.x + metric_y->G2_23 * a.y + metric_z->G2_33 * a.z); + result.y += vcn.x * (metric->G2_11 * a.x + metric->G2_12 * a.y + metric->G2_13 * a.z); + result.y += vcn.y * (metric->G2_12 * a.x + metric->G2_22 * a.y + metric->G2_23 * a.z); + result.y += vcn.z * (metric->G2_13 * a.x + metric->G2_23 * a.y + metric->G2_33 * a.z); result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); - result.z += vcn.x * (metric_x->G3_11 * a.x + metric_y->G3_12 * a.y + metric_z->G3_13 * a.z); - result.z += vcn.y * (metric_x->G3_12 * a.x + metric_y->G3_22 * a.y + metric_z->G3_23 * a.z); - result.z += vcn.z * (metric_x->G3_13 * a.x + metric_y->G3_23 * a.y + metric_z->G3_33 * a.z); + result.z += vcn.x * (metric->G3_11 * a.x + metric->G3_12 * a.y + metric->G3_13 * a.z); + result.z += vcn.y * (metric->G3_12 * a.x + metric->G3_22 * a.y + metric->G3_23 * a.z); + result.z += vcn.z * (metric->G3_13 * a.x + metric->G3_23 * a.y + metric->G3_33 * a.z); result.covariant = false; } + result.setLocation(v.getLocation()); + return result; } From d5a9f214abdca892abc207ca1117099a402154c1 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 17:03:26 +0100 Subject: [PATCH 41/69] Add some text on setting the openmp schedule --- manual/sphinx/user_docs/advanced_install.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index 6f024075a3..755a37d979 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -279,6 +279,16 @@ this is not always possible. You may need to perform some testing yourself to find e.g. the optimum split of OpenMP threads and MPI ranks. +One such parameter that can potentially have a significant effect (for +some problem sizes on some machines) is setting the OpenMP schedule +used in some of the OpenMP loops (specifically those using +`BOUT_FOR`). This can be set using:: + + ./configure --enable-openmp --with-openmp-schedule= + +with ```` being one of: ``static`` (the default), +``dynamic``, ``guided``, ``auto`` or ``runtime``. + .. note:: If you want to use OpenMP with Clang, you will need Clang 3.7+, From 1493312e1cd6fbeea98a1c697387fd553ba73fb6 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 11 Oct 2018 17:03:51 +0100 Subject: [PATCH 42/69] Fix some sphinx whitespace/code blocks --- manual/sphinx/developer_docs/data_types.rst | 20 ++++++++++---------- manual/sphinx/user_docs/advanced_install.rst | 15 ++++++++------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/manual/sphinx/developer_docs/data_types.rst b/manual/sphinx/developer_docs/data_types.rst index aec326d7f3..6bfffff328 100644 --- a/manual/sphinx/developer_docs/data_types.rst +++ b/manual/sphinx/developer_docs/data_types.rst @@ -265,7 +265,7 @@ to OpenMP parallelise or vectorise:: } If you wish to vectorise but can't use OpenMP then there is a serial -verion of the macro: +verion of the macro:: BoutReal max=0.; BOUT_FOR_SERIAL(i, region) { @@ -285,10 +285,10 @@ For loops inside parallel regions, there is ``BOUT_FOR_INNER``:: If a more general OpenMP directive is needed, there is ``BOUT_FOR_OMP``:: - BoutReal result=0.; - BOUT_FOR_OMP(i, region, parallel for reduction(max:result)) { - result = f[i] > result ? f[i] : result; - } + BoutReal result=0.; + BOUT_FOR_OMP(i, region, parallel for reduction(max:result)) { + result = f[i] > result ? f[i] : result; + } The iterator provides access to the x, y, z indices:: @@ -304,11 +304,11 @@ modulo operators are needed to calculate individual indices. To perform finite difference or similar operators, index offsets can be calculated:: - Field3D f = ...; - Field3D g(0.0); - BOUT_FOR(i, f.getMesh()->getRegion3D("RGN_NOBNDRY")) { - g[i] = f[i.xp()] - f[i.xm()]; - } + Field3D f = ...; + Field3D g(0.0); + BOUT_FOR(i, f.getMesh()->getRegion3D("RGN_NOBNDRY")) { + g[i] = f[i.xp()] - f[i.xm()]; + } The ``xp()`` function by default produces an offset of ``+1`` in ``X``, ``xm()`` an offset of ``-1`` in the ``X`` direction. These functions can also diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index 755a37d979..6468f31d47 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -165,13 +165,14 @@ To compile for the SKL partition, configure with to enable AVX512 vectorization. -.. note:: As of 20/04/2018, an issue with the netcdf and netcdf-cxx4 modules - means that you will need to remove ``-lnetcdf`` from ``EXTRA_LIBS`` in - ``make.config`` after running ``./configure`` and before running - ``make``. ``-lnetcdf`` needs also to be removed from ``bin/bout-config`` - to allow a successful build of the python interface. Recreation of - ``boutcore.pyx`` needs to be manually triggered, if - ``boutcore.pyx`` has already been created. +.. note:: As of 20/04/2018, an issue with the netcdf and netcdf-cxx4 + modules means that you will need to remove ``-lnetcdf`` from + ``EXTRA_LIBS`` in ``make.config`` after running + ``./configure`` and before running ``make``. ``-lnetcdf`` + needs also to be removed from ``bin/bout-config`` to allow a + successful build of the python interface. Recreation of + ``boutcore.pyx`` needs to be manually triggered, if + ``boutcore.pyx`` has already been created. Ubgl ~~~~ From 836abfbf4426926fda9847e79c4eb0b72fb53b30 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Thu, 11 Oct 2018 16:19:09 +0100 Subject: [PATCH 43/69] Provide `getRegion` method on Fields to return the requested Region from fieldmesh --- include/field2d.hxx | 4 ++++ include/field3d.hxx | 4 ++++ include/fieldperp.hxx | 4 ++++ src/field/field2d.cxx | 7 +++++++ src/field/field3d.cxx | 7 +++++++ src/field/fieldperp.cxx | 7 +++++++ 6 files changed, 33 insertions(+) diff --git a/include/field2d.hxx b/include/field2d.hxx index b261ca8456..51e14607ab 100644 --- a/include/field2d.hxx +++ b/include/field2d.hxx @@ -154,6 +154,10 @@ class Field2D : public Field, public FieldData { */ const IndexRange DEPRECATED(region(REGION rgn)) const override; + /// Return a Region reference to use to iterate over this field + const Region& getRegion(REGION region) const; + const Region& getRegion(const std::string ®ion_name) const; + BoutReal& operator[](const Ind2D &d) { return data[d.ind]; } diff --git a/include/field3d.hxx b/include/field3d.hxx index bd085f7c73..1025f935ab 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -328,6 +328,10 @@ class Field3D : public Field, public FieldData { */ const IndexRange DEPRECATED(region2D(REGION rgn)) const; + /// Return a Region reference to use to iterate over this field + const Region& getRegion(REGION region) const; + const Region& getRegion(const std::string ®ion_name) const; + /*! * Direct data access using DataIterator object. * This uses operator(x,y,z) so checks will only be diff --git a/include/fieldperp.hxx b/include/fieldperp.hxx index 8fef875e8a..90fdcf03d8 100644 --- a/include/fieldperp.hxx +++ b/include/fieldperp.hxx @@ -91,6 +91,10 @@ class FieldPerp : public Field { const IndexRange DEPRECATED(region(REGION rgn)) const override; + /// Return a Region reference to use to iterate over this field + const Region& getRegion(REGION region) const; + const Region& getRegion(const std::string ®ion_name) const; + /*! * Direct data access using DataIterator indexing */ diff --git a/src/field/field2d.cxx b/src/field/field2d.cxx index c7859f1d46..ad44b43a1b 100644 --- a/src/field/field2d.cxx +++ b/src/field/field2d.cxx @@ -179,6 +179,13 @@ const IndexRange Field2D::region(REGION rgn) const { }; } +const Region &Field2D::getRegion(REGION region) const { + return fieldmesh->getRegion2D(REGION_STRING(region)); +}; +const Region &Field2D::getRegion(const std::string ®ion_name) const { + return fieldmesh->getRegion2D(region_name); +}; + void Field2D::setLocation(CELL_LOC new_location) { if (getMesh()->StaggerGrids) { if (new_location == CELL_VSHIFT) { diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index c62900285a..1143eb9fdc 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -355,6 +355,13 @@ const IndexRange Field3D::region2D(REGION rgn) const { }; } +const Region &Field3D::getRegion(REGION region) const { + return fieldmesh->getRegion3D(REGION_STRING(region)); +}; +const Region &Field3D::getRegion(const std::string ®ion_name) const { + return fieldmesh->getRegion3D(region_name); +}; + /////////////////// ASSIGNMENT //////////////////// Field3D & Field3D::operator=(const Field3D &rhs) { diff --git a/src/field/fieldperp.cxx b/src/field/fieldperp.cxx index 856b6c0272..5bd7765e91 100644 --- a/src/field/fieldperp.cxx +++ b/src/field/fieldperp.cxx @@ -215,6 +215,13 @@ const IndexRange FieldPerp::region(REGION rgn) const { }; } +const Region &FieldPerp::getRegion(REGION region) const { + return fieldmesh->getRegionPerp(REGION_STRING(region)); +}; +const Region &FieldPerp::getRegion(const std::string ®ion_name) const { + return fieldmesh->getRegionPerp(region_name); +}; + //////////////// NON-MEMBER FUNCTIONS ////////////////// ////////////// NON-MEMBER OVERLOADED OPERATORS ////////////// From 00dfc5fb408dce38d3f9731ed5658b171290effa Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Fri, 12 Oct 2018 11:53:21 +0100 Subject: [PATCH 44/69] Add const(_iterator) overload of Region::begin/end --- include/bout/region.hxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/bout/region.hxx b/include/bout/region.hxx index d11587ef98..d4671ebe25 100644 --- a/include/bout/region.hxx +++ b/include/bout/region.hxx @@ -483,8 +483,10 @@ public: /// Note that if the indices are altered using these iterators, the /// blocks may become out of sync and will need to manually updated typename RegionIndices::iterator begin() { return std::begin(indices); }; + typename RegionIndices::const_iterator begin() const { return std::begin(indices); }; typename RegionIndices::const_iterator cbegin() const { return indices.cbegin(); }; typename RegionIndices::iterator end() { return std::end(indices); }; + typename RegionIndices::const_iterator end() const { return std::end(indices); }; typename RegionIndices::const_iterator cend() const { return indices.cend(); }; const ContiguousBlocks &getBlocks() const { return blocks; }; From a1b8deefcc7ce3af8236f4acdff4dc3e08e1a864 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Fri, 12 Oct 2018 11:53:42 +0100 Subject: [PATCH 45/69] Make mesh::getRegion?? const --- include/bout/mesh.hxx | 8 ++++---- src/mesh/mesh.cxx | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index f3682c9dbd..41ecbd41d0 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -650,12 +650,12 @@ class Mesh { /// Get the named region from the region_map for the data iterator /// /// Throws if region_name not found - Region<> &getRegion(const std::string ®ion_name){ + const Region<> &getRegion(const std::string ®ion_name) const{ return getRegion3D(region_name); } - Region &getRegion3D(const std::string ®ion_name); - Region &getRegion2D(const std::string ®ion_name); - Region &getRegionPerp(const std::string ®ion_name); + const Region &getRegion3D(const std::string ®ion_name) const; + const Region &getRegion2D(const std::string ®ion_name) const; + const Region &getRegionPerp(const std::string ®ion_name) const; /// Add a new region to the region_map for the data iterator /// diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index 34b1c7709f..2bc9b0617e 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -335,24 +335,24 @@ std::shared_ptr Mesh::createDefaultCoordinates(const CELL_LOC locat } -Region<> & Mesh::getRegion3D(const std::string ®ion_name){ - auto found = regionMap3D.find(region_name); - if (found == end(regionMap3D)) { - throw BoutException("Couldn't find region %s in regionMap3D", region_name.c_str()); - } - return found->second; +const Region<> & Mesh::getRegion3D(const std::string ®ion_name) const { + const auto found = regionMap3D.find(region_name); + if (found == end(regionMap3D)) { + throw BoutException("Couldn't find region %s in regionMap3D", region_name.c_str()); + } + return found->second; } -Region & Mesh::getRegion2D(const std::string ®ion_name){ - auto found = regionMap2D.find(region_name); - if (found == end(regionMap2D)) { - throw BoutException("Couldn't find region %s in regionMap2D", region_name.c_str()); - } - return found->second; +const Region & Mesh::getRegion2D(const std::string ®ion_name) const { + const auto found = regionMap2D.find(region_name); + if (found == end(regionMap2D)) { + throw BoutException("Couldn't find region %s in regionMap2D", region_name.c_str()); + } + return found->second; } -Region &Mesh::getRegionPerp(const std::string ®ion_name) { - auto found = regionMapPerp.find(region_name); +const Region &Mesh::getRegionPerp(const std::string ®ion_name) const { + const auto found = regionMapPerp.find(region_name); if (found == end(regionMapPerp)) { throw BoutException("Couldn't find region %s in regionMapPerp", region_name.c_str()); } From cba520fea1ea01ac778e592e445e8b3cac4fe40c Mon Sep 17 00:00:00 2001 From: John Omotani Date: Sat, 6 Oct 2018 01:02:29 +0100 Subject: [PATCH 46/69] Remove unnecessary interp_to in Grad2_par2 g_22 is already at outloc, so interp_to(g_22, outloc) is unnecessary. --- src/mesh/coordinates.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 10dcd9b4df..1b6531e295 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -759,7 +759,7 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc) { result = ::DDY(f, outloc); - r2 = D2DY2(f, outloc) / interp_to(g_22, outloc); + r2 = D2DY2(f, outloc, method) / g_22; result = sg * result + r2; From b54aef907554b5714ef380f476bfd35187a08d2b Mon Sep 17 00:00:00 2001 From: John Omotani Date: Thu, 11 Oct 2018 23:47:35 +0100 Subject: [PATCH 47/69] Tidying up more location setting in derivatives --- src/mesh/coordinates.cxx | 22 ++++++++++------------ src/mesh/difops.cxx | 3 +-- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 1b6531e295..e655d154e0 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -650,7 +650,7 @@ const Field2D Coordinates::DDZ(const Field2D &f, CELL_LOC loc, const Field2D Coordinates::Grad_par(const Field2D &var, CELL_LOC outloc, DIFF_METHOD UNUSED(method)) { TRACE("Coordinates::Grad_par( Field2D )"); - ASSERT1(location == outloc || outloc == CELL_DEFAULT); + ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == var.getLocation())); return DDY(var) / sqrt(g_22); } @@ -670,7 +670,7 @@ const Field3D Coordinates::Grad_par(const Field3D &var, CELL_LOC outloc, const Field2D Coordinates::Vpar_Grad_par(const Field2D &v, const Field2D &f, CELL_LOC outloc, DIFF_METHOD UNUSED(method)) { - ASSERT1(location == outloc || outloc == CELL_DEFAULT); + ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); return VDDY(v, f) / sqrt(g_22); } @@ -730,7 +730,7 @@ const Field3D Coordinates::Div_par(const Field3D &f, CELL_LOC outloc, const Field2D Coordinates::Grad2_par2(const Field2D &f, CELL_LOC outloc) { TRACE("Coordinates::Grad2_par2( Field2D )"); - ASSERT1(location == outloc || outloc == CELL_DEFAULT); + ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); Field2D sg = sqrt(g_22); Field2D result = DDY(1. / sg, outloc) * DDY(f, outloc) / sg + D2DY2(f, outloc) / g_22; @@ -740,7 +740,9 @@ const Field2D Coordinates::Grad2_par2(const Field2D &f, CELL_LOC outloc) { const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc) { TRACE("Coordinates::Grad2_par2( Field3D )"); - ASSERT1(location == outloc || outloc == CELL_DEFAULT); + if (outloc == CELL_DEFAULT) + outloc = f.getLocation(); + ASSERT1(location == outloc); Field2D sg(localmesh); Field3D result(localmesh), r2(localmesh); @@ -748,9 +750,6 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc) { sg = sqrt(g_22); sg = DDY(1. / sg) / sg; - if (outloc == CELL_DEFAULT) { - outloc = f.getLocation(); - } if (sg.getLocation() != outloc) { localmesh->communicate(sg); @@ -763,8 +762,7 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc) { result = sg * result + r2; - ASSERT2(((outloc == CELL_DEFAULT) && (result.getLocation() == f.getLocation())) || - (result.getLocation() == outloc)); + ASSERT2(result.getLocation() == outloc); return result; } @@ -785,7 +783,8 @@ const Field2D Coordinates::Delp2(const Field2D &f, CELL_LOC outloc) { const Field3D Coordinates::Delp2(const Field3D &f, CELL_LOC outloc) { TRACE("Coordinates::Delp2( Field3D )"); - ASSERT1(location == outloc || outloc == CELL_DEFAULT); + if (outloc == CELL_DEFAULT) outloc = f.getLocation(); + ASSERT1(location == outloc); if (localmesh->GlobalNx == 1 && localmesh->GlobalNz == 1) { // copy mesh, location, etc @@ -793,7 +792,6 @@ const Field3D Coordinates::Delp2(const Field3D &f, CELL_LOC outloc) { } ASSERT2(localmesh->xstart > 0); // Need at least one guard cell - if (outloc == CELL_DEFAULT) outloc = f.getLocation(); ASSERT2(f.getLocation() == outloc); Field3D result(localmesh); @@ -855,7 +853,7 @@ const FieldPerp Coordinates::Delp2(const FieldPerp &f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); - ASSERT1(location == outloc || outloc == CELL_DEFAULT); + ASSERT1(location == outloc); ASSERT2(f.getLocation() == outloc); FieldPerp result(localmesh); diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 8b8ff649ce..54a0b1c03b 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -730,8 +730,7 @@ const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC ou result.name = "b0xGrad_dot_Grad("+phi.name+","+A.name+")"; #endif - ASSERT2(((outloc == CELL_DEFAULT) && (result.getLocation() == A.getLocation())) || - (result.getLocation() == outloc)); + ASSERT2(result.getLocation() == outloc); return result; } From 3be53345ce2ab4f8617a391fb41e914053d33d1a Mon Sep 17 00:00:00 2001 From: John Omotani Date: Fri, 12 Oct 2018 13:14:10 +0100 Subject: [PATCH 48/69] Remove bracket_location() function, replace with ASSERT1 The bracket_location() method was just checking that the locations of both input fields and the output are all the same. Can replace this simply with an ASSERT1 statement in each bracket operator. --- src/mesh/difops.cxx | 82 +++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 52 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 54a0b1c03b..846a0490b7 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -740,52 +740,25 @@ const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC ou * Terms of form b0 x Grad(f) dot Grad(g) / B = [f, g] *******************************************************************************/ -/*! - * Calculate location of result - */ -// use anonymous namespace so this function is only available in this file -namespace { - CELL_LOC bracket_location(const CELL_LOC &f_loc, const CELL_LOC &g_loc, const CELL_LOC &outloc, Mesh* localmesh=mesh) { - if(!localmesh->StaggerGrids) - return CELL_CENTRE; - - if(outloc == CELL_DEFAULT){ - // Check that f and g are in the same location - if (f_loc != g_loc){ - throw BoutException("Bracket currently requires both fields to have the same cell location"); - }else { - return f_loc; // Location of result - } - } - - // Check that f, and g are in the same location as the specified output location - if(f_loc != g_loc || f_loc != outloc){ - throw BoutException("Bracket currently requires the location of both fields and the output locaton to be the same"); - } - - return outloc; // Location of result - } -} - const Field2D bracket(const Field2D &f, const Field2D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *UNUSED(solver)) { TRACE("bracket(Field2D, Field2D)"); ASSERT1(f.getMesh() == g.getMesh()); + if (outloc == CELL_DEFAULT) + outloc = g.getLocation(); + ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Field2D result(f.getMesh()); - // Sort out cell locations - CELL_LOC result_loc = bracket_location(f.getLocation(), g.getLocation(), outloc, f.getMesh()); - if( (method == BRACKET_SIMPLE) || (method == BRACKET_ARAKAWA)) { // Use a subset of terms for comparison to BOUT-06 result = 0.0; + result.setLocation(outloc); }else { // Use full expression with all terms - result = b0xGrad_dot_Grad(f, g) / f.getCoordinates(result_loc)->Bxy; + result = b0xGrad_dot_Grad(f, g, outloc) / f.getCoordinates(outloc)->Bxy; } - result.setLocation(result_loc); return result; } @@ -794,14 +767,15 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, TRACE("bracket(Field3D, Field2D)"); ASSERT1(f.getMesh() == g.getMesh()); + if (outloc == CELL_DEFAULT) + outloc = g.getLocation(); + ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Mesh *mesh = f.getMesh(); Field3D result(mesh); - CELL_LOC result_loc = bracket_location(f.getLocation(), g.getLocation(), outloc, f.getMesh()); - - Coordinates *metric = f.getCoordinates(result_loc); + Coordinates *metric = f.getCoordinates(outloc); switch(method) { case BRACKET_CTU: { @@ -812,6 +786,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, throw BoutException("CTU method requires access to the solver"); result.allocate(); + result.setLocation(outloc); int ncz = mesh->LocalNz; for(int x=mesh->xstart;x<=mesh->xend;x++) @@ -849,6 +824,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, // Arakawa scheme for perpendicular flow. Here as a test result.allocate(); + result.setLocation(outloc); const BoutReal fac = 1.0 / (12 * metric->dz); const int ncz = mesh->LocalNz; @@ -919,6 +895,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, } case BRACKET_ARAKAWA_OLD: { result.allocate(); + result.setLocation(outloc); const int ncz = mesh->LocalNz; const BoutReal partialFactor = 1.0/(12 * metric->dz); BOUT_OMP(parallel for) @@ -958,15 +935,14 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, } case BRACKET_SIMPLE: { // Use a subset of terms for comparison to BOUT-06 - result = VDDX(DDZ(f), g); + result = VDDX(DDZ(f, outloc), g, outloc); break; } default: { // Use full expression with all terms - result = b0xGrad_dot_Grad(f, g) / metric->Bxy; + result = b0xGrad_dot_Grad(f, g, outloc) / metric->Bxy; } } - result.setLocation(result_loc); return result; } @@ -975,13 +951,14 @@ const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, TRACE("bracket(Field2D, Field3D)"); ASSERT1(f.getMesh() == g.getMesh()); + if (outloc == CELL_DEFAULT) + outloc = g.getLocation(); + ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Mesh *mesh = f.getMesh(); Field3D result(mesh); - CELL_LOC result_loc = bracket_location(f.getLocation(), g.getLocation(), outloc, f.getMesh()); - switch(method) { case BRACKET_CTU: throw BoutException("Bracket method CTU is not yet implemented for [2d,3d] fields."); @@ -992,16 +969,15 @@ const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, break; case BRACKET_SIMPLE: { // Use a subset of terms for comparison to BOUT-06 - result = VDDZ(-DDX(f), g); + result = VDDZ(-DDX(f, outloc), g, outloc); break; } default: { // Use full expression with all terms - Coordinates *metric = f.getCoordinates(result_loc); - result = b0xGrad_dot_Grad(f, g) / metric->Bxy; + Coordinates *metric = f.getCoordinates(outloc); + result = b0xGrad_dot_Grad(f, g, outloc) / metric->Bxy; } } - result.setLocation(result_loc) ; return result; } @@ -1011,18 +987,19 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, TRACE("Field3D, Field3D"); ASSERT1(f.getMesh() == g.getMesh()); + if (outloc == CELL_DEFAULT) + outloc = g.getLocation(); + ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Mesh *mesh = f.getMesh(); Field3D result(mesh); - CELL_LOC result_loc = bracket_location(f.getLocation(), g.getLocation(), outloc, f.getMesh()); - - Coordinates *metric = f.getCoordinates(result_loc); + Coordinates *metric = f.getCoordinates(outloc); if (mesh->GlobalNx == 1 || mesh->GlobalNz == 1) { result=0; - result.setLocation(result_loc); + result.setLocation(outloc); return result; } @@ -1038,6 +1015,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, BoutReal dt = solver->getCurrentTimestep(); result.allocate(); + result.setLocation(outloc); FieldPerp vx(mesh), vz(mesh); vx.allocate(); @@ -1128,6 +1106,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, // Arakawa scheme for perpendicular flow result.allocate(); + result.setLocation(outloc); const int ncz = mesh->LocalNz; const BoutReal partialFactor = 1.0/(12 * metric->dz); @@ -1221,6 +1200,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, // Arakawa scheme for perpendicular flow result.allocate(); + result.setLocation(outloc); const int ncz = mesh->LocalNz; const BoutReal partialFactor = 1.0 / (12 * metric->dz); @@ -1270,16 +1250,14 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, } case BRACKET_SIMPLE: { // Use a subset of terms for comparison to BOUT-06 - result = VDDX(DDZ(f), g) + VDDZ(-DDX(f), g); + result = VDDX(DDZ(f, outloc), g, outloc) + VDDZ(-DDX(f, outloc), g, outloc); break; } default: { // Use full expression with all terms - result = b0xGrad_dot_Grad(f, g) / metric->Bxy; + result = b0xGrad_dot_Grad(f, g, outloc) / metric->Bxy; } } - result.setLocation(result_loc) ; - return result; } From ac984b812d853fce96b32d2fb579a4b5800d53d8 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Thu, 11 Oct 2018 23:36:37 +0100 Subject: [PATCH 49/69] Remove const on arguments passed by value --- src/mesh/difops.cxx | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 846a0490b7..88d3ce2901 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -167,7 +167,7 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { * vparallel times the parallel derivative along unperturbed B-field *******************************************************************************/ -const Field2D Vpar_Grad_par(const Field2D &v, const Field2D &f, const CELL_LOC outloc) { +const Field2D Vpar_Grad_par(const Field2D &v, const Field2D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc); } @@ -184,7 +184,7 @@ const Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, DIFF_METHOD meth * parallel divergence operator B \partial_{||} (F/B) *******************************************************************************/ -const Field2D Div_par(const Field2D &f, const CELL_LOC outloc) { +const Field2D Div_par(const Field2D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc); } @@ -489,11 +489,11 @@ const Field3D Div_par_CtoL(const Field3D &var) { * Note: For parallel Laplacian use LaplacePar *******************************************************************************/ -const Field2D Grad2_par2(const Field2D &f, const CELL_LOC outloc) { +const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc); } -const Field3D Grad2_par2(const Field3D &f, const CELL_LOC outloc) { +const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc); } @@ -502,27 +502,27 @@ const Field3D Grad2_par2(const Field3D &f, const CELL_LOC outloc) { * Parallel divergence of diffusive flux, K*Grad_par *******************************************************************************/ -const Field2D Div_par_K_Grad_par(BoutReal kY, const Field2D &f, const CELL_LOC outloc) { +const Field2D Div_par_K_Grad_par(BoutReal kY, const Field2D &f, CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } -const Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, const CELL_LOC outloc) { +const Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } -const Field2D Div_par_K_Grad_par(const Field2D &kY, const Field2D &f, const CELL_LOC outloc) { +const Field2D Div_par_K_Grad_par(const Field2D &kY, const Field2D &f, CELL_LOC outloc) { return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); } -const Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, const CELL_LOC outloc) { +const Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc) { return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); } -const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, const CELL_LOC outloc) { +const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc) { return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); } -const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, const CELL_LOC outloc) { +const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc) { return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); } @@ -531,15 +531,15 @@ const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, const CELL * perpendicular Laplacian operator *******************************************************************************/ -const Field2D Delp2(const Field2D &f, const CELL_LOC outloc) { +const Field2D Delp2(const Field2D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Delp2(f, outloc); } -const Field3D Delp2(const Field3D &f, BoutReal UNUSED(zsmooth), const CELL_LOC outloc) { +const Field3D Delp2(const Field3D &f, BoutReal UNUSED(zsmooth), CELL_LOC outloc) { return f.getCoordinates(outloc)->Delp2(f, outloc); } -const FieldPerp Delp2(const FieldPerp &f, BoutReal UNUSED(zsmooth), const CELL_LOC outloc) { +const FieldPerp Delp2(const FieldPerp &f, BoutReal UNUSED(zsmooth), CELL_LOC outloc) { return f.getCoordinates(outloc)->Delp2(f, outloc); } @@ -550,11 +550,11 @@ const FieldPerp Delp2(const FieldPerp &f, BoutReal UNUSED(zsmooth), const CELL_L * Laplace_perp = Laplace - Laplace_par *******************************************************************************/ -const Field2D Laplace_perp(const Field2D &f, const CELL_LOC outloc) { +const Field2D Laplace_perp(const Field2D &f, CELL_LOC outloc) { return Laplace(f, outloc) - Laplace_par(f, outloc); } -const Field3D Laplace_perp(const Field3D &f, const CELL_LOC outloc) { +const Field3D Laplace_perp(const Field3D &f, CELL_LOC outloc) { return Laplace(f, outloc) - Laplace_par(f, outloc); } @@ -566,11 +566,11 @@ const Field3D Laplace_perp(const Field3D &f, const CELL_LOC outloc) { * *******************************************************************************/ -const Field2D Laplace_par(const Field2D &f, const CELL_LOC outloc) { +const Field2D Laplace_par(const Field2D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } -const Field3D Laplace_par(const Field3D &f, const CELL_LOC outloc) { +const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } @@ -579,11 +579,11 @@ const Field3D Laplace_par(const Field3D &f, const CELL_LOC outloc) { * Full Laplacian operator on scalar field *******************************************************************************/ -const Field2D Laplace(const Field2D &f, const CELL_LOC outloc) { +const Field2D Laplace(const Field2D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace(f, outloc); } -const Field3D Laplace(const Field3D &f, const CELL_LOC outloc) { +const Field3D Laplace(const Field3D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace(f, outloc); } From 2bef4ec427e1cd981dba8c1c077940f896f46647 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Wed, 3 Oct 2018 21:07:44 +0100 Subject: [PATCH 50/69] Add method argument to Grad2_par2 Also tidy up calculation of 'sg' intermediate variable in Grad2_par2: pass outloc to it's derivative and remove unneeded if clause that used to interpolate 'sg' if its location was wrong. --- include/bout/coordinates.hxx | 4 ++-- include/difops.hxx | 4 ++-- src/mesh/coordinates.cxx | 15 +++++---------- src/mesh/difops.cxx | 8 ++++---- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index ba9522c6c3..e649cdfcc7 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -123,8 +123,8 @@ public: const Field3D Div_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT, DIFF_METHOD method=DIFF_DEFAULT); // Second derivative along magnetic field - const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); - const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); + const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT, DIFF_METHOD method=DIFF_DEFAULT); + const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT, DIFF_METHOD method=DIFF_DEFAULT); // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code diff --git a/include/difops.hxx b/include/difops.hxx index 029fade7eb..52caf84bc5 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -173,7 +173,7 @@ const Field3D Div_par(const Field3D &f, const Field3D &v); * * Note: For parallel Laplacian use LaplacePar */ -const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT, DIFF_METHOD method=DIFF_DEFAULT); /*! * second parallel derivative @@ -186,7 +186,7 @@ const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); * @param[in] f The field to be differentiated * @param[in] outloc The cell location of the result */ -const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); +const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT, DIFF_METHOD method=DIFF_DEFAULT); /*! * Parallel derivatives, converting between cell-centred and lower cell boundary diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index e655d154e0..e1f3f4a867 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -728,17 +728,17 @@ const Field3D Coordinates::Div_par(const Field3D &f, CELL_LOC outloc, // second parallel derivative (b dot Grad)(b dot Grad) // Note: For parallel Laplacian use Laplace_par -const Field2D Coordinates::Grad2_par2(const Field2D &f, CELL_LOC outloc) { +const Field2D Coordinates::Grad2_par2(const Field2D &f, CELL_LOC outloc, DIFF_METHOD method) { TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); Field2D sg = sqrt(g_22); - Field2D result = DDY(1. / sg, outloc) * DDY(f, outloc) / sg + D2DY2(f, outloc) / g_22; + Field2D result = DDY(1. / sg, outloc, method) * DDY(f, outloc, method) / sg + D2DY2(f, outloc, method) / g_22; return result; } -const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc) { +const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc, DIFF_METHOD method) { TRACE("Coordinates::Grad2_par2( Field3D )"); if (outloc == CELL_DEFAULT) outloc = f.getLocation(); @@ -748,15 +748,10 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc) { Field3D result(localmesh), r2(localmesh); sg = sqrt(g_22); - sg = DDY(1. / sg) / sg; + sg = DDY(1. / sg, outloc, method) / sg; - if (sg.getLocation() != outloc) { - localmesh->communicate(sg); - sg = interp_to(sg, outloc); - } - - result = ::DDY(f, outloc); + result = ::DDY(f, outloc, method); r2 = D2DY2(f, outloc, method) / g_22; diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 88d3ce2901..fbd063559d 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -489,12 +489,12 @@ const Field3D Div_par_CtoL(const Field3D &var) { * Note: For parallel Laplacian use LaplacePar *******************************************************************************/ -const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc) { - return f.getCoordinates(outloc)->Grad2_par2(f, outloc); +const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc, DIFF_METHOD method) { + return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } -const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc) { - return f.getCoordinates(outloc)->Grad2_par2(f, outloc); +const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, DIFF_METHOD method) { + return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } /******************************************************************************* From 8757d9c10c0abb25e698da892ee1f4e752fa2a9c Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 12 Oct 2018 15:43:59 +0100 Subject: [PATCH 51/69] Use std::map::emplace to avoid naming complicated type with insert --- include/bout/mesh.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index 41ecbd41d0..97a05e99c8 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -439,7 +439,7 @@ class Mesh { // No coordinate system set. Create default // Note that this can't be allocated here due to incomplete type // (circular dependency between Mesh and Coordinates) - coords_map.insert(std::pair >(location, createDefaultCoordinates(location))); + coords_map.emplace(location, createDefaultCoordinates(location)); return coords_map[location].get(); } } From fce89793dd1d4233a73a894463f5056d76a8296e Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 12 Oct 2018 15:55:48 +0100 Subject: [PATCH 52/69] Fix V_dot_Grad documentation --- include/vecops.hxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index b9376298b7..d416e23a95 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -118,7 +118,8 @@ const Vector3D DEPRECATED(Curl(const Vector3D &v, /// Advection of a scalar field \p f by a velocity vector \p v /// -/// Both vectors must be at the same location, which cannot be CELL_VSHIFT +/// The vector and the field must be at the same location, which +/// cannot be CELL_VSHIFT const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f); const Field3D V_dot_Grad(const Vector2D &v, const Field3D &f); const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f); From 49247a30f9c1ac56f54d27142a576ae69afff076 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Fri, 12 Oct 2018 16:34:57 +0100 Subject: [PATCH 53/69] Use curly braces with if statements --- src/mesh/coordinates.cxx | 7 +++++-- src/mesh/difops.cxx | 12 ++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index e1f3f4a867..236f4552a0 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -740,8 +740,9 @@ const Field2D Coordinates::Grad2_par2(const Field2D &f, CELL_LOC outloc, DIFF_ME const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc, DIFF_METHOD method) { TRACE("Coordinates::Grad2_par2( Field3D )"); - if (outloc == CELL_DEFAULT) + if (outloc == CELL_DEFAULT) { outloc = f.getLocation(); + } ASSERT1(location == outloc); Field2D sg(localmesh); @@ -778,7 +779,9 @@ const Field2D Coordinates::Delp2(const Field2D &f, CELL_LOC outloc) { const Field3D Coordinates::Delp2(const Field3D &f, CELL_LOC outloc) { TRACE("Coordinates::Delp2( Field3D )"); - if (outloc == CELL_DEFAULT) outloc = f.getLocation(); + if (outloc == CELL_DEFAULT) { + outloc = f.getLocation(); + } ASSERT1(location == outloc); if (localmesh->GlobalNx == 1 && localmesh->GlobalNz == 1) { diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index fbd063559d..51b9ce101d 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -745,8 +745,9 @@ const Field2D bracket(const Field2D &f, const Field2D &g, BRACKET_METHOD method, TRACE("bracket(Field2D, Field2D)"); ASSERT1(f.getMesh() == g.getMesh()); - if (outloc == CELL_DEFAULT) + if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); + } ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Field2D result(f.getMesh()); @@ -767,8 +768,9 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, TRACE("bracket(Field3D, Field2D)"); ASSERT1(f.getMesh() == g.getMesh()); - if (outloc == CELL_DEFAULT) + if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); + } ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Mesh *mesh = f.getMesh(); @@ -951,8 +953,9 @@ const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, TRACE("bracket(Field2D, Field3D)"); ASSERT1(f.getMesh() == g.getMesh()); - if (outloc == CELL_DEFAULT) + if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); + } ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Mesh *mesh = f.getMesh(); @@ -987,8 +990,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, TRACE("Field3D, Field3D"); ASSERT1(f.getMesh() == g.getMesh()); - if (outloc == CELL_DEFAULT) + if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); + } ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) Mesh *mesh = f.getMesh(); From 6ef003f18f37a743beed16e193e9a4ee8d6f0aec Mon Sep 17 00:00:00 2001 From: John Omotani Date: Thu, 11 Oct 2018 16:25:45 +0100 Subject: [PATCH 54/69] Set yup/ydown fields for Div_par_flux() Div_par_flux() takes FDDY(v, f/B). If f has yup/ydown fields these were being lost in the division. This commit copies the solution from Div_par() by dividing creating a new field f_B=f/B whose yup/ydown fields are also set, before calling FDDY. --- src/mesh/difops.cxx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 51b9ce101d..072c9ed93c 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -239,7 +239,24 @@ const Field3D Div_par(const Field3D &f, const Field3D &v) { const Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, DIFF_METHOD method) { Coordinates *metric = f.getCoordinates(outloc); - return metric->Bxy*FDDY(v, f/f.getCoordinates()->Bxy, outloc, method)/sqrt(metric->g_22); + + Field2D Bxy_floc = f.getCoordinates()->Bxy; + if (f.hasYupYdown()) { + // Need to modify yup and ydown fields + Field3D f_B = f / Bxy_floc; + if (&f.yup() == &f) { + // Identity, yup and ydown point to same field + f_B.mergeYupYdown(); + } else { + // Distinct fields + f_B.splitYupYdown(); + f_B.yup() = f.yup() / Bxy_floc; + f_B.ydown() = f.ydown() / Bxy_floc; + } + return metric->Bxy*FDDY(v, f_B, outloc, method)/sqrt(metric->g_22); + } + + return metric->Bxy*FDDY(v, f/Bxy_floc, outloc, method)/sqrt(metric->g_22); } const Field3D Div_par_flux(const Field3D &v, const Field3D &f, DIFF_METHOD method, CELL_LOC outloc) { From c9acb64656a58f4601ce8c048096273ae85dcbcd Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 15 Oct 2018 11:34:57 +0100 Subject: [PATCH 55/69] Fix locations of Jacobian in Div Also clarify that Div cannot have outloc == VSHIFT --- include/vecops.hxx | 3 ++- src/field/vecops.cxx | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index d416e23a95..01245467a6 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -89,7 +89,8 @@ const Vector3D DEPRECATED(Grad_perp(const Field3D &f, /// Divergence of a vector \p v, returning a scalar /// -/// All locations except CELL_VSHIFT supported +/// All locations except `CELL_VSHIFT` supported. Note that if \p v is +/// at `CELL_VSHIFT`, then \p outloc must be `CELL_CENTRE` /// /// @param[in] v The vector to differentiate /// @param[in] outloc The cell location where the result is desired diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 46f520418b..b056d832f2 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -171,6 +171,7 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { outloc = v.getLocation(); } + // This also catches the combination of v at VSHIFT and outloc at DEFAULT ASSERT1(outloc != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); @@ -182,9 +183,9 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { Vector3D vcn = v; vcn.toContravariant(); - result = DDX(metric->J * vcn.x, outloc); - result += DDY(metric->J * vcn.y, outloc); - result += DDZ(metric->J * vcn.z, outloc); + result = DDX(vcn.x.getCoordinates()->J * vcn.x, outloc); + result += DDY(vcn.y.getCoordinates()->J * vcn.y, outloc); + result += DDZ(vcn.z.getCoordinates()->J * vcn.z, outloc); result /= metric->J; return result; @@ -211,9 +212,9 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { vcn.toContravariant(); Field2D result(localmesh); - result = FDDX(metric->J * vcn.x, f, outloc); - result += FDDY(metric->J * vcn.y, f, outloc); - result += FDDZ(metric->J * vcn.z, f, outloc); + result = FDDX(vcn.x.getCoordinates()->J * vcn.x, f, outloc); + result += FDDY(vcn.y.getCoordinates()->J * vcn.y, f, outloc); + result += FDDZ(vcn.z.getCoordinates()->J * vcn.z, f, outloc); result /= metric->J; return result; @@ -236,9 +237,9 @@ const Field3D Div(const Vector3D &v, const Field3D &f, DIFF_METHOD method, vcn.toContravariant(); Field3D result(localmesh); - result = FDDX(metric->J * vcn.x, f, outloc, method); - result += FDDY(metric->J * vcn.y, f, outloc, method); - result += FDDZ(metric->J * vcn.z, f, outloc, method); + result = FDDX(vcn.x.getCoordinates()->J * vcn.x, f, outloc, method); + result += FDDY(vcn.y.getCoordinates()->J * vcn.y, f, outloc, method); + result += FDDZ(vcn.z.getCoordinates()->J * vcn.z, f, outloc, method); result /= metric->J; return result; From afe353c031b401dc356cbfd0d7b1d238e939d027 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 15 Oct 2018 11:38:53 +0100 Subject: [PATCH 56/69] Deprecate Curl overloads that take a location Not currently supported, as it would involve "cross-staggering" terms --- include/vecops.hxx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 01245467a6..9c9bc8e140 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -105,15 +105,23 @@ const Field3D Div(const Vector3D &v, const Field3D &f); /// Curl of a vector /// -/// All locations except CELL_VSHIFT supported +/// Does not currently support any output locations /// /// @param[in] v The vector to differentiate -/// @param[in] outloc The cell location where the result is desired /// -const Vector2D Curl(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); -const Vector3D Curl(const Vector3D &v, CELL_LOC outloc = CELL_DEFAULT); -const Vector3D DEPRECATED(Curl(const Vector3D &v, - CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z)); +const Vector2D Curl(const Vector2D &v); +const Vector3D Curl(const Vector3D &v); +inline const Vector2D DEPRECATED(Curl(const Vector2D &v, CELL_LOC UNUSED(outloc))) { + return Curl(v); +} +inline const Vector3D DEPRECATED(Curl(const Vector3D &v, CELL_LOC UNUSED(outloc))) { + return Curl(v); +} +inline const Vector3D DEPRECATED(Curl(const Vector3D &v, CELL_LOC UNUSED(outloc_x), + CELL_LOC UNUSED(outloc_y), + CELL_LOC UNUSED(outloc_z))) { + return Curl(v); +} // Upwinding routines From df49dd13a1e68ba2ec3c7ba7ed26115bae8756fa Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 15 Oct 2018 11:39:41 +0100 Subject: [PATCH 57/69] Fix whitespace in vecops header --- include/vecops.hxx | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 9c9bc8e140..879912c3d7 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -1,6 +1,6 @@ /*!************************************************************************ * \file vecops.hxx - * + * * Operators on vector objects * B.Dudson, October 2007 * @@ -8,7 +8,7 @@ * Copyright 2010 B.D.Dudson, S.Farley, M.V.Umansky, X.Q.Xu * * Contact: Ben Dudson, bd512@york.ac.uk - * + * * This file is part of BOUT++. * * BOUT++ is free software: you can redistribute it and/or modify @@ -52,8 +52,8 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// @param[in] outloc_x The cell location where the X component should be defined /// @param[in] outloc_y The cell location where the Y component should be defined /// @param[in] outloc_z The cell location where the Z component should be defined -const Vector3D DEPRECATED(Grad(const Field3D &f, - CELL_LOC outloc_x, CELL_LOC outloc_y, CELL_LOC outloc_z)); +const Vector3D DEPRECATED(Grad(const Field3D &f, CELL_LOC outloc_x, CELL_LOC outloc_y, + CELL_LOC outloc_z)); /// Perpendicular gradient of scalar field \p f /// @@ -62,7 +62,7 @@ const Vector3D DEPRECATED(Grad(const Field3D &f, /// result.x = df/dx - g_12/(JB)^2 df/dy /// result.y = 0 /// result.z = df/dz - g_23/(JB)^2 df/dy -/// +/// /// @param[in] f The field to differentiate /// @param[in] outloc The cell location where the result is desired /// @@ -76,16 +76,14 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// result.x = df/dx - g_12/(JB)^2 df/dy /// result.y = 0 /// result.z = df/dz - g_23/(JB)^2 df/dy -/// +/// /// @param[in] f The field to differentiate /// @param[in] outloc_x The cell location where the X component should be defined /// @param[in] outloc_y The cell location where the Y component should be defined /// @param[in] outloc_z The cell location where the Z component should be defined /// -const Vector3D DEPRECATED(Grad_perp(const Field3D &f, - CELL_LOC outloc_x, - CELL_LOC outloc_y, - CELL_LOC outloc_z)); +const Vector3D DEPRECATED(Grad_perp(const Field3D &f, CELL_LOC outloc_x, + CELL_LOC outloc_y, CELL_LOC outloc_z)); /// Divergence of a vector \p v, returning a scalar /// From 64e24b7c367025bb7164db672b401bb0547b0fa5 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 15 Oct 2018 12:56:02 +0100 Subject: [PATCH 58/69] Remove output location from Curl properly --- include/vecops.hxx | 8 ++++++- src/field/vecops.cxx | 50 +++++++++++++------------------------------- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 879912c3d7..ca06def8d2 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -103,7 +103,13 @@ const Field3D Div(const Vector3D &v, const Field3D &f); /// Curl of a vector /// -/// Does not currently support any output locations +/// Does not currently support any output locations. \p v must not be +/// at `CELL_VSHIFT` +/// +/// We can't support VSHIFT here as, e.g. DDY can't produce an output +/// at CELL_XLOW unless the input field is at CELL_XLOW, but then that +/// field will also be needed at CELL_YLOW, for example for another +/// component. /// /// @param[in] v The vector to differentiate /// diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index b056d832f2..21c5b3133b 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -259,21 +259,13 @@ const Field3D Div(const Vector3D &v, const Field3D &f) { * Curl operators **************************************************************************/ -const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { +const Vector2D Curl(const Vector2D &v) { TRACE("Curl( Vector2D )"); - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - } - - // We can't support VSHIFT here as, e.g. DDY can't produce an output at CELL_XLOW - // unless the input field is at CELL_XLOW, but then that field will also be needed - // at CELL_YLOW, for example for another component. - ASSERT1(outloc != CELL_VSHIFT); - + ASSERT1(v.getLocation() != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); - auto metric = localmesh->coordinates(outloc); + auto metric = v.x.getCoordinates(); // Get covariant components of v Vector2D vco = v; @@ -281,41 +273,27 @@ const Vector2D Curl(const Vector2D &v, CELL_LOC outloc) { // get components (curl(v))^j Vector2D result(localmesh); - result.x = (DDY(vco.z, outloc) - DDZ(vco.y, outloc)) / metric->J; - result.y = (DDZ(vco.x, outloc) - DDX(vco.z, outloc)) / metric->J; - result.z = (DDX(vco.y, outloc) - DDY(vco.x, outloc)) / metric->J; + result.x = (DDY(vco.z) - DDZ(vco.y)) / metric->J; + result.y = (DDZ(vco.x) - DDX(vco.z)) / metric->J; + result.z = (DDX(vco.y) - DDY(vco.x)) / metric->J; /// Coordinate torsion result.z -= metric->ShiftTorsion * vco.z / metric->J; - result.setLocation(outloc); + result.setLocation(v.getLocation()); result.covariant = false; // result is contravariant return result; } -const Vector3D Curl(const Vector3D &v, CELL_LOC outloc_x, CELL_LOC outloc_y, - CELL_LOC outloc_z) { +const Vector3D Curl(const Vector3D &v) { TRACE("Curl( Vector3D )"); - ASSERT1(outloc_x == outloc_y && outloc_x == outloc_z); - return Curl(v, outloc_x); -} - -const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { - TRACE("Curl( Vector3D )"); - - if (outloc == CELL_DEFAULT) { - outloc = v.getLocation(); - }; - // We can't support VSHIFT here as, e.g. DDY can't produce an output at CELL_XLOW - // unless the input field is at CELL_XLOW, but then that field will also be needed - // at CELL_YLOW, for example for another component. - ASSERT1(outloc != CELL_VSHIFT); + ASSERT1(v.getLocation() != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); - auto metric = v.x.getCoordinates(outloc); + auto metric = v.x.getCoordinates(); // Get covariant components of v Vector3D vco = v; @@ -323,14 +301,14 @@ const Vector3D Curl(const Vector3D &v, CELL_LOC outloc) { // get components (curl(v))^j Vector3D result(localmesh); - result.x = (DDY(vco.z, outloc) - DDZ(vco.y, outloc)) / metric->J; - result.y = (DDZ(vco.x, outloc) - DDX(vco.z, outloc)) / metric->J; - result.z = (DDX(vco.y, outloc) - DDY(vco.x, outloc)) / metric->J; + result.x = (DDY(vco.z) - DDZ(vco.y)) / metric->J; + result.y = (DDZ(vco.x) - DDX(vco.z)) / metric->J; + result.z = (DDX(vco.y) - DDY(vco.x)) / metric->J; // Coordinate torsion result.z -= metric->ShiftTorsion * vco.z / metric->J; - result.setLocation(outloc); + result.setLocation(v.getLocation()); result.covariant = false; // result is contravariant From 20a4cc1680ff7a40c5d374c47567b27db78f6ee9 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Sun, 14 Oct 2018 13:49:24 +0100 Subject: [PATCH 59/69] Check TwistShift==true in ShiftedMetric The ShiftedMetric class requires TwistShift==true to get yup/ydown fields correct at the branch cut where poloidal angle and zShift jump. So check in ShiftedMetric constructor that the option is set correctly. Add second option to turn off the check if you really want to use ShiftedMetric with TwistShift=false (e.g. in a linear device). --- src/mesh/parallel/shiftedmetric.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/mesh/parallel/shiftedmetric.cxx b/src/mesh/parallel/shiftedmetric.cxx index 13067fe07c..e4b493dabc 100644 --- a/src/mesh/parallel/shiftedmetric.cxx +++ b/src/mesh/parallel/shiftedmetric.cxx @@ -23,6 +23,15 @@ ShiftedMetric::ShiftedMetric(Mesh &m) : mesh(m), zShift(&m) { mesh.get(zShift, "qinty"); } + // TwistShift needs to be set for derivatives to be correct at the jump where + // poloidal angle theta goes 2pi->0 + bool twistshift = Options::root()["TwistShift"].withDefault(false); + bool shift_without_twist = Options::root()["ShiftWithoutTwist"].withDefault(false); + if (!twistshift and !shift_without_twist) { + throw BoutException("ShiftedMetric usually requires the option TwistShift=true\n" + " Set ShiftWithoutTwist=true to use ShiftedMetric without TwistShift"); + } + //If we wanted to be efficient we could move the following cached phase setup //into the relevant shifting routines (with static bool first protection) //so that we only calculate the phase if we actually call a relevant shift From 0d57cb7e1846d416a6da26d6c5f6bfdafa91bcdb Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 15 Oct 2018 18:27:38 +0100 Subject: [PATCH 60/69] Make test-yupdown work with new test for TwistShift=true --- tests/integrated/test-yupdown/data/BOUT.inp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-yupdown/data/BOUT.inp b/tests/integrated/test-yupdown/data/BOUT.inp index f905f9c36c..46604e38e7 100644 --- a/tests/integrated/test-yupdown/data/BOUT.inp +++ b/tests/integrated/test-yupdown/data/BOUT.inp @@ -1,3 +1,4 @@ +ShiftWithoutTwist = true [mesh] nx = 12 From 05759978813dbfa3ed1314e833b802c463ab8bf5 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 15 Oct 2018 18:38:46 +0100 Subject: [PATCH 61/69] Invert conditional in Div_par and Div_par_flux In new form there is less state the reader needs to keep in their heads. --- src/mesh/coordinates.cxx | 32 ++++++++++++++++---------------- src/mesh/difops.cxx | 29 +++++++++++++++-------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 236f4552a0..81c0e921e4 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -704,24 +704,24 @@ const Field3D Coordinates::Div_par(const Field3D &f, CELL_LOC outloc, // Coordinates object Field2D Bxy_floc = f.getCoordinates()->Bxy; - if (f.hasYupYdown()) { - // Need to modify yup and ydown fields - Field3D f_B = f / Bxy_floc; - if (&f.yup() == &f) { - // Identity, yup and ydown point to same field - f_B.mergeYupYdown(); - } else { - // Distinct fields - f_B.splitYupYdown(); - f_B.yup() = f.yup() / Bxy_floc; - f_B.ydown() = f.ydown() / Bxy_floc; - } - return Bxy * Grad_par(f_B, outloc, method); + if (!f.hasYupYdown()) { + // No yup/ydown fields. The Grad_par operator will + // shift to field aligned coordinates + return Bxy * Grad_par(f / Bxy_floc, outloc, method); } - // No yup/ydown fields. The Grad_par operator will - // shift to field aligned coordinates - return Bxy * Grad_par(f / Bxy_floc, outloc, method); + // Need to modify yup and ydown fields + Field3D f_B = f / Bxy_floc; + if (&f.yup() == &f) { + // Identity, yup and ydown point to same field + f_B.mergeYupYdown(); + } else { + // Distinct fields + f_B.splitYupYdown(); + f_B.yup() = f.yup() / Bxy_floc; + f_B.ydown() = f.ydown() / Bxy_floc; + } + return Bxy * Grad_par(f_B, outloc, method); } ///////////////////////////////////////////////////////// diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 072c9ed93c..1aaafb7598 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -241,22 +241,23 @@ const Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, Coordinates *metric = f.getCoordinates(outloc); Field2D Bxy_floc = f.getCoordinates()->Bxy; - if (f.hasYupYdown()) { - // Need to modify yup and ydown fields - Field3D f_B = f / Bxy_floc; - if (&f.yup() == &f) { - // Identity, yup and ydown point to same field - f_B.mergeYupYdown(); - } else { - // Distinct fields - f_B.splitYupYdown(); - f_B.yup() = f.yup() / Bxy_floc; - f_B.ydown() = f.ydown() / Bxy_floc; - } - return metric->Bxy*FDDY(v, f_B, outloc, method)/sqrt(metric->g_22); + + if (!f.hasYupYdown()) { + return metric->Bxy*FDDY(v, f/Bxy_floc, outloc, method)/sqrt(metric->g_22); } - return metric->Bxy*FDDY(v, f/Bxy_floc, outloc, method)/sqrt(metric->g_22); + // Need to modify yup and ydown fields + Field3D f_B = f / Bxy_floc; + if (&f.yup() == &f) { + // Identity, yup and ydown point to same field + f_B.mergeYupYdown(); + } else { + // Distinct fields + f_B.splitYupYdown(); + f_B.yup() = f.yup() / Bxy_floc; + f_B.ydown() = f.ydown() / Bxy_floc; + } + return metric->Bxy*FDDY(v, f_B, outloc, method)/sqrt(metric->g_22); } const Field3D Div_par_flux(const Field3D &v, const Field3D &f, DIFF_METHOD method, CELL_LOC outloc) { From 3fe02cbf694d299eb1ce7b5eda59d84ca029087c Mon Sep 17 00:00:00 2001 From: John Omotani Date: Thu, 11 Oct 2018 20:52:05 +0100 Subject: [PATCH 62/69] Handle CELL_ZLOW case in boundary_standard.cxx Previously, fields at CELL_ZLOW had nothing done by any boundary condition operator. This commit passes them through to the unstaggered case, which is correct since there are no z-boundaries so no special handling is needed. --- src/mesh/boundary_standard.cxx | 52 +++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 44f910d74d..f5f1d9b6a0 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -135,7 +135,7 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -271,6 +271,8 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryDirichlet."); } } else { // Non-staggered, standard case @@ -321,7 +323,7 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -473,6 +475,8 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryDirichlet."); } } else { @@ -587,7 +591,7 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW) { @@ -719,6 +723,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryDirichlet_O3."); } } else { @@ -771,7 +777,7 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -921,6 +927,8 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryDirichlet_O3."); } } else { @@ -1002,7 +1010,7 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if(loc == CELL_XLOW ) { @@ -1145,6 +1153,8 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryDirichlet_O4."); } } else { @@ -1198,7 +1208,7 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -1353,6 +1363,8 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryDirichlet_O4."); } } else { @@ -1712,7 +1724,7 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently // Use one-sided differencing. Cell is now on // the boundary, so use one-sided differencing @@ -1861,6 +1873,8 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryNeumann."); } } else { @@ -1909,7 +1923,7 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently // Use one-sided differencing. Cell is now on // the boundary, so use one-sided differencing @@ -2065,6 +2079,8 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryNeumann."); } } else { @@ -2134,7 +2150,7 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { throw BoutException("neumann_o4 not implemented with staggered grid yet"); } else { @@ -2188,7 +2204,7 @@ void BoundaryNeumann_O4::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { throw BoutException("neumann_o4 not implemented with staggered grid yet"); } else { @@ -2796,7 +2812,7 @@ void BoundaryFree_O2::apply(Field2D &f) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW) { @@ -2869,6 +2885,8 @@ void BoundaryFree_O2::apply(Field2D &f) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryFree_O2."); } } else { @@ -2894,7 +2912,7 @@ void BoundaryFree_O2::apply(Field3D &f) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -2983,6 +3001,8 @@ void BoundaryFree_O2::apply(Field3D &f) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryFree_O2."); } } else { @@ -3033,7 +3053,7 @@ void BoundaryFree_O3::apply(Field2D &f) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW) { @@ -3107,6 +3127,8 @@ void BoundaryFree_O3::apply(Field2D &f) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryFree_O3."); } } else { @@ -3132,7 +3154,7 @@ void BoundaryFree_O3::apply(Field3D &f) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE) { + if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -3228,6 +3250,8 @@ void BoundaryFree_O3::apply(Field3D &f) { } } } + } else { + throw BoutException("Unhandled staggering in BoundaryFree_O3."); } } else { From 3657ce80404cd9c7b784f68b0d7c926128eea30a Mon Sep 17 00:00:00 2001 From: John Omotani Date: Thu, 11 Oct 2018 12:28:09 +0100 Subject: [PATCH 63/69] Remove uses of global mesh from boundary conditions Requires adding a Mesh* pointer and getDataMesh() method to FieldData, so that FieldData::setBoundary() can use the local mesh. getDataMesh() method is needed in case the FieldData is constructed before the global mesh is created (i.e. when Field3D, etc. are declared in global scope). It must not be called getMesh() because that would clash with the method of Field. --- include/field_data.hxx | 11 +- src/field/field2d.cxx | 8 +- src/field/field3d.cxx | 13 +- src/field/field_data.cxx | 17 +- src/field/vector2d.cxx | 9 +- src/field/vector3d.cxx | 11 +- src/mesh/boundary_standard.cxx | 838 ++++++++++++++++++--------------- 7 files changed, 500 insertions(+), 407 deletions(-) diff --git a/include/field_data.hxx b/include/field_data.hxx index c4fadd4e95..d75e89c2ca 100644 --- a/include/field_data.hxx +++ b/include/field_data.hxx @@ -62,12 +62,20 @@ class FieldVisitor; */ class FieldData { public: - FieldData(); + FieldData(Mesh* m); virtual ~FieldData(); // Visitor pattern support virtual void accept(FieldVisitor &v) = 0; + virtual Mesh * getDataMesh() const{ + if (fielddatamesh){ + return fielddatamesh; + } else { + return mesh; + } + } + // Defines interface which must be implemented virtual bool isReal() const = 0; ///< Returns true if field consists of BoutReal values virtual bool is3D() const = 0; ///< True if variable is 3D @@ -92,6 +100,7 @@ public: FieldGeneratorPtr getBndryGenerator(BndryLoc location); protected: + Mesh* fielddatamesh; vector bndry_op; ///< Boundary conditions bool boundaryIsCopy; ///< True if bndry_op is a copy bool boundaryIsSet; ///< Set to true when setBoundary called diff --git a/src/field/field2d.cxx b/src/field/field2d.cxx index ad44b43a1b..ad0885f2ab 100644 --- a/src/field/field2d.cxx +++ b/src/field/field2d.cxx @@ -45,7 +45,8 @@ #include -Field2D::Field2D(Mesh *localmesh) : Field(localmesh), deriv(nullptr) { +Field2D::Field2D(Mesh *localmesh) : + Field(localmesh), FieldData(localmesh), deriv(nullptr) { boundaryIsSet = false; @@ -66,6 +67,7 @@ Field2D::Field2D(Mesh *localmesh) : Field(localmesh), deriv(nullptr) { } Field2D::Field2D(const Field2D& f) : Field(f.fieldmesh), // The mesh containing array sizes + FieldData(f.fieldmesh), data(f.data), // This handles references to the data array deriv(nullptr) { TRACE("Field2D(Field2D&)"); @@ -95,7 +97,9 @@ Field2D::Field2D(const Field2D& f) : Field(f.fieldmesh), // The mesh containing boundaryIsSet = false; } -Field2D::Field2D(BoutReal val, Mesh *localmesh) : Field(localmesh), deriv(nullptr) { +Field2D::Field2D(BoutReal val, Mesh *localmesh) : + Field(localmesh), FieldData(localmesh), deriv(nullptr) { + boundaryIsSet = false; nx = fieldmesh->LocalNx; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 1143eb9fdc..7a141d2a7f 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -45,8 +45,8 @@ /// Constructor Field3D::Field3D(Mesh *localmesh) - : Field(localmesh), background(nullptr), deriv(nullptr), yup_field(nullptr), - ydown_field(nullptr) { + : Field(localmesh), FieldData(localmesh), background(nullptr), + deriv(nullptr), yup_field(nullptr), ydown_field(nullptr) { #ifdef TRACK name = ""; #endif @@ -71,6 +71,7 @@ Field3D::Field3D(Mesh *localmesh) /// later) Field3D::Field3D(const Field3D &f) : Field(f.fieldmesh), // The mesh containing array sizes + FieldData(f.fieldmesh), background(nullptr), data(f.data), // This handles references to the data array deriv(nullptr), yup_field(nullptr), ydown_field(nullptr) { @@ -100,8 +101,8 @@ Field3D::Field3D(const Field3D &f) } Field3D::Field3D(const Field2D &f) - : Field(f.getMesh()), background(nullptr), deriv(nullptr), yup_field(nullptr), - ydown_field(nullptr) { + : Field(f.getMesh()), FieldData(f.getMesh()), background(nullptr), + deriv(nullptr), yup_field(nullptr), ydown_field(nullptr) { TRACE("Field3D: Copy constructor from Field2D"); @@ -118,8 +119,8 @@ Field3D::Field3D(const Field2D &f) } Field3D::Field3D(const BoutReal val, Mesh *localmesh) - : Field(localmesh), background(nullptr), deriv(nullptr), yup_field(nullptr), - ydown_field(nullptr) { + : Field(localmesh), FieldData(localmesh), background(nullptr), + deriv(nullptr), yup_field(nullptr), ydown_field(nullptr) { TRACE("Field3D: Copy constructor from value"); diff --git a/src/field/field_data.cxx b/src/field/field_data.cxx index 6ab19709c7..48c48e4847 100644 --- a/src/field/field_data.cxx +++ b/src/field/field_data.cxx @@ -6,8 +6,11 @@ #include #include "unused.hxx" -FieldData::FieldData() : boundaryIsCopy(false), boundaryIsSet(true) { - +FieldData::FieldData(Mesh* m) : + fielddatamesh(m), boundaryIsCopy(false), boundaryIsSet(true) { + if (fielddatamesh == nullptr) { + fielddatamesh = mesh; + } } FieldData::~FieldData() { @@ -24,7 +27,7 @@ void FieldData::setBoundary(const string &name) { output_info << "Setting boundary for variable " << name << endl; /// Loop over the mesh boundary regions - for(const auto& reg : mesh->getBoundaries()) { + for(const auto& reg : getDataMesh()->getBoundaries()) { BoundaryOp* op = static_cast(bfact->createFromOptions(name, reg)); if (op != nullptr) bndry_op.push_back(op); @@ -32,9 +35,9 @@ void FieldData::setBoundary(const string &name) { } /// Get the mesh boundary regions - vector par_reg = mesh->getBoundariesPar(); + vector par_reg = getDataMesh()->getBoundariesPar(); /// Loop over the mesh parallel boundary regions - for(const auto& reg : mesh->getBoundariesPar()) { + for(const auto& reg : getDataMesh()->getBoundariesPar()) { BoundaryOpPar* op = static_cast(bfact->createFromOptions(name, reg)); if (op != nullptr) bndry_op_par.push_back(op); @@ -47,7 +50,7 @@ void FieldData::setBoundary(const string &name) { void FieldData::setBoundary(const string &UNUSED(region), BoundaryOp *op) { /// Get the mesh boundary regions - vector reg = mesh->getBoundaries(); + vector reg = getDataMesh()->getBoundaries(); /// Find the region @@ -76,7 +79,7 @@ void FieldData::addBndryFunction(FuncPtr userfunc, BndryLoc location){ void FieldData::addBndryGenerator(FieldGeneratorPtr gen, BndryLoc location) { if(location == BNDRY_ALL){ - for(const auto& reg : mesh->getBoundaries()) { + for(const auto& reg : getDataMesh()->getBoundaries()) { bndry_generator[reg->location] = gen; } } else { diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index 2a931dbbbb..5677b4cd1e 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -36,11 +36,12 @@ #include Vector2D::Vector2D(Mesh *localmesh) - : x(localmesh), y(localmesh), z(localmesh), covariant(true), deriv(nullptr), location(CELL_CENTRE) {} + : FieldData(localmesh), x(localmesh), y(localmesh), z(localmesh), + covariant(true), deriv(nullptr), location(CELL_CENTRE) {} Vector2D::Vector2D(const Vector2D &f) - : x(f.x), y(f.y), z(f.z), covariant(f.covariant), deriv(nullptr), - location(f.getLocation()) {} + : FieldData(f.fielddatamesh), x(f.x), y(f.y), z(f.z), covariant(f.covariant), + deriv(nullptr), location(f.getLocation()) {} Vector2D::~Vector2D() { if (deriv != nullptr) { @@ -148,6 +149,8 @@ Vector2D* Vector2D::timeDeriv() { /////////////////// ASSIGNMENT //////////////////// Vector2D & Vector2D::operator=(const Vector2D &rhs) { + fielddatamesh = rhs.fielddatamesh; + x = rhs.x; y = rhs.y; z = rhs.z; diff --git a/src/field/vector3d.cxx b/src/field/vector3d.cxx index 9855e422ed..8996efc824 100644 --- a/src/field/vector3d.cxx +++ b/src/field/vector3d.cxx @@ -37,11 +37,12 @@ #include Vector3D::Vector3D(Mesh *localmesh) - : x(localmesh), y(localmesh), z(localmesh), covariant(true), deriv(nullptr), location(CELL_CENTRE) {} + : FieldData(localmesh), x(localmesh), y(localmesh), z(localmesh), + covariant(true), deriv(nullptr), location(CELL_CENTRE) {} Vector3D::Vector3D(const Vector3D &f) - : x(f.x), y(f.y), z(f.z), covariant(f.covariant), deriv(nullptr), - location(f.getLocation()) {} + : FieldData(f.fielddatamesh), x(f.x), y(f.y), z(f.z), covariant(f.covariant), + deriv(nullptr), location(f.getLocation()) {} Vector3D::~Vector3D() { if (deriv != nullptr) { @@ -149,6 +150,8 @@ Vector3D* Vector3D::timeDeriv() { /////////////////// ASSIGNMENT //////////////////// Vector3D & Vector3D::operator=(const Vector3D &rhs) { + fielddatamesh = rhs.fielddatamesh; + x = rhs.x; y = rhs.y; z = rhs.z; @@ -160,6 +163,8 @@ Vector3D & Vector3D::operator=(const Vector3D &rhs) { } Vector3D & Vector3D::operator=(const Vector2D &rhs) { + fielddatamesh = rhs.x.getMesh(); + x = rhs.x; y = rhs.y; z = rhs.z; diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index f5f1d9b6a0..0dc8936ed2 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -23,88 +23,92 @@ lead to an out of bounds access error later but we add it here to provide a more explanatory message. */ -void verifyNumPoints(BoundaryRegion *region, int ptsRequired) { - TRACE("Verifying number of points available for BC"); +namespace { + void verifyNumPoints(BoundaryRegion *region, int ptsRequired) { + TRACE("Verifying number of points available for BC"); #ifndef CHECK - return; //No checking so just return + return; //No checking so just return #else - int ptsAvailGlobal, ptsAvailLocal, ptsAvail; - string side, gridType; - - //Initialise var in case of no match and CHECK<=2 - ptsAvail = ptsRequired; //Ensures test passes without exception - - switch(region->location) { - case BNDRY_XIN: - case BNDRY_XOUT: { - side = "x"; - - //Here 2*mesh->xstart is the total number of guard/boundary cells - ptsAvailGlobal = mesh->GlobalNx - 2*mesh->xstart; - - //Work out how many processor local points we have excluding boundaries - //but including ghost/guard cells - ptsAvailLocal = mesh->LocalNx; - if(mesh->firstX()) ptsAvailLocal -= mesh->xstart; - if(mesh->lastX()) ptsAvailLocal -= mesh->xstart; - - //Now decide if it's a local or global limit, prefer global if a tie - if(ptsAvailGlobal <= ptsAvailLocal){ - ptsAvail = ptsAvailGlobal; - gridType = "global"; - }else{ - ptsAvail = ptsAvailLocal; - gridType = "local"; - } + Mesh* localmesh = region->localmesh; - break; - } - case BNDRY_YUP: - case BNDRY_YDOWN: { - side = "y"; + int ptsAvailGlobal, ptsAvailLocal, ptsAvail; + string side, gridType; + + //Initialise var in case of no match and CHECK<=2 + ptsAvail = ptsRequired; //Ensures test passes without exception + + switch(region->location) { + case BNDRY_XIN: + case BNDRY_XOUT: { + side = "x"; + + //Here 2*localmesh->xstart is the total number of guard/boundary cells + ptsAvailGlobal = localmesh->GlobalNx - 2*localmesh->xstart; - //Here 2*mesh->ystart is the total number of guard/boundary cells - ptsAvailGlobal = mesh->GlobalNy - 2*mesh->ystart; + //Work out how many processor local points we have excluding boundaries + //but including ghost/guard cells + ptsAvailLocal = localmesh->LocalNx; + if(localmesh->firstX()) ptsAvailLocal -= localmesh->xstart; + if(localmesh->lastX()) ptsAvailLocal -= localmesh->xstart; - //Work out how many processor local points we have excluding boundaries - //but including ghost/guard cells - ptsAvailLocal = mesh->LocalNy; - if(mesh->firstY()) ptsAvailLocal -= mesh->ystart; - if(mesh->lastY()) ptsAvailLocal -= mesh->ystart; + //Now decide if it's a local or global limit, prefer global if a tie + if(ptsAvailGlobal <= ptsAvailLocal){ + ptsAvail = ptsAvailGlobal; + gridType = "global"; + }else{ + ptsAvail = ptsAvailLocal; + gridType = "local"; + } - //Now decide if it's a local or global limit, prefer global if a tie - if(ptsAvailGlobal <= ptsAvailLocal){ - ptsAvail = ptsAvailGlobal; - gridType = "global"; - }else{ - ptsAvail = ptsAvailLocal; - gridType = "local"; + break; } + case BNDRY_YUP: + case BNDRY_YDOWN: { + side = "y"; - break; - } + //Here 2*localmesh->ystart is the total number of guard/boundary cells + ptsAvailGlobal = localmesh->GlobalNy - 2*localmesh->ystart; + + //Work out how many processor local points we have excluding boundaries + //but including ghost/guard cells + ptsAvailLocal = localmesh->LocalNy; + if(localmesh->firstY()) ptsAvailLocal -= localmesh->ystart; + if(localmesh->lastY()) ptsAvailLocal -= localmesh->ystart; + + //Now decide if it's a local or global limit, prefer global if a tie + if(ptsAvailGlobal <= ptsAvailLocal){ + ptsAvail = ptsAvailGlobal; + gridType = "global"; + }else{ + ptsAvail = ptsAvailLocal; + gridType = "local"; + } + + break; + } #if CHECK > 2 //Only fail on Unrecognised boundary for extreme checking - default : { - throw BoutException("Unrecognised boundary region (%s) for verifyNumPoints.",region->location); - } + default : { + throw BoutException("Unrecognised boundary region (%s) for verifyNumPoints.",region->location); + } #endif - } + } - //Now check we have enough points and if not throw an exception - if(ptsAvail < ptsRequired){ - throw BoutException("Too few %s grid points for %s boundary, have %d but need at least %d", - gridType.c_str(),side.c_str(),ptsAvail,ptsRequired); - } + //Now check we have enough points and if not throw an exception + if(ptsAvail < ptsRequired){ + throw BoutException("Too few %s grid points for %s boundary, have %d but need at least %d", + gridType.c_str(),side.c_str(),ptsAvail,ptsRequired); + } #endif + } } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryDirichlet::clone(BoundaryRegion *region, const list &args){ - verifyNumPoints(region,1); + verifyNumPoints(region, 1); std::shared_ptr newgen; if(!args.empty()) { @@ -122,6 +126,8 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -135,7 +141,7 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -146,9 +152,9 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -167,9 +173,9 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -190,8 +196,8 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { if(fg) { // x norm is shifted by half a grid point because it is staggered. // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); @@ -200,8 +206,8 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { for(int i=1;iwidth;i++) { int xi = bndry->x ; int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); - } + f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); + } } } } @@ -213,9 +219,9 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -233,9 +239,9 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { // Lower y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -255,10 +261,10 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); @@ -281,11 +287,11 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { if(fg) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -311,6 +317,8 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -323,7 +331,7 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -333,13 +341,13 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Outer x boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y, zk) = val; @@ -357,13 +365,13 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x - bndry->bx,bndry->y, zk) = val; f(bndry->x,bndry->y, zk) = f(bndry->x - bndry->bx,bndry->y, zk); @@ -383,12 +391,12 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is shifted by half a grid point because it is staggered. // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); @@ -410,11 +418,11 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Upper y boundary boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y,zk) = val; @@ -432,12 +440,12 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Lower y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y - bndry->by, zk) = val; @@ -454,14 +462,14 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { if(bndry->bx != 0){ // x boundaries for(; !bndry->isDone(); bndry->next1d()) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); @@ -483,15 +491,15 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Standard (non-staggered) case for(; !bndry->isDone(); bndry->next1d()) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); @@ -529,11 +537,11 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { // Set any other guard cells using the values on the cells int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; - xnorm = mesh->GlobalX(xi); - ynorm = mesh->GlobalY(yi); - for(int zk=0;zkLocalNz;zk++) { + xnorm = localmesh->GlobalX(xi); + ynorm = localmesh->GlobalY(yi); + for(int zk=0;zkLocalNz;zk++) { if(fg) { - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(xi, yi, zk) = val; } @@ -550,9 +558,10 @@ void BoundaryDirichlet::apply_ddt(Field2D &f) { } void BoundaryDirichlet::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } @@ -561,7 +570,7 @@ void BoundaryDirichlet::apply_ddt(Field3D &f) { // New implementation, accurate to higher order BoundaryOp* BoundaryDirichlet_O3::clone(BoundaryRegion *region, const list &args){ - verifyNumPoints(region,2); + verifyNumPoints(region, 2); std::shared_ptr newgen = nullptr; if(!args.empty()) { // First argument should be an expression @@ -578,6 +587,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -591,7 +602,7 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW) { @@ -601,8 +612,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Outer x boundary for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -620,8 +631,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } f(bndry->x - bndry->bx,bndry->y) = val; @@ -638,9 +649,9 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -665,8 +676,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -685,8 +696,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Lower y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -707,8 +718,8 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { if(fg) { // x norm is located half way between first grid cell and guard cell. // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -734,11 +745,11 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { if(fg) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -765,6 +776,8 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -777,7 +790,7 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -787,12 +800,12 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Outer x boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y, zk) = val; @@ -810,12 +823,12 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x - bndry->bx,bndry->y, zk) = val; @@ -834,13 +847,13 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; @@ -862,11 +875,11 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Upper y boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y,zk) = val; @@ -884,12 +897,12 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Lower y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*(mesh->GlobalY(bndry->y)+ mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*(localmesh->GlobalY(bndry->y)+ localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y - bndry->by, zk) = val; @@ -908,12 +921,12 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is located half way between first grid cell and guard cell. // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; @@ -935,15 +948,15 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { // Standard (non-staggered) case for(; !bndry->isDone(); bndry->next1d()) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; @@ -966,11 +979,11 @@ void BoundaryDirichlet_O3::apply_ddt(Field2D &f) { } void BoundaryDirichlet_O3::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); - bndry->first() ; for(bndry->first(); !bndry->isDone(); bndry->next()){ - for(int z=0;zLocalNz;z++){ + for(int z=0;zLocalNz;z++){ (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } } @@ -980,7 +993,7 @@ void BoundaryDirichlet_O3::apply_ddt(Field3D &f) { // Extrapolate to calculate boundary cell to 4th-order BoundaryOp* BoundaryDirichlet_O4::clone(BoundaryRegion *region, const list &args){ - verifyNumPoints(region,3); + verifyNumPoints(region, 3); std::shared_ptr newgen = nullptr; if(!args.empty()) { // First argument should be an expression @@ -997,6 +1010,8 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -1010,7 +1025,7 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if(loc == CELL_XLOW ) { @@ -1021,8 +1036,8 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } f(bndry->x,bndry->y) = val; @@ -1041,9 +1056,9 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { // Inner boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -1065,8 +1080,8 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { if(fg) { // x norm is shifted by half a grid point because it is staggered. // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -1090,9 +1105,9 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } f(bndry->x,bndry->y) = val; @@ -1110,9 +1125,9 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { // Inner y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -1136,8 +1151,8 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { if(fg) { // x norm is located half way between first grid cell and guard cell. // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -1164,11 +1179,11 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { if(fg) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } @@ -1196,6 +1211,8 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -1208,7 +1225,7 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -1218,13 +1235,13 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Outer x boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y, zk) = val; @@ -1242,13 +1259,13 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x - bndry->bx,bndry->y, zk) = val; @@ -1268,12 +1285,12 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is shifted by half a grid point because it is staggered. // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) { - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); } f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); @@ -1295,12 +1312,12 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Outer y boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = val; @@ -1318,13 +1335,13 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Inner y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y - bndry->by, zk) = val; @@ -1344,12 +1361,12 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is located half way between first grid cell and guard cell. // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); @@ -1371,15 +1388,15 @@ void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { // Standard (non-staggered) case for(; !bndry->isDone(); bndry->next1d()) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz), t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); @@ -1402,9 +1419,10 @@ void BoundaryDirichlet_O4::apply_ddt(Field2D &f) { } void BoundaryDirichlet_O4::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } @@ -1413,7 +1431,7 @@ void BoundaryDirichlet_O4::apply_ddt(Field3D &f) { BoundaryOp* BoundaryDirichlet_2ndOrder::clone(BoundaryRegion *region, const list &args) { output << "WARNING: Use of boundary condition \"dirichlet_2ndorder\" is deprecated!\n"; output << " Consider using \"dirichlet\" instead\n"; - verifyNumPoints(region,2); + verifyNumPoints(region, 2); if(!args.empty()) { // First argument should be a value val = stringToReal(args.front()); @@ -1436,10 +1454,11 @@ void BoundaryDirichlet_2ndOrder::apply(Field2D &f) { } void BoundaryDirichlet_2ndOrder::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used for(bndry->first(); !bndry->isDone(); bndry->next1d()) - for(int z=0;zLocalNz;z++) { + for(int z=0;zLocalNz;z++) { f(bndry->x,bndry->y,z) = 8./3.*val - 2.*f(bndry->x-bndry->bx,bndry->y-bndry->by,z) + 1./3.*f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by,z); #ifdef BOUNDARY_CONDITIONS_UPGRADE_EXTRAPOLATE_FOR_2ND_ORDER f(bndry->x+bndry->bx,bndry->y+bndry->by,z) = 3.*f(bndry->x,bndry->y,z) - 3.*f(bndry->x-bndry->bx,bndry->y-bndry->by,z) + f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by,z); @@ -1456,16 +1475,17 @@ void BoundaryDirichlet_2ndOrder::apply_ddt(Field2D &f) { } void BoundaryDirichlet_2ndOrder::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryDirichlet_4thOrder::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,4); + verifyNumPoints(region, 4); if(!args.empty()) { // First argument should be a value val = stringToReal(args.front()); @@ -1483,9 +1503,10 @@ void BoundaryDirichlet_4thOrder::apply(Field2D &f) { } void BoundaryDirichlet_4thOrder::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); // Set (at 4th order) the value at the mid-point between the guard cell and the grid cell to be val for(bndry->first(); !bndry->isDone(); bndry->next1d()) - for(int z=0;zLocalNz;z++) { + for(int z=0;zLocalNz;z++) { f(bndry->x,bndry->y,z) = 128./35.*val - 4.*f(bndry->x-bndry->bx,bndry->y-bndry->by,z) + 2.*f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by,z) - 4./3.*f(bndry->x-3*bndry->bx,bndry->y-3*bndry->by,z) + 1./7.*f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by,z); f(bndry->x+bndry->bx,bndry->y+bndry->by,z) = -128./5.*val + 9.*f(bndry->x,bndry->y,z) + 18.*f(bndry->x-bndry->bx,bndry->y-bndry->by,z) -4.*f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by,z) + 3./5.*f(bndry->x-3*bndry->bx,bndry->y-3*bndry->by,z); } @@ -1498,16 +1519,17 @@ void BoundaryDirichlet_4thOrder::apply_ddt(Field2D &f) { } void BoundaryDirichlet_4thOrder::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryNeumann_NonOrthogonal::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,1); + verifyNumPoints(region, 1); if(!args.empty()) { output << "WARNING: arguments is set to BoundaryNeumann None Zero Gradient\n"; // First argument should be a value @@ -1518,9 +1540,10 @@ BoundaryOp* BoundaryNeumann_NonOrthogonal::clone(BoundaryRegion *region, const l } void BoundaryNeumann_NonOrthogonal::apply(Field2D &f) { + Mesh* localmesh = f.getMesh(); Coordinates *metric = f.getCoordinates(); // Calculate derivatives for metric use - mesh->communicate(f); + localmesh->communicate(f); Field2D dfdy = DDY(f); // Loop over all elements and set equal to the next point in for(bndry->first(); !bndry->isDone(); bndry->next1d()) { @@ -1558,9 +1581,10 @@ void BoundaryNeumann_NonOrthogonal::apply(Field2D &f) { } void BoundaryNeumann_NonOrthogonal::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); Coordinates *metric = f.getCoordinates(); // Calculate derivatives for metric use - mesh->communicate(f); + localmesh->communicate(f); Field3D dfdy = DDY(f); Field3D dfdz = DDZ(f); // Loop over all elements and set equal to the next point in @@ -1572,7 +1596,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D &f) { // Have to use derivatives at last gridpoint instead of derivatives on boundary layer // because derivative values don't exist in boundary region // NOTE: should be fixed to interpolate to boundary line - for(int z=0;zLocalNz;z++) { + for(int z=0;zLocalNz;z++) { BoutReal xshift = g12shift*dfdy(bndry->x-bndry->bx,bndry->y,z) + g13shift*dfdz(bndry->x-bndry->bx,bndry->y,z); if(bndry->bx != 0 && bndry->by == 0) { @@ -1606,7 +1630,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D &f) { BoundaryOp* BoundaryNeumann2::clone(BoundaryRegion *region, const list &args) { output << "WARNING: Use of boundary condition \"neumann2\" is deprecated!\n"; output << " Consider using \"neumann\" instead\n"; - verifyNumPoints(region,2); + verifyNumPoints(region, 2); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryNeumann2\n"; } @@ -1620,8 +1644,9 @@ void BoundaryNeumann2::apply(Field2D &f) { } void BoundaryNeumann2::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) f(bndry->x, bndry->y, z) = (4.*f(bndry->x - bndry->bx, bndry->y - bndry->by, z) - f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, z))/3.; } @@ -1631,9 +1656,9 @@ BoundaryOp* BoundaryNeumann_2ndOrder::clone(BoundaryRegion *region, const listfirst(); !bndry->isDone(); bndry->next1d()) - for(int z=0;zLocalNz;z++) { + for(int z=0;zLocalNz;z++) { BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); f(bndry->x,bndry->y,z) = f(bndry->x-bndry->bx,bndry->y-bndry->by,z) + val*delta; #ifdef BOUNDARY_CONDITIONS_UPGRADE_EXTRAPOLATE_FOR_2ND_ORDER @@ -1683,16 +1709,17 @@ void BoundaryNeumann_2ndOrder::apply_ddt(Field2D &f) { } void BoundaryNeumann_2ndOrder::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryNeumann::clone(BoundaryRegion *region, const list &args){ - verifyNumPoints(region,1); + verifyNumPoints(region, 1); std::shared_ptr newgen = nullptr; if(!args.empty()) { // First argument should be an expression @@ -1710,6 +1737,8 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + Coordinates *metric = f.getCoordinates(); bndry->first(); @@ -1724,7 +1753,7 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently // Use one-sided differencing. Cell is now on // the boundary, so use one-sided differencing @@ -1738,9 +1767,9 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); } @@ -1762,9 +1791,9 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { if(fg) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); } @@ -1790,8 +1819,8 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { if(fg) { // x norm is shifted by half a grid point because it is staggered. // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); } @@ -1811,9 +1840,9 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); } @@ -1835,9 +1864,9 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { if(fg) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y - bndry->by); } @@ -1861,8 +1890,8 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { if(fg) { // x norm is located half way between first grid cell and guard cell. // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); } @@ -1885,11 +1914,11 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { if(fg) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); } @@ -1909,6 +1938,8 @@ void BoundaryNeumann::apply(Field3D &f) { void BoundaryNeumann::apply(Field3D &f,BoutReal t) { + Mesh* localmesh = f.getMesh(); + Coordinates *metric = f.getCoordinates(); bndry->first(); @@ -1923,7 +1954,7 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently // Use one-sided differencing. Cell is now on // the boundary, so use one-sided differencing @@ -1934,13 +1965,13 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { if(bndry->bx > 0) { // Outer x boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t) * metric->dx(bndry->x, bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dx(bndry->x, bndry->y); f(bndry->x,bndry->y, zk) = (4.*f(bndry->x - bndry->bx, bndry->y,zk) - f(bndry->x - 2*bndry->bx, bndry->y,zk) + 2.*val)/3.; @@ -1960,14 +1991,14 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { // Inner x boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) - + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = mesh->GlobalY(bndry->y); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t) * metric->dx(bndry->x - bndry->bx, bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dx(bndry->x - bndry->bx, bndry->y); f(bndry->x - bndry->bx,bndry->y, zk) = (4.*f(bndry->x - 2*bndry->bx, bndry->y,zk) - f(bndry->x - 3*bndry->bx, bndry->y,zk) - 2.*val)/3.; @@ -1987,14 +2018,14 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is shifted by half a grid point because it is staggered. // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - bndry->by) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; if (bndry->width == 2){ @@ -2011,13 +2042,13 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { // Outer y boundary for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t) * metric->dy(bndry->x, bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dy(bndry->x, bndry->y); } f(bndry->x,bndry->y,zk) = (4.*f(bndry->x, bndry->y - bndry->by,zk) - f(bndry->x, bndry->y - 2*bndry->by,zk) + 2.*val)/3.; @@ -2037,12 +2068,12 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { // Inner y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = mesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) - + mesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t) * metric->dy(bndry->x, bndry->y - bndry->by); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dy(bndry->x, bndry->y - bndry->by); f(bndry->x,bndry->y - bndry->by,zk) = (4.*f(bndry->x, bndry->y - 2*bndry->by,zk) - f(bndry->x, bndry->y - 3*bndry->by,zk) - 2.*val)/3.; @@ -2063,14 +2094,14 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { for(; !bndry->isDone(); bndry->next1d()) { // x norm is located half way between first grid cell and guard cell. // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) + mesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) + mesh->GlobalY(bndry->y - 1) ); + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; if (bndry->width == 2){ @@ -2086,17 +2117,17 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { else { for(; !bndry->isDone(); bndry->next1d()) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; if (bndry->width == 2){ @@ -2114,9 +2145,10 @@ void BoundaryNeumann::apply_ddt(Field2D &f) { } void BoundaryNeumann::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } @@ -2139,6 +2171,8 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { // Set (at 4th order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -2150,7 +2184,7 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { throw BoutException("neumann_o4 not implemented with staggered grid yet"); } else { @@ -2163,11 +2197,11 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { if(fg) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); } @@ -2193,6 +2227,8 @@ void BoundaryNeumann_O4::apply(Field3D &f) { } void BoundaryNeumann_O4::apply(Field3D &f,BoutReal t) { + Mesh* localmesh = f.getMesh(); + bndry->first(); // Decide which generator to use @@ -2204,24 +2240,24 @@ void BoundaryNeumann_O4::apply(Field3D &f,BoutReal t) { // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { throw BoutException("neumann_o4 not implemented with staggered grid yet"); } else { Coordinates *coords = f.getCoordinates(); for(; !bndry->isDone(); bndry->next1d()) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( mesh->GlobalX(bndry->x) // In the guard cell - + mesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell BoutReal delta = bndry->bx*coords->dx(bndry->x,bndry->y)+bndry->by*coords->dy(bndry->x,bndry->y); - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = 12.*delta*val/11. @@ -2248,16 +2284,17 @@ void BoundaryNeumann_O4::apply_ddt(Field2D &f) { } void BoundaryNeumann_O4::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryNeumann_4thOrder::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,4); + verifyNumPoints(region, 4); if(!args.empty()) { // First argument should be a value val = stringToReal(args.front()); @@ -2278,11 +2315,12 @@ void BoundaryNeumann_4thOrder::apply(Field2D &f) { } void BoundaryNeumann_4thOrder::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); Coordinates *metric = f.getCoordinates(); // Set (at 4th order) the gradient at the mid-point between the guard cell and the grid cell to be val // This sets the value of the co-ordinate derivative, i.e. DDX/DDY not Grad_par/Grad_perp.x for(bndry->first(); !bndry->isDone(); bndry->next1d()) - for(int z=0;zLocalNz;z++) { + for(int z=0;zLocalNz;z++) { BoutReal delta = -(bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y)); f(bndry->x,bndry->y,z) = 12.*delta/11.*val + 17./22.*f(bndry->x-bndry->bx,bndry->y-bndry->by,z) + 9./22.*f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by,z) - 5./22.*f(bndry->x-3*bndry->bx,bndry->y-3*bndry->by,z) + 1./22.*f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by,z); f(bndry->x+bndry->bx,bndry->y+bndry->by,z) = -24.*delta*val + 27.*f(bndry->x,bndry->y,z) - 27.*f(bndry->x-bndry->bx,bndry->y-bndry->by,z) + f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by,z); // The f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by,z) term vanishes, so that this sets to zero the 4th order central difference first derivative at the point half way between the guard cell and the grid cell @@ -2296,16 +2334,17 @@ void BoundaryNeumann_4thOrder::apply_ddt(Field2D &f) { } void BoundaryNeumann_4thOrder::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryNeumannPar::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,1); + verifyNumPoints(region, 1); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryNeumann2\n"; } @@ -2321,16 +2360,17 @@ void BoundaryNeumannPar::apply(Field2D &f) { } void BoundaryNeumannPar::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); Coordinates *metric = f.getCoordinates(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) f(bndry->x,bndry->y,z) = f(bndry->x - bndry->bx,bndry->y - bndry->by,z)*sqrt(metric->g_22(bndry->x, bndry->y)/metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryRobin::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,1); + verifyNumPoints(region, 1); BoutReal a = 0.5, b = 1.0, g = 0.; list::const_iterator it = args.begin(); @@ -2374,16 +2414,17 @@ void BoundaryRobin::apply(Field2D &f) { } void BoundaryRobin::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); if(fabs(bval) < 1.e-12) { for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) f(bndry->x, bndry->y, z) = gval / aval; }else { BoutReal sign = 1.; if( (bndry->bx < 0) || (bndry->by < 0)) sign = -1.; for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) f(bndry->x, bndry->y, z) = f(bndry->x - bndry->bx, bndry->y - bndry->by, z) + sign*(gval - aval*f(bndry->x - bndry->bx, bndry->y - bndry->by, z) ) / bval; } } @@ -2397,15 +2438,16 @@ void BoundaryConstGradient::apply(Field2D &f){ } void BoundaryConstGradient::apply(Field3D &f) { + Mesh* localmesh = f.getMesh(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) f(bndry->x, bndry->y, z) = 2.*f(bndry->x - bndry->bx, bndry->y - bndry->by, z) - f(bndry->x - 2*bndry->bx,bndry->y - 2*bndry->by,z); } /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryConstGradient::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,2); + verifyNumPoints(region, 2); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryConstGradient\n"; } @@ -2415,7 +2457,7 @@ BoundaryOp* BoundaryConstGradient::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,2); + verifyNumPoints(region, 2); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryZeroLaplace\n"; } @@ -2445,7 +2487,9 @@ void BoundaryZeroLaplace::apply(Field2D &f) { } void BoundaryZeroLaplace::apply(Field3D &f) { - int ncz = mesh->LocalNz; + Mesh* localmesh = f.getMesh(); + + int ncz = localmesh->LocalNz; Coordinates *metric = f.getCoordinates(); @@ -2468,8 +2512,8 @@ void BoundaryZeroLaplace::apply(Field3D &f) { int y = bndry->y; // Take FFT of last 2 points in domain - rfft(f(x - bx, y), mesh->LocalNz, c0.begin()); - rfft(f(x - 2 * bx, y), mesh->LocalNz, c1.begin()); + rfft(f(x - bx, y), localmesh->LocalNz, c0.begin()); + rfft(f(x - 2 * bx, y), localmesh->LocalNz, c1.begin()); c1[0] = c0[0] - c1[0]; // Only need gradient // Solve metric->g11*d2f/dx2 - metric->g33*kz^2f = 0 @@ -2488,7 +2532,7 @@ void BoundaryZeroLaplace::apply(Field3D &f) { c0[jz] *= exp(coef * kwave); // The decaying solution only } // Reverse FFT - irfft(c0.begin(), mesh->LocalNz, f(x, y)); + irfft(c0.begin(), localmesh->LocalNz, f(x, y)); bndry->nextX(); x = bndry->x; @@ -2501,7 +2545,7 @@ void BoundaryZeroLaplace::apply(Field3D &f) { BoundaryOp *BoundaryZeroLaplace2::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region, 3); + verifyNumPoints(region, 3); if (!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryZeroLaplace2\n"; } @@ -2535,7 +2579,9 @@ void BoundaryZeroLaplace2::apply(Field2D &f) { } void BoundaryZeroLaplace2::apply(Field3D &f) { - int ncz = mesh->LocalNz; + Mesh* localmesh = f.getMesh(); + + int ncz = localmesh->LocalNz; ASSERT0(ncz % 2 == 0); // Allocation assumes even number @@ -2588,7 +2634,7 @@ void BoundaryZeroLaplace2::apply(Field3D &f) { /////////////////////////////////////////////////////////////// BoundaryOp* BoundaryConstLaplace::clone(BoundaryRegion *region, const list &args) { - verifyNumPoints(region,2); + verifyNumPoints(region, 2); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryConstLaplace\n"; } @@ -2631,9 +2677,11 @@ void BoundaryConstLaplace::apply(Field3D &f) { throw BoutException("ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); } + Mesh* localmesh = f.getMesh(); + Coordinates *metric = f.getCoordinates(); - int ncz = mesh->LocalNz; + int ncz = localmesh->LocalNz; // Allocate memory Array c0(ncz/2 + 1), c1(ncz/2 + 1), c2(ncz/2 + 1); @@ -2702,21 +2750,23 @@ void BoundaryDivCurl::apply(Vector3D &var) { int jx, jy, jz, jzp, jzm; BoutReal tmp; - Coordinates *metric = mesh->getCoordinates(var.getLocation()); + Mesh* localmesh = var.x.getMesh(); + + Coordinates *metric = localmesh->getCoordinates(var.getLocation()); - int ncz = mesh->LocalNz; + int ncz = localmesh->LocalNz; if(bndry->location != BNDRY_XOUT) { throw BoutException("ERROR: DivCurl boundary only works for outer X currently\n"); } var.toCovariant(); - if(mesh->xstart > 2) { + if(localmesh->xstart > 2) { throw BoutException("Error: Div = Curl = 0 boundary condition doesn't work for MXG > 2. Sorry\n"); } - jx = mesh->xend+1; - for(jy=1;jyLocalNy-1;jy++) { + jx = localmesh->xend+1; + for(jy=1;jyLocalNy-1;jy++) { for(jz=0;jzdy(jx-1,jy-1) + metric->dy(jx-1,jy)); var.y(jx,jy,jz) = var.y(jx-2,jy,jz) + (metric->dx(jx-2,jy) + metric->dx(jx-1,jy)) * tmp; - if(mesh->xstart == 2) + if(localmesh->xstart == 2) // 4th order to get last point var.y(jx+1,jy,jz) = var.y(jx-3,jy,jz) + 4.*metric->dx(jx,jy)*tmp; @@ -2736,7 +2786,7 @@ void BoundaryDivCurl::apply(Vector3D &var) { tmp = (var.x(jx-1,jy,jzp) - var.x(jx-1,jy,jzm)) / (2.*metric->dz); var.z(jx,jy,jz) = var.z(jx-2,jy,jz) + (metric->dx(jx-2,jy) + metric->dx(jx-1,jy)) * tmp; - if(mesh->xstart == 2) + if(localmesh->xstart == 2) var.z(jx+1,jy,jz) = var.z(jx-3,jy,jz) + 4.*metric->dx(jx,jy)*tmp; // d/dx( Jmetric->g11 B_x ) = - d/dx( Jmetric->g12 B_y + Jmetric->g13 B_z) @@ -2755,7 +2805,7 @@ void BoundaryDivCurl::apply(Vector3D &var) { var.x(jx,jy,jz) = ( metric->J(jx-2,jy)*metric->g11(jx-2,jy)*var.x(jx-2,jy,jz) + (metric->dx(jx-2,jy) + metric->dx(jx-1,jy)) * tmp ) / metric->J(jx,jy)*metric->g11(jx,jy); - if(mesh->xstart == 2) + if(localmesh->xstart == 2) var.x(jx+1,jy,jz) = ( metric->J(jx-3,jy)*metric->g11(jx-3,jy)*var.x(jx-3,jy,jz) + 4.*metric->dx(jx,jy)*tmp ) / metric->J(jx+1,jy)*metric->g11(jx+1,jy); } @@ -2796,7 +2846,7 @@ void BoundaryFree::apply_ddt(Field3D &UNUSED(f)) { // 2nd order extrapolation: BoundaryOp* BoundaryFree_O2::clone(BoundaryRegion *region, const list &args){ - verifyNumPoints(region,2); + verifyNumPoints(region, 2); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryFree\n"; } @@ -2807,12 +2857,14 @@ void BoundaryFree_O2::apply(Field2D &f) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + bndry->first(); // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW) { @@ -2908,11 +2960,12 @@ void BoundaryFree_O2::apply(Field3D &f) { bndry->first(); + Mesh* localmesh = f.getMesh(); // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -2923,7 +2976,7 @@ void BoundaryFree_O2::apply(Field3D &f) { for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -2936,7 +2989,7 @@ void BoundaryFree_O2::apply(Field3D &f) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=-1;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -2950,7 +3003,7 @@ void BoundaryFree_O2::apply(Field3D &f) { for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -2966,7 +3019,7 @@ void BoundaryFree_O2::apply(Field3D &f) { if(bndry->by > 0) { // Upper y boundary for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -2979,7 +3032,7 @@ void BoundaryFree_O2::apply(Field3D &f) { // Lower y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=-1;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -2992,7 +3045,7 @@ void BoundaryFree_O2::apply(Field3D &f) { // x boundaries for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3009,7 +3062,7 @@ void BoundaryFree_O2::apply(Field3D &f) { // Standard (non-staggered) case for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3027,9 +3080,10 @@ void BoundaryFree_O2::apply_ddt(Field2D &f) { } void BoundaryFree_O2::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } @@ -3038,7 +3092,7 @@ void BoundaryFree_O2::apply_ddt(Field3D &f) { // Third order extrapolation: ////////////////////////////////// BoundaryOp* BoundaryFree_O3::clone(BoundaryRegion *region, const list &args){ - verifyNumPoints(region,3); + verifyNumPoints(region, 3); if(!args.empty()) { output << "WARNING: Ignoring arguments to BoundaryConstLaplace\n"; @@ -3048,12 +3102,14 @@ BoundaryOp* BoundaryFree_O3::clone(BoundaryRegion *region, const list &a void BoundaryFree_O3::apply(Field2D &f) { + Mesh* localmesh = f.getMesh(); + bndry->first(); // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW) { @@ -3148,13 +3204,14 @@ void BoundaryFree_O3::apply(Field2D &f) { void BoundaryFree_O3::apply(Field3D &f) { // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. - bndry->first(); + Mesh* localmesh = f.getMesh(); + bndry->first(); // Check for staggered grids CELL_LOC loc = f.getLocation(); - if(mesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { + if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { // Staggered. Need to apply slightly differently if( loc == CELL_XLOW ) { @@ -3165,7 +3222,7 @@ void BoundaryFree_O3::apply(Field3D &f) { for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3179,7 +3236,7 @@ void BoundaryFree_O3::apply(Field3D &f) { // Inner x boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=-1;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3194,7 +3251,7 @@ void BoundaryFree_O3::apply(Field3D &f) { for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3211,7 +3268,7 @@ void BoundaryFree_O3::apply(Field3D &f) { if(bndry->by > 0) { // Upper y boundary for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3225,7 +3282,7 @@ void BoundaryFree_O3::apply(Field3D &f) { // Lower y boundary. Set one point inwards for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=-1;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3239,7 +3296,7 @@ void BoundaryFree_O3::apply(Field3D &f) { // x boundaries for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3258,7 +3315,7 @@ void BoundaryFree_O3::apply(Field3D &f) { // Standard (non-staggered) case for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { + for(int zk=0;zkLocalNz;zk++) { for(int i=0;iwidth;i++) { int xi = bndry->x + i*bndry->bx; int yi = bndry->y + i*bndry->by; @@ -3277,9 +3334,10 @@ void BoundaryFree_O3::apply_ddt(Field2D &f) { } void BoundaryFree_O3::apply_ddt(Field3D &f) { + Mesh* localmesh = f.getMesh(); Field3D *dt = f.timeDeriv(); for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) + for(int z=0;zLocalNz;z++) (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero } @@ -3328,13 +3386,15 @@ void BoundaryRelax::apply_ddt(Field2D &f) { void BoundaryRelax::apply_ddt(Field3D &f) { TRACE("BoundaryRelax::apply_ddt(Field3D)"); + Mesh* localmesh = f.getMesh(); + // Make a copy of f Field3D g = f; // NOTE: This is not very efficient... copying entire field // Apply the boundary to g op->apply(g); // Set time-derivatives for(bndry->first(); !bndry->isDone(); bndry->next()) - for(int z=0;zLocalNz;z++) { + for(int z=0;zLocalNz;z++) { ddt(f)(bndry->x, bndry->y, z) = r * (g(bndry->x, bndry->y, z) - f(bndry->x, bndry->y, z)); } } @@ -3401,14 +3461,16 @@ void BoundaryToFieldAligned::apply(Field2D &f, BoutReal t) { } void BoundaryToFieldAligned::apply(Field3D &f, BoutReal t) { + Mesh* localmesh = f.getMesh(); + //NOTE: This is not very efficient... updating entire field - f = mesh->fromFieldAligned(f); + f = localmesh->fromFieldAligned(f); // Apply the boundary to shifted field op->apply(f, t); //Shift back - f = mesh->toFieldAligned(f); + f = localmesh->toFieldAligned(f); //This is inefficient -- could instead use the shiftZ just in the bndry //but this is not portable to other parallel transforms -- we could instead @@ -3420,10 +3482,12 @@ void BoundaryToFieldAligned::apply_ddt(Field2D &f) { } void BoundaryToFieldAligned::apply_ddt(Field3D &f) { - f = mesh->fromFieldAligned(f); - ddt(f) = mesh->fromFieldAligned(ddt(f)); + Mesh* localmesh = f.getMesh(); + + f = localmesh->fromFieldAligned(f); + ddt(f) = localmesh->fromFieldAligned(ddt(f)); op->apply_ddt(f); - ddt(f) = mesh->toFieldAligned(ddt(f)); + ddt(f) = localmesh->toFieldAligned(ddt(f)); } @@ -3444,14 +3508,16 @@ void BoundaryFromFieldAligned::apply(Field2D &f, BoutReal t) { } void BoundaryFromFieldAligned::apply(Field3D &f, BoutReal t) { + Mesh* localmesh = f.getMesh(); + //NOTE: This is not very efficient... shifting entire field - f = mesh->toFieldAligned(f); + f = localmesh->toFieldAligned(f); // Apply the boundary to shifted field op->apply(f, t); //Shift back - f = mesh->fromFieldAligned(f); + f = localmesh->fromFieldAligned(f); //This is inefficient -- could instead use the shiftZ just in the bndry //but this is not portable to other parallel transforms -- we could instead @@ -3463,8 +3529,10 @@ void BoundaryFromFieldAligned::apply_ddt(Field2D &f) { } void BoundaryFromFieldAligned::apply_ddt(Field3D &f) { - f = mesh->toFieldAligned(f); - ddt(f) = mesh->toFieldAligned(ddt(f)); + Mesh* localmesh = f.getMesh(); + + f = localmesh->toFieldAligned(f); + ddt(f) = localmesh->toFieldAligned(ddt(f)); op->apply_ddt(f); - ddt(f) = mesh->fromFieldAligned(ddt(f)); + ddt(f) = localmesh->fromFieldAligned(ddt(f)); } From bfcf30f2e9d36381fdaf3395343b743393b889f8 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 15 Oct 2018 17:35:30 +0100 Subject: [PATCH 64/69] Tidy up location checking in boundary_standard.cxx --- src/mesh/boundary_standard.cxx | 3437 ++++++++++++++++---------------- 1 file changed, 1672 insertions(+), 1765 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 0dc8936ed2..c55fef3510 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -125,9 +125,13 @@ void BoundaryDirichlet::apply(Field2D &f){ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used - + Mesh* localmesh = f.getMesh(); + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + bndry->first(); // Decide which generator to use @@ -136,174 +140,163 @@ void BoundaryDirichlet::apply(Field2D &f,BoutReal t) { fg = f.getBndryGenerator(bndry->location); BoutReal val = 0.0; - - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW ) { - // shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y ; - - f(xi, yi) = 2*f(xi - bndry->bx, yi) - f(xi - 2*bndry->bx, yi); - } - } - } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x - bndry->bx,bndry->y) = val; + if( loc == CELL_XLOW ) { + // shifted in X - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y ; - - f(xi, yi) = 2*f(xi - bndry->bx, yi) - f(xi - 2*bndry->bx, yi); - } + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y ; + + f(xi, yi) = 2*f(xi - bndry->bx, yi) - f(xi - 2*bndry->bx, yi); } } - if(bndry->by !=0){ - // y boundaries - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x ; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x - bndry->bx,bndry->y) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y ; + + f(xi, yi) = 2*f(xi - bndry->bx, yi) - f(xi - 2*bndry->bx, yi); } } } - else if( loc == CELL_YLOW ) { - // Y boundary, and field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x ; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); - } + if(bndry->by !=0){ + // y boundaries + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x ; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); } } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y - bndry->by) = val; + } + } else if( loc == CELL_YLOW ) { + // Y boundary, and field is shifted in Y + + if(bndry->by > 0) { + // Upper y boundary + + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x ; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); - } + f(bndry->x,bndry->y) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x ; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); } } - if (bndry->bx !=0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y ; - f(xi, yi) = 2*f(xi - bndry->bx, yi) - f(xi - 2*bndry->bx, yi); - } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y - bndry->by) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x ; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi, yi - bndry->by) - f(xi, yi - 2*bndry->by); + } + } + } + if (bndry->bx !=0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y ; + f(xi, yi) = 2*f(xi - bndry->bx, yi) - f(xi - 2*bndry->bx, yi); } } - } else { - throw BoutException("Unhandled staggering in BoundaryDirichlet."); } } else { - // Non-staggered, standard case - + // CELL_CENTRE or CELL_ZLOW + for(; !bndry->isDone(); bndry->next1d()) { - + if(fg) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + // Calculate the X and Y normalised values half-way between the guard cell and grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } - + f(bndry->x,bndry->y) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by); - + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->bx; - f(xi, yi) = 2*f(xi - bndry->bx, yi - bndry->by) - f(xi - 2*bndry->bx, yi - 2*bndry->by); - } + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->bx; + f(xi, yi) = 2*f(xi - bndry->bx, yi - bndry->by) - f(xi - 2*bndry->bx, yi - 2*bndry->by); + } } } } @@ -319,6 +312,10 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { Mesh* localmesh = f.getMesh(); + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + bndry->first(); // Decide which generator to use @@ -328,180 +325,169 @@ void BoundaryDirichlet::apply(Field3D &f,BoutReal t) { BoutReal val = 0.0; - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW ) { - // X boundary, and field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y, zk) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y ; - - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi , zk) - f(xi- 2*bndry->bx, yi , zk); - } - } - } + if( loc == CELL_XLOW ) { + // X boundary, and field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y, zk) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y ; + + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi , zk) - f(xi- 2*bndry->bx, yi , zk); + } + } } - if (bndry->bx < 0){ - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x - bndry->bx,bndry->y, zk) = val; - f(bndry->x,bndry->y, zk) = f(bndry->x - bndry->bx,bndry->y, zk); - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y ; - - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi , zk) - f(xi- 2*bndry->bx, yi , zk); - } - } - } + } + if (bndry->bx < 0){ + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x - bndry->bx,bndry->y, zk) = val; + f(bndry->x,bndry->y, zk) = f(bndry->x - bndry->bx,bndry->y, zk); + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y ; + + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi , zk) - f(xi- 2*bndry->bx, yi , zk); + } + } } - if(bndry->by !=0){ - // y boundaries - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x ; - int yi = bndry->y + i*bndry->by; - - f(xi, yi, zk) = 2*f(xi, yi - bndry->by, zk) - f(xi, yi - 2*bndry->by, zk); - } - } - } - } - } - else if( loc == CELL_YLOW ) { - // Shifted in Y - - if(bndry->by > 0) { - // Upper y boundary boundary - - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y,zk) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x ; - int yi = bndry->y + i*bndry->by; - - f(xi, yi, zk) = 2.0*f(xi, yi - bndry->by, zk) - f(xi, yi - 2*bndry->by, zk); - } - } - } + } + if(bndry->by !=0){ + // y boundaries + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x ; + int yi = bndry->y + i*bndry->by; + + f(xi, yi, zk) = 2*f(xi, yi - bndry->by, zk) - f(xi, yi - 2*bndry->by, zk); + } + } } - if(bndry->by < 0){ - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y - bndry->by, zk) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x ; - int yi = bndry->y + i*bndry->by; - - f(xi, yi, zk) = 2*f(xi, yi - bndry->by, zk) - f(xi, yi - 2*bndry->by, zk); - } - } - } + } + } else if( loc == CELL_YLOW ) { + // Shifted in Y + + if(bndry->by > 0) { + // Upper y boundary boundary + + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y,zk) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x ; + int yi = bndry->y + i*bndry->by; + + f(xi, yi, zk) = 2.0*f(xi, yi - bndry->by, zk) - f(xi, yi - 2*bndry->by, zk); + } + } } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y ; - - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi , zk) - f(xi - 2*bndry->bx, yi, zk); - } - } - } + } + if(bndry->by < 0){ + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y - bndry->by, zk) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x ; + int yi = bndry->y + i*bndry->by; + + f(xi, yi, zk) = 2*f(xi, yi - bndry->by, zk) - f(xi, yi - 2*bndry->by, zk); + } + } } - } else { - throw BoutException("Unhandled staggering in BoundaryDirichlet."); } - } - else { - // Standard (non-staggered) case + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y ; + + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi , zk) - f(xi - 2*bndry->bx, yi, zk); + } + } + } + } + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { // Calculate the X and Y normalised values half-way between the guard cell and grid cell BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y,zk) = 2*val - f(bndry->x-bndry->bx, bndry->y-bndry->by, zk); // We've set the first boundary point using extrapolation in // the line above. The below block of code is attempting to @@ -586,9 +572,13 @@ void BoundaryDirichlet_O3::apply(Field2D &f){ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used - + Mesh* localmesh = f.getMesh(); + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + bndry->first(); // Decide which generator to use @@ -597,188 +587,179 @@ void BoundaryDirichlet_O3::apply(Field2D &f,BoutReal t) { fg = f.getBndryGenerator(bndry->location); BoutReal val = 0.0; - - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } - } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - f(bndry->x - bndry->bx,bndry->y) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } - } - if(bndry->by != 0){ - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - - } + if( loc == CELL_XLOW) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - - } - } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y - bndry->by) = val; - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + f(bndry->x - bndry->bx,bndry->y) = val; - } - } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - } else { - throw BoutException("Unhandled staggering in BoundaryDirichlet_O3."); } - } - else { - // Non-staggered, standard case - - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by)/3.; + if(bndry->by != 0){ + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } - } -} + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + f(bndry->x,bndry->y) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by)/3.; -void BoundaryDirichlet_O3::apply(Field3D &f) { - BoundaryDirichlet_O3::apply(f,0.); -} + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } + } + } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y -void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { - // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val - // N.B. Only first guard cells (closest to the grid) should ever be used + if(bndry->by > 0) { + // Upper y boundary - Mesh* localmesh = f.getMesh(); + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } - bndry->first(); + f(bndry->x,bndry->y) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } + + } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y - bndry->by) = val; + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } + + } + } + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } + } + } + } else { + // CELL_CENTRE or CELL_ZLOW + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + // Calculate the X and Y normalised values half-way between the guard cell and grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } + } + } +} + + +void BoundaryDirichlet_O3::apply(Field3D &f) { + BoundaryDirichlet_O3::apply(f,0.); +} + + +void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { + // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val + // N.B. Only first guard cells (closest to the grid) should ever be used + + Mesh* localmesh = f.getMesh(); + + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + + bndry->first(); // Decide which generator to use std::shared_ptr fg = gen; @@ -787,186 +768,175 @@ void BoundaryDirichlet_O3::apply(Field3D &f,BoutReal t) { BoutReal val = 0.0; - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y, zk) = val; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + if( loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y, zk) = val; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x - bndry->bx,bndry->y, zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x - bndry->bx,bndry->y, zk) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->by != 0){ - //y boundaries - - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->by != 0){ + //y boundaries + + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y,zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Upper y boundary + + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y,zk) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*(localmesh->GlobalY(bndry->y)+ localmesh->GlobalY(bndry->y - bndry->by) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y - bndry->by, zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*(localmesh->GlobalY(bndry->y)+ localmesh->GlobalY(bndry->y - bndry->by) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y - bndry->by, zk) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - } else { - throw BoutException("Unhandled staggering in BoundaryDirichlet_O3."); } - } - else { - // Standard (non-staggered) case + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell + // Calculate the X and Y normalised values half-way between the guard cell and grid cell BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x,bndry->y,zk) = (8./3)*val - 2.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk)/3.; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } } } } @@ -1009,9 +979,13 @@ void BoundaryDirichlet_O4::apply(Field2D &f){ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used - + Mesh* localmesh = f.getMesh(); + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + bndry->first(); // Decide which generator to use @@ -1020,393 +994,373 @@ void BoundaryDirichlet_O4::apply(Field2D &f,BoutReal t) { fg = f.getBndryGenerator(bndry->location); BoutReal val = 0.0; - - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if(loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - f(bndry->x,bndry->y) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); - } - } + if(loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + f(bndry->x,bndry->y) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } } - - if(bndry->bx < 0) { - // Inner boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x - bndry->bx,bndry->y) = val; + } - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); - } - } + if(bndry->bx < 0) { + // Inner boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x - bndry->bx,bndry->y) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } } - if (bndry->by != 0){ - // y boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by); - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); - } - } + } + if (bndry->by != 0){ + // y boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by); + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Outer y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - f(bndry->x,bndry->y) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Outer y boundary + + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + f(bndry->x,bndry->y) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } } - if(bndry->by < 0) { - // Inner y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y - bndry->by) = val; + } + if(bndry->by < 0) { + // Inner y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); - } - } + f(bndry->x,bndry->y - bndry->by) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } } - if(bndry->bx !=0){ - // x boundaries. - - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); - } - - f(bndry->x,bndry->y) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by); - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); - } - } + } + if(bndry->bx !=0){ + // x boundaries. + + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + } + + f(bndry->x,bndry->y) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by); + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } } - } else { - throw BoutException("Unhandled staggering in BoundaryDirichlet_O4."); } - } - else { - // Non-staggered, standard case - + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - + if(fg) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); + // Calculate the X and Y normalised values half-way between the guard cell and grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t); } - + f(bndry->x,bndry->y) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by); - + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 4.0*f(xi - bndry->bx, yi - bndry->by) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by) - f(xi - 4*bndry->bx, yi - 4*bndry->by); + } + } + } +} + + +void BoundaryDirichlet_O4::apply(Field3D &f) { + BoundaryDirichlet_O4::apply(f,0.); +} + + +void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { + // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val + // N.B. Only first guard cells (closest to the grid) should ever be used + + Mesh* localmesh = f.getMesh(); + + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + + bndry->first(); + + // Decide which generator to use + std::shared_ptr fg = gen; + if(!fg) + fg = f.getBndryGenerator(bndry->location); + + BoutReal val = 0.0; + + if( loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y, zk) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); + } + } + } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x - bndry->bx,bndry->y, zk) = val; + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); + } + } + } + } + if (bndry->by != 0){ + // y boundaries + + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) { + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + } + f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); + } + } } } - } -} + } else if( loc == CELL_YLOW ) { + // Y boundary, and field is shifted in Y + if(bndry->by > 0) { + // Outer y boundary -void BoundaryDirichlet_O4::apply(Field3D &f) { - BoundaryDirichlet_O4::apply(f,0.); -} - + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); -void BoundaryDirichlet_O4::apply(Field3D &f,BoutReal t) { - // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val - // N.B. Only first guard cells (closest to the grid) should ever be used + f(bndry->x,bndry->y,zk) = val; - Mesh* localmesh = f.getMesh(); + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); + } + } + } + } + if(bndry->by < 0) { + // Inner y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { - bndry->first(); + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); - // Decide which generator to use - std::shared_ptr fg = gen; - if(!fg) - fg = f.getBndryGenerator(bndry->location); + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - BoutReal val = 0.0; + f(bndry->x,bndry->y - bndry->by, zk) = val; - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y, zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } - } - } - } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x - bndry->bx,bndry->y, zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } - } - } + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); + } + } } - if (bndry->by != 0){ - // y boundaries + } + if(bndry->bx !=0){ + // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); - for(int zk=0;zkLocalNz;zk++) { - if(fg) { - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - } - f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); } } } } - else if( loc == CELL_YLOW ) { - // Y boundary, and field is shifted in Y - - if(bndry->by > 0) { - // Outer y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } - } - } - } - if(bndry->by < 0) { - // Inner y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y - bndry->by, zk) = val; - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } - } - } - } - if(bndry->bx !=0){ - // x boundaries - - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } - } - } - } - } else { - throw BoutException("Unhandled staggering in BoundaryDirichlet_O4."); - } - } - else { - // Standard (non-staggered) case + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell + // Calculate the X and Y normalised values half-way between the guard cell and grid cell BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); - - f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); - - // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); - } + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz), t); + + f(bndry->x,bndry->y,zk) = (16./5)*val - 3.*f(bndry->x-bndry->bx, bndry->y-bndry->by,zk) + f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by,zk) - (1./5)*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by,zk); + + // Need to set remaining guard cells, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 4.0*f(xi - bndry->bx, yi - bndry->by, zk) - 6.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + 4.0*f(xi - 3*bndry->bx, yi - 3*bndry->by, zk) - f(xi - 4*bndry->bx, yi - 4*bndry->by, zk); + } } } } @@ -1736,196 +1690,188 @@ void BoundaryNeumann::apply(Field2D &f) { void BoundaryNeumann::apply(Field2D &f,BoutReal t) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used - + Mesh* localmesh = f.getMesh(); + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + Coordinates *metric = f.getCoordinates(); - + bndry->first(); - + // Decide which generator to use std::shared_ptr fg = gen; if(!fg) fg = f.getBndryGenerator(bndry->location); - + BoutReal val = 0.0; - - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - // Use one-sided differencing. Cell is now on - // the boundary, so use one-sided differencing - - if( loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); - } - - f(bndry->x,bndry->y) = (4.*f(bndry->x - bndry->bx, bndry->y) - f(bndry->x - 2*bndry->bx, bndry->y) + 2.*val)/3.; - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + + // For staggered case need to apply slightly differently Use one-sided + // differencing. Cell is now on the boundary, so use one-sided differencing + if( loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); + } + + f(bndry->x,bndry->y) = (4.*f(bndry->x - bndry->bx, bndry->y) - f(bndry->x - 2*bndry->bx, bndry->y) + 2.*val)/3.; + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); - } - - f(bndry->x - bndry->bx,bndry->y) = (4.*f(bndry->x - 2*bndry->bx, bndry->y) - f(bndry->x - 3*bndry->bx, bndry->y) - 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); + } + + f(bndry->x - bndry->bx,bndry->y) = (4.*f(bndry->x - 2*bndry->bx, bndry->y) - f(bndry->x - 3*bndry->bx, bndry->y) - 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->by !=0 ){ - // y boundaries - - for(bndry->first(); !bndry->isDone(); bndry->next1d()) { - BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - - if(fg) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - - val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); - } - - f(bndry->x,bndry->y) = f(bndry->x-bndry->bx, bndry->y-bndry->by) + delta*val; - if (bndry->width == 2){ - f(bndry->x + bndry->bx, bndry->y + bndry->by) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by) + 3.0*delta*val; - } - } + } + if(bndry->by !=0 ){ + // y boundaries + + for(bndry->first(); !bndry->isDone(); bndry->next1d()) { + BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); + + if(fg) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + + val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); + } + + f(bndry->x,bndry->y) = f(bndry->x-bndry->bx, bndry->y-bndry->by) + delta*val; + if (bndry->width == 2){ + f(bndry->x + bndry->bx, bndry->y + bndry->by) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by) + 3.0*delta*val; + } } } - else if(loc == CELL_YLOW) { - // Y boundary, and field is shifted in Y - - if(bndry->by > 0) { - // Outer y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - if(fg) { - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); - } - f(bndry->x,bndry->y) = (4.*f(bndry->x, bndry->y - bndry->by) - f(bndry->x, bndry->y - 2*bndry->by) + 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + } else if(loc == CELL_YLOW) { + // Y boundary, and field is shifted in Y + + if(bndry->by > 0) { + // Outer y boundary + + for(; !bndry->isDone(); bndry->next1d()) { + if(fg) { + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y); + } + f(bndry->x,bndry->y) = (4.*f(bndry->x, bndry->y - bndry->by) - f(bndry->x, bndry->y - 2*bndry->by) + 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->by < 0) { - // Inner y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - if(fg) { - - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - - val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y - bndry->by); - } - f(bndry->x,bndry->y - bndry->by) = (4.*f(bndry->x, bndry->y - 2*bndry->by) - f(bndry->x, bndry->y - 3*bndry->by) - 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + } + if(bndry->by < 0) { + // Inner y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + if(fg) { + + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + + val = fg->generate(xnorm,TWOPI*ynorm,0.0, t) * metric->dx(bndry->x, bndry->y - bndry->by); + } + f(bndry->x,bndry->y - bndry->by) = (4.*f(bndry->x, bndry->y - 2*bndry->by) - f(bndry->x, bndry->y - 3*bndry->by) - 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->bx != 0){ - // x boundaries - for(bndry->first(); !bndry->isDone(); bndry->next1d()) { - BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - - if(fg) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); - } - - f(bndry->x,bndry->y) = f(bndry->x-bndry->bx, bndry->y-bndry->by) + delta*val; - if (bndry->width == 2){ - f(bndry->x + bndry->bx, bndry->y + bndry->by) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by) + 3.0*delta*val; - } - } - } - } else { - throw BoutException("Unhandled staggering in BoundaryNeumann."); } - } - else { - // Non-staggered, standard case - + if(bndry->bx != 0){ + // x boundaries + for(bndry->first(); !bndry->isDone(); bndry->next1d()) { + BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); + + if(fg) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); + } + + f(bndry->x,bndry->y) = f(bndry->x-bndry->bx, bndry->y-bndry->by) + delta*val; + if (bndry->width == 2){ + f(bndry->x + bndry->bx, bndry->y + bndry->by) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by) + 3.0*delta*val; + } + } + } + } else { + // CELL_CENTRE or CELL_ZLOW for(bndry->first(); !bndry->isDone(); bndry->next1d()) { BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - + if(fg) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); + // Calculate the X and Y normalised values half-way between the guard cell and grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + + val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); } - + f(bndry->x,bndry->y) = f(bndry->x-bndry->bx, bndry->y-bndry->by) + delta*val; if (bndry->width == 2){ - f(bndry->x + bndry->bx, bndry->y + bndry->by) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by) + 3.0*delta*val; + f(bndry->x + bndry->bx, bndry->y + bndry->by) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by) + 3.0*delta*val; } } } @@ -1938,201 +1884,197 @@ void BoundaryNeumann::apply(Field3D &f) { void BoundaryNeumann::apply(Field3D &f,BoutReal t) { + Mesh* localmesh = f.getMesh(); + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + Coordinates *metric = f.getCoordinates(); - + bndry->first(); - + // Decide which generator to use std::shared_ptr fg = gen; if(!fg) fg = f.getBndryGenerator(bndry->location); - + BoutReal val = 0.0; - - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - // Use one-sided differencing. Cell is now on - // the boundary, so use one-sided differencing - - if( loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - for(; !bndry->isDone(); bndry->next1d()) { - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dx(bndry->x, bndry->y); - - f(bndry->x,bndry->y, zk) = (4.*f(bndry->x - bndry->bx, bndry->y,zk) - f(bndry->x - 2*bndry->bx, bndry->y,zk) + 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + + // For staggered case need to apply slightly differently Use one-sided + // differencing. Cell is now on the boundary, so use one-sided differencing + + if( loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + for(; !bndry->isDone(); bndry->next1d()) { + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dx(bndry->x, bndry->y); + + f(bndry->x,bndry->y, zk) = (4.*f(bndry->x - bndry->bx, bndry->y,zk) - f(bndry->x - 2*bndry->bx, bndry->y,zk) + 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->bx < 0) { - // Inner x boundary - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) - + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = localmesh->GlobalY(bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dx(bndry->x - bndry->bx, bndry->y); - - f(bndry->x - bndry->bx,bndry->y, zk) = (4.*f(bndry->x - 2*bndry->bx, bndry->y,zk) - f(bndry->x - 3*bndry->bx, bndry->y,zk) - 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->bx < 0) { + // Inner x boundary + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = localmesh->GlobalY(bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dx(bndry->x - bndry->bx, bndry->y); + + f(bndry->x - bndry->bx,bndry->y, zk) = (4.*f(bndry->x - 2*bndry->bx, bndry->y,zk) - f(bndry->x - 3*bndry->bx, bndry->y,zk) - 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->by != 0) { - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is shifted by half a grid point because it is staggered. - // y norm is located half way between first grid cell and guard cell. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); - - BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); - } - f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; - if (bndry->width == 2){ - f(bndry->x + bndry->bx, bndry->y + bndry->by, zk) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, zk) + 3.0*delta*val; - } - } - } + } + if(bndry->by != 0) { + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is shifted by half a grid point because it is staggered. + // y norm is located half way between first grid cell and guard cell. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - 1) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - bndry->by) ); + + BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); + } + f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; + if (bndry->width == 2){ + f(bndry->x + bndry->bx, bndry->y + bndry->by, zk) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, zk) + 3.0*delta*val; + } + } } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Outer y boundary - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { - - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dy(bndry->x, bndry->y); - } - f(bndry->x,bndry->y,zk) = (4.*f(bndry->x, bndry->y - bndry->by,zk) - f(bndry->x, bndry->y - 2*bndry->by,zk) + 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Outer y boundary + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { + + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dy(bndry->x, bndry->y); + } + f(bndry->x,bndry->y,zk) = (4.*f(bndry->x, bndry->y - bndry->by,zk) - f(bndry->x, bndry->y - 2*bndry->by,zk) + 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->by < 0) { - // Inner y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - BoutReal xnorm = localmesh->GlobalX(bndry->x); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) - + localmesh->GlobalY(bndry->y - bndry->by) ); - for(int zk=0;zkLocalNz;zk++) { - if(fg) - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dy(bndry->x, bndry->y - bndry->by); - - f(bndry->x,bndry->y - bndry->by,zk) = (4.*f(bndry->x, bndry->y - 2*bndry->by,zk) - f(bndry->x, bndry->y - 3*bndry->by,zk) - 2.*val)/3.; - - // Need to set second guard cell, as may be used for interpolation or upwinding derivatives - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - // Use third order extrapolation because boundary point is set to third order, and these points - // may be used be used by 2nd order upwinding type schemes, which require 3rd order - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->by < 0) { + // Inner y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + BoutReal xnorm = localmesh->GlobalX(bndry->x); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + + localmesh->GlobalY(bndry->y - bndry->by) ); + for(int zk=0;zkLocalNz;zk++) { + if(fg) + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t) * metric->dy(bndry->x, bndry->y - bndry->by); + + f(bndry->x,bndry->y - bndry->by,zk) = (4.*f(bndry->x, bndry->y - 2*bndry->by,zk) - f(bndry->x, bndry->y - 3*bndry->by,zk) - 2.*val)/3.; + + // Need to set second guard cell, as may be used for interpolation or upwinding derivatives + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + // Use third order extrapolation because boundary point is set to third order, and these points + // may be used be used by 2nd order upwinding type schemes, which require 3rd order + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->bx !=0 ){ - // x boundaries. - for(; !bndry->isDone(); bndry->next1d()) { - // x norm is located half way between first grid cell and guard cell. - // y norm is shifted by half a grid point because it is staggered. - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); - - BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); - } - f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; - if (bndry->width == 2){ - f(bndry->x + bndry->bx, bndry->y + bndry->by, zk) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, zk) + 3.0*delta*val; - } - } - } + } + if(bndry->bx !=0 ){ + // x boundaries. + for(; !bndry->isDone(); bndry->next1d()) { + // x norm is located half way between first grid cell and guard cell. + // y norm is shifted by half a grid point because it is staggered. + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) + localmesh->GlobalX(bndry->x - bndry->bx) ); + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) + localmesh->GlobalY(bndry->y - 1) ); + + BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); + + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); + } + f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; + if (bndry->width == 2){ + f(bndry->x + bndry->bx, bndry->y + bndry->by, zk) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, zk) + 3.0*delta*val; + } + } } - } else { - throw BoutException("Unhandled staggering in BoundaryNeumann."); } - } - else { + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell + // Calculate the X and Y normalised values half-way between the guard cell and grid cell BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y); - + for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); - } - f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; - if (bndry->width == 2){ - f(bndry->x + bndry->bx, bndry->y + bndry->by, zk) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, zk) + 3.0*delta*val; - } + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); + } + f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; + if (bndry->width == 2){ + f(bndry->x + bndry->bx, bndry->y + bndry->by, zk) = f(bndry->x - 2*bndry->bx, bndry->y - 2*bndry->by, zk) + 3.0*delta*val; + } } } } @@ -2171,8 +2113,12 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { // Set (at 4th order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used + Mesh* localmesh = f.getMesh(); + // Check for staggered grids + ASSERT1(f.getLocation() == CELL_CENTRE || f.getLocation() == CELL_ZLOW); + bndry->first(); // Decide which generator to use @@ -2181,43 +2127,34 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { fg = f.getBndryGenerator(bndry->location); BoutReal val = 0.0; - - // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - throw BoutException("neumann_o4 not implemented with staggered grid yet"); - } - else { - // Non-staggered, standard case - - Coordinates *coords = f.getCoordinates(); - for(bndry->first(); !bndry->isDone(); bndry->next1d()) { - BoutReal delta = bndry->bx*coords->dx(bndry->x,bndry->y)+bndry->by*coords->dy(bndry->x,bndry->y); - - if(fg) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); - } - - f(bndry->x, bndry->y) = 12.*delta*val/11. - + - ( - + 17.*f(bndry->x- bndry->bx, bndry->y- bndry->by) - + 9.*f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) - - 5.*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by) - + f(bndry->x-4*bndry->bx, bndry->y-4*bndry->by) - )/22.; + Coordinates *coords = f.getCoordinates(); - if (bndry->width == 2){ - throw BoutException("neumann_o4 with a boundary width of 2 not implemented yet"); - } + for(bndry->first(); !bndry->isDone(); bndry->next1d()) { + BoutReal delta = bndry->bx*coords->dx(bndry->x,bndry->y)+bndry->by*coords->dy(bndry->x,bndry->y); + + if(fg) { + // Calculate the X and Y normalised values half-way between the guard cell and grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell + + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell + + val = fg->generate(xnorm, TWOPI*ynorm, 0.0, t); + } + + f(bndry->x, bndry->y) = 12.*delta*val/11. + + + ( + + 17.*f(bndry->x- bndry->bx, bndry->y- bndry->by) + + 9.*f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by) + - 5.*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by) + + f(bndry->x-4*bndry->bx, bndry->y-4*bndry->by) + )/22.; + + if (bndry->width == 2){ + throw BoutException("neumann_o4 with a boundary width of 2 not implemented yet"); } } } @@ -2229,6 +2166,9 @@ void BoundaryNeumann_O4::apply(Field3D &f) { void BoundaryNeumann_O4::apply(Field3D &f,BoutReal t) { Mesh* localmesh = f.getMesh(); + // Check for staggered grids + ASSERT1(f.getLocation() == CELL_CENTRE || f.getLocation() == CELL_ZLOW); + bndry->first(); // Decide which generator to use @@ -2237,41 +2177,34 @@ void BoundaryNeumann_O4::apply(Field3D &f,BoutReal t) { fg = f.getBndryGenerator(bndry->location); BoutReal val = 0.0; - - // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - throw BoutException("neumann_o4 not implemented with staggered grid yet"); - } - else { - Coordinates *coords = f.getCoordinates(); - for(; !bndry->isDone(); bndry->next1d()) { - // Calculate the X and Y normalised values half-way between the guard cell and grid cell - BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell - + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell - + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - BoutReal delta = bndry->bx*coords->dx(bndry->x,bndry->y)+bndry->by*coords->dy(bndry->x,bndry->y); + Coordinates *coords = f.getCoordinates(); + for(; !bndry->isDone(); bndry->next1d()) { + // Calculate the X and Y normalised values half-way between the guard cell and grid cell + BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) // In the guard cell + + localmesh->GlobalX(bndry->x - bndry->bx) ); // the grid cell - for(int zk=0;zkLocalNz;zk++) { - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); - } + BoutReal ynorm = 0.5*( localmesh->GlobalY(bndry->y) // In the guard cell + + localmesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - f(bndry->x,bndry->y, zk) = 12.*delta*val/11. - + - ( - + 17.*f(bndry->x- bndry->bx, bndry->y- bndry->by, zk) - + 9.*f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by, zk) - - 5.*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by, zk) - + f(bndry->x-4*bndry->bx, bndry->y-4*bndry->by, zk) - )/22.; + BoutReal delta = bndry->bx*coords->dx(bndry->x,bndry->y)+bndry->by*coords->dy(bndry->x,bndry->y); - if (bndry->width == 2){ - throw BoutException("neumann_o4 with a boundary width of 2 not implemented yet"); - } + for(int zk=0;zkLocalNz;zk++) { + if(fg){ + val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(localmesh->LocalNz),t); + } + + f(bndry->x,bndry->y, zk) = 12.*delta*val/11. + + + ( + + 17.*f(bndry->x- bndry->bx, bndry->y- bndry->by, zk) + + 9.*f(bndry->x-2*bndry->bx, bndry->y-2*bndry->by, zk) + - 5.*f(bndry->x-3*bndry->bx, bndry->y-3*bndry->by, zk) + + f(bndry->x-4*bndry->bx, bndry->y-4*bndry->by, zk) + )/22.; + + if (bndry->width == 2){ + throw BoutException("neumann_o4 with a boundary width of 2 not implemented yet"); } } } @@ -2856,218 +2789,205 @@ BoundaryOp* BoundaryFree_O2::clone(BoundaryRegion *region, const list &a void BoundaryFree_O2::apply(Field2D &f) { // Set (at 2nd order) the value at the mid-point between the guard cell and the grid cell to be val // N.B. Only first guard cells (closest to the grid) should ever be used - - Mesh* localmesh = f.getMesh(); - bndry->first(); + Mesh* localmesh = f.getMesh(); // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } - } + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + + bndry->first(); + + // If staggered, need to apply slightly differently + if( loc == CELL_XLOW) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } } - if(bndry->by != 0){ - // y boundaries - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } - - } + } + if(bndry->by != 0){ + // y boundaries + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } + } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Upper y boundary + + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } - } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } - } + } + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } } - } else { - throw BoutException("Unhandled staggering in BoundaryFree_O2."); } - } - else { - // Non-staggered, standard case - + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - + for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); - } + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 2*f(xi - bndry->bx, yi -bndry->by) - f(xi- 2*bndry->bx, yi - 2*bndry->by); + } } } } void BoundaryFree_O2::apply(Field3D &f) { - // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. - - bndry->first(); + // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. Mesh* localmesh = f.getMesh(); // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } - } - } + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + + bndry->first(); + + // If staggered, need to apply slightly differently + if( loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } + } } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } - } - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } + } } - if(bndry->by != 0){ - //y boundaries - - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } - } - } + } + if(bndry->by != 0){ + //y boundaries + + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } + } } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Upper y boundary + for(; !bndry->isDone(); bndry->next1d()) { + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } + } } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } - } - } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } + } } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } - } - } + } + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } + } } - } else { - throw BoutException("Unhandled staggering in BoundaryFree_O2."); } - } - else { - // Standard (non-staggered) case + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - + for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); - } + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 2*f(xi - bndry->bx, yi -bndry->by, zk) - f(xi- 2*bndry->bx, yi - 2*bndry->by, zk); + } } } } @@ -3104,224 +3024,211 @@ void BoundaryFree_O3::apply(Field2D &f) { Mesh* localmesh = f.getMesh(); - bndry->first(); - // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + + bndry->first(); + + // If staggered, need to apply slightly differently + if( loc == CELL_XLOW) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->by != 0){ - // y boundaries - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - - } + } + if(bndry->by != 0){ + // y boundaries + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } + } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Upper y boundary + + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } - } } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } - } + } + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } - } else { - throw BoutException("Unhandled staggering in BoundaryFree_O3."); } - } - else { - // Non-staggered, standard case - + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - + for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); - } + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi) = 3.0*f(xi - bndry->bx, yi - bndry->by) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by) + f(xi - 3*bndry->bx, yi - 3*bndry->by); + } } } } void BoundaryFree_O3::apply(Field3D &f) { - // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. + // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. Mesh* localmesh = f.getMesh(); - bndry->first(); - // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if(localmesh->StaggerGrids && loc != CELL_CENTRE && loc != CELL_ZLOW) { - // Staggered. Need to apply slightly differently - - if( loc == CELL_XLOW ) { - // Field is shifted in X - - if(bndry->bx > 0) { - // Outer x boundary - - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + ASSERT1(localmesh->StaggerGrids || loc == CELL_CENTRE); + + bndry->first(); + + // If staggered, need to apply slightly differently + if( loc == CELL_XLOW ) { + // Field is shifted in X + + if(bndry->bx > 0) { + // Outer x boundary + + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->bx < 0) { - // Inner x boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->by != 0){ - //y boundaries - - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->by != 0){ + //y boundaries + + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } } - else if( loc == CELL_YLOW ) { - // Field is shifted in Y - - if(bndry->by > 0) { - // Upper y boundary - for(; !bndry->isDone(); bndry->next1d()) { - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } else if( loc == CELL_YLOW ) { + // Field is shifted in Y + + if(bndry->by > 0) { + // Upper y boundary + for(; !bndry->isDone(); bndry->next1d()) { + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->by < 0) { - // Lower y boundary. Set one point inwards - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=-1;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - } - } + } + if(bndry->by < 0) { + // Lower y boundary. Set one point inwards + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=-1;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + } } - if(bndry->bx != 0){ - // x boundaries - for(; !bndry->isDone(); bndry->next1d()) { - - for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } - - } - } + } + if(bndry->bx != 0){ + // x boundaries + for(; !bndry->isDone(); bndry->next1d()) { + + for(int zk=0;zkLocalNz;zk++) { + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } + + } } - } else { - throw BoutException("Unhandled staggering in BoundaryFree_O3."); } - } - else { - // Standard (non-staggered) case + } else { + // CELL_CENTRE or CELL_ZLOW for(; !bndry->isDone(); bndry->next1d()) { - + for(int zk=0;zkLocalNz;zk++) { - for(int i=0;iwidth;i++) { - int xi = bndry->x + i*bndry->bx; - int yi = bndry->y + i*bndry->by; - f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) - + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); - } + for(int i=0;iwidth;i++) { + int xi = bndry->x + i*bndry->bx; + int yi = bndry->y + i*bndry->by; + f(xi, yi, zk) = 3.0*f(xi - bndry->bx, yi - bndry->by, zk) - 3.0*f(xi - 2*bndry->bx, yi - 2*bndry->by, zk) + + f(xi - 3*bndry->bx, yi - 3*bndry->by, zk); + } } } } From ea613e17974b2b1cc8c5989feeb8cc5a11cad6e2 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 15 Oct 2018 17:37:54 +0100 Subject: [PATCH 65/69] Make FieldData() backward compatible, no virtual on getDataMesh() Give default argument 'Mesh* m = nullptr' for FieldData::FieldData constructor so that it is backward compatible. Method FieldData::getDataMesh() does not need to be virtual, since it is unlikely to be overridden. --- include/field_data.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/field_data.hxx b/include/field_data.hxx index d75e89c2ca..ac43cfc5f4 100644 --- a/include/field_data.hxx +++ b/include/field_data.hxx @@ -62,13 +62,13 @@ class FieldVisitor; */ class FieldData { public: - FieldData(Mesh* m); + FieldData(Mesh* m = nullptr); virtual ~FieldData(); // Visitor pattern support virtual void accept(FieldVisitor &v) = 0; - virtual Mesh * getDataMesh() const{ + Mesh * getDataMesh() const{ if (fielddatamesh){ return fielddatamesh; } else { From 38f4161daf6d7d0f428b3bdbf63ed0aa5a03e417 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 16 Oct 2018 12:11:41 +0100 Subject: [PATCH 66/69] Move FieldData::fielddatamesh init into init list Also move FieldData ctor into header --- include/field_data.hxx | 11 +++++++---- src/field/field_data.cxx | 7 ------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/include/field_data.hxx b/include/field_data.hxx index ac43cfc5f4..5124726a92 100644 --- a/include/field_data.hxx +++ b/include/field_data.hxx @@ -62,14 +62,17 @@ class FieldVisitor; */ class FieldData { public: - FieldData(Mesh* m = nullptr); + FieldData(Mesh *datamesh = nullptr) + : fielddatamesh(datamesh != nullptr ? datamesh : mesh), boundaryIsCopy(false), + boundaryIsSet(true) {} + virtual ~FieldData(); // Visitor pattern support virtual void accept(FieldVisitor &v) = 0; - - Mesh * getDataMesh() const{ - if (fielddatamesh){ + + Mesh *getDataMesh() const { + if (fielddatamesh != nullptr) { return fielddatamesh; } else { return mesh; diff --git a/src/field/field_data.cxx b/src/field/field_data.cxx index 48c48e4847..98bf71eaec 100644 --- a/src/field/field_data.cxx +++ b/src/field/field_data.cxx @@ -6,13 +6,6 @@ #include #include "unused.hxx" -FieldData::FieldData(Mesh* m) : - fielddatamesh(m), boundaryIsCopy(false), boundaryIsSet(true) { - if (fielddatamesh == nullptr) { - fielddatamesh = mesh; - } -} - FieldData::~FieldData() { if(!boundaryIsCopy) { // Delete the boundary operations From 2de6e1d5f7b9c5dda2e3e781e94ee6f53add88d0 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 16 Oct 2018 12:27:15 +0100 Subject: [PATCH 67/69] Check Mesh*'s are the same in Field3D operator=(Field2D) --- src/field/field3d.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 7a141d2a7f..a7406ab14f 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -388,10 +388,12 @@ Field3D & Field3D::operator=(const Field3D &rhs) { Field3D & Field3D::operator=(const Field2D &rhs) { TRACE("Field3D = Field2D"); + + ASSERT1(fieldmesh == rhs.getMesh()); /// Check that the data is valid checkData(rhs); - + /// Make sure there's a unique array to copy data into allocate(); From 2f36229ec28af8ccdc7679dde14053b266730fe6 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 16 Oct 2018 12:28:01 +0100 Subject: [PATCH 68/69] Copy or check fielddatamesh in Field3D/Field2D operator= --- src/field/field2d.cxx | 1 + src/field/field3d.cxx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/field/field2d.cxx b/src/field/field2d.cxx index ad0885f2ab..1431947026 100644 --- a/src/field/field2d.cxx +++ b/src/field/field2d.cxx @@ -249,6 +249,7 @@ Field2D &Field2D::operator=(const Field2D &rhs) { // Copy the data and data sizes fieldmesh = rhs.fieldmesh; + fielddatamesh = rhs.fielddatamesh; nx = rhs.nx; ny = rhs.ny; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index a7406ab14f..0bd47fc2ba 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -377,6 +377,7 @@ Field3D & Field3D::operator=(const Field3D &rhs) { // Copy the data and data sizes fieldmesh = rhs.fieldmesh; + fielddatamesh = rhs.fielddatamesh; nx = rhs.nx; ny = rhs.ny; nz = rhs.nz; data = rhs.data; @@ -390,6 +391,7 @@ Field3D & Field3D::operator=(const Field2D &rhs) { TRACE("Field3D = Field2D"); ASSERT1(fieldmesh == rhs.getMesh()); + ASSERT1(fielddatamesh == rhs.getDataMesh()); /// Check that the data is valid checkData(rhs); From df110a0459eac06b4401750de6561e007e6d7a32 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 16 Oct 2018 13:35:11 +0100 Subject: [PATCH 69/69] Check consistency of fieldmesh and fielddatamesh In places where fieldmesh and fielddatamesh are set from separate pointers, check that their values are equal. Also, for consistency set fielddatamesh from *.fielddatamesh or *.getDataMesh(), rather than fieldmesh or getMesh(). --- src/field/field2d.cxx | 9 ++++++--- src/field/field3d.cxx | 14 ++++++++++---- src/field/vector3d.cxx | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/field/field2d.cxx b/src/field/field2d.cxx index 1431947026..6af68cf44d 100644 --- a/src/field/field2d.cxx +++ b/src/field/field2d.cxx @@ -67,11 +67,13 @@ Field2D::Field2D(Mesh *localmesh) : } Field2D::Field2D(const Field2D& f) : Field(f.fieldmesh), // The mesh containing array sizes - FieldData(f.fieldmesh), + FieldData(f.fielddatamesh), data(f.data), // This handles references to the data array deriv(nullptr) { TRACE("Field2D(Field2D&)"); + ASSERT1(fieldmesh == fielddatamesh); // Check consistency between Field::fieldmesh and FieldData::fielddatamesh + #ifdef TRACK name = f.name; #endif @@ -248,8 +250,9 @@ Field2D &Field2D::operator=(const Field2D &rhs) { #endif // Copy the data and data sizes - fieldmesh = rhs.fieldmesh; - fielddatamesh = rhs.fielddatamesh; + fieldmesh = rhs.getMesh(); + fielddatamesh = rhs.getDataMesh(); + ASSERT1(fieldmesh == fielddatamesh); // Check consistency between Field::fieldmesh and FieldData::fielddatamesh nx = rhs.nx; ny = rhs.ny; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 0bd47fc2ba..34acc5e47d 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -71,12 +71,14 @@ Field3D::Field3D(Mesh *localmesh) /// later) Field3D::Field3D(const Field3D &f) : Field(f.fieldmesh), // The mesh containing array sizes - FieldData(f.fieldmesh), + FieldData(f.fielddatamesh), background(nullptr), data(f.data), // This handles references to the data array deriv(nullptr), yup_field(nullptr), ydown_field(nullptr) { TRACE("Field3D(Field3D&)"); + ASSERT1(fieldmesh == fielddatamesh); // Check consistency between Field::fieldmesh and FieldData::fielddatamesh + #if CHECK > 2 checkData(f); #endif @@ -101,11 +103,13 @@ Field3D::Field3D(const Field3D &f) } Field3D::Field3D(const Field2D &f) - : Field(f.getMesh()), FieldData(f.getMesh()), background(nullptr), + : Field(f.getMesh()), FieldData(f.getDataMesh()), background(nullptr), deriv(nullptr), yup_field(nullptr), ydown_field(nullptr) { TRACE("Field3D: Copy constructor from Field2D"); + ASSERT1(fieldmesh == fielddatamesh); // Check consistency between Field::fieldmesh and FieldData::fielddatamesh + boundaryIsSet = false; nx = fieldmesh->LocalNx; @@ -376,8 +380,9 @@ Field3D & Field3D::operator=(const Field3D &rhs) { checkData(rhs); // Copy the data and data sizes - fieldmesh = rhs.fieldmesh; - fielddatamesh = rhs.fielddatamesh; + fieldmesh = rhs.getMesh(); + fielddatamesh = rhs.getDataMesh(); + ASSERT1(fieldmesh == fielddatamesh); // Check consistency between Field::fieldmesh and FieldData::fielddatamesh nx = rhs.nx; ny = rhs.ny; nz = rhs.nz; data = rhs.data; @@ -392,6 +397,7 @@ Field3D & Field3D::operator=(const Field2D &rhs) { ASSERT1(fieldmesh == rhs.getMesh()); ASSERT1(fielddatamesh == rhs.getDataMesh()); + ASSERT1(fieldmesh == fielddatamesh); // Check consistency between Field::fieldmesh and FieldData::fielddatamesh /// Check that the data is valid checkData(rhs); diff --git a/src/field/vector3d.cxx b/src/field/vector3d.cxx index 8996efc824..28ada267e5 100644 --- a/src/field/vector3d.cxx +++ b/src/field/vector3d.cxx @@ -163,7 +163,7 @@ Vector3D & Vector3D::operator=(const Vector3D &rhs) { } Vector3D & Vector3D::operator=(const Vector2D &rhs) { - fielddatamesh = rhs.x.getMesh(); + fielddatamesh = rhs.x.getDataMesh(); x = rhs.x; y = rhs.y;